Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b75e65bcb1 | ||
|
|
8d173175eb | ||
|
|
5cbde0448e | ||
|
|
49a09fde05 | ||
|
|
f3962422c8 | ||
|
|
ee36e3c711 | ||
|
|
cca3b21d35 | ||
|
|
75c33e073e | ||
| 7b4bcc745a | |||
| 42774d44a6 |
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@@ -18,7 +19,7 @@ type InstallDisk struct {
|
||||
MountedParts []string // partition mount points currently active
|
||||
}
|
||||
|
||||
const squashfsPath = "/run/live/medium/live/filesystem.squashfs"
|
||||
const squashfsGlob = "/run/live/medium/live/*.squashfs"
|
||||
|
||||
// ListInstallDisks returns block devices suitable for installation.
|
||||
// Excludes the current live boot medium but includes USB drives.
|
||||
@@ -176,11 +177,22 @@ func inferLiveBootKind(fsType, source, deviceType, transport string) string {
|
||||
// squashfs size × 1.5 to allow for extracted filesystem and bootloader.
|
||||
// Returns 0 if the squashfs is not available (non-live environment).
|
||||
func MinInstallBytes() int64 {
|
||||
fi, err := os.Stat(squashfsPath)
|
||||
if err != nil {
|
||||
files, err := filepath.Glob(squashfsGlob)
|
||||
if err != nil || len(files) == 0 {
|
||||
return 0
|
||||
}
|
||||
return fi.Size() * 3 / 2
|
||||
var total int64
|
||||
for _, path := range files {
|
||||
fi, statErr := os.Stat(path)
|
||||
if statErr != nil {
|
||||
continue
|
||||
}
|
||||
total += fi.Size()
|
||||
}
|
||||
if total == 0 {
|
||||
return 0
|
||||
}
|
||||
return total * 3 / 2
|
||||
}
|
||||
|
||||
// toramActive returns true when the live system was booted with toram.
|
||||
@@ -222,12 +234,10 @@ func DiskWarnings(d InstallDisk) []string {
|
||||
humanBytes(min), humanBytes(d.SizeBytes)))
|
||||
}
|
||||
if toramActive() {
|
||||
sqFi, err := os.Stat(squashfsPath)
|
||||
if err == nil {
|
||||
free := freeMemBytes()
|
||||
if free > 0 && free < sqFi.Size()*2 {
|
||||
w = append(w, "toram mode — low RAM, extraction may be slow or fail")
|
||||
}
|
||||
free := freeMemBytes()
|
||||
min := MinInstallBytes()
|
||||
if free > 0 && min > 0 && free < (min*4/3) {
|
||||
w = append(w, "toram mode — low RAM, extraction may be slow or fail")
|
||||
}
|
||||
}
|
||||
return w
|
||||
|
||||
2
bible
2
bible
Submodule bible updated: 1d89a4918e...d2600f1279
Submodule internal/chart updated: ac8120c8ab...2a15bc87f1
@@ -38,7 +38,7 @@ lb config noauto \
|
||||
--memtest memtest86+ \
|
||||
--iso-volume "${LB_ISO_VOLUME}" \
|
||||
--iso-application "EASY-BEE-${BEE_GPU_VENDOR_UPPER:-NVIDIA}" \
|
||||
--bootappend-live "boot=live live-media-label=${LB_ISO_VOLUME} components video=1920x1080 console=ttyS0,115200n8 console=tty0 loglevel=3 systemd.show_status=1 username=bee user-fullname=Bee modprobe.blacklist=nouveau,snd_hda_intel,snd_hda_codec_realtek,snd_hda_codec_generic,soundcore" \
|
||||
--bootappend-live "boot=live live-media=/dev/disk/by-label/${LB_ISO_VOLUME} live-media-label=${LB_ISO_VOLUME} components video=1920x1080 console=ttyS0,115200n8 console=tty0 loglevel=3 systemd.show_status=1 username=bee user-fullname=Bee modprobe.blacklist=nouveau,snd_hda_intel,snd_hda_codec_realtek,snd_hda_codec_generic,soundcore" \
|
||||
--debootstrap-options "--include=ca-certificates" \
|
||||
--apt-recommends false \
|
||||
--chroot-squashfs-compression-type zstd \
|
||||
|
||||
@@ -516,12 +516,12 @@ validate_iso_live_boot_entries() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
grep -q 'menuentry "EASY-BEE"' "$grub_cfg" || {
|
||||
grep -q 'menuentry "EASY-BEE v' "$grub_cfg" || {
|
||||
echo "ERROR: GRUB default EASY-BEE entry is missing" >&2
|
||||
rm -f "$grub_cfg" "$isolinux_cfg"
|
||||
exit 1
|
||||
}
|
||||
grep -q 'menuentry "EASY-BEE -- load to RAM (toram)"' "$grub_cfg" || {
|
||||
grep -q 'menuentry "EASY-BEE v.* -- load to RAM (toram)"' "$grub_cfg" || {
|
||||
echo "ERROR: GRUB toram entry is missing" >&2
|
||||
rm -f "$grub_cfg" "$isolinux_cfg"
|
||||
exit 1
|
||||
@@ -562,40 +562,38 @@ validate_iso_live_boot_entries() {
|
||||
echo "=== live boot validation OK ==="
|
||||
}
|
||||
|
||||
validate_iso_grub_theme_assets() {
|
||||
validate_iso_grub_assets() {
|
||||
iso_path="$1"
|
||||
echo "=== validating GRUB theme assets in ISO ==="
|
||||
echo "=== validating GRUB assets in ISO ==="
|
||||
|
||||
[ -f "$iso_path" ] || {
|
||||
echo "ERROR: ISO not found for GRUB theme validation: $iso_path" >&2
|
||||
echo "ERROR: ISO not found for GRUB asset validation: $iso_path" >&2
|
||||
exit 1
|
||||
}
|
||||
require_iso_reader "$iso_path" >/dev/null 2>&1 || {
|
||||
echo "ERROR: ISO reader unavailable for GRUB theme validation" >&2
|
||||
echo "ERROR: ISO reader unavailable for GRUB asset validation" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
iso_files="$(mktemp)"
|
||||
iso_list_files "$iso_path" > "$iso_files" || {
|
||||
echo "ERROR: failed to list ISO files for GRUB theme validation" >&2
|
||||
echo "ERROR: failed to list ISO files for GRUB asset validation" >&2
|
||||
rm -f "$iso_files"
|
||||
exit 1
|
||||
}
|
||||
|
||||
for required in \
|
||||
boot/grub/config.cfg \
|
||||
boot/grub/theme.cfg \
|
||||
boot/grub/live-theme/theme.txt \
|
||||
boot/grub/live-theme/bee-logo.tga; do
|
||||
boot/grub/grub.cfg; do
|
||||
grep -q "^${required}$" "$iso_files" || {
|
||||
echo "ERROR: missing GRUB theme asset in ISO: ${required}" >&2
|
||||
echo "ERROR: missing GRUB asset in ISO: ${required}" >&2
|
||||
rm -f "$iso_files"
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
rm -f "$iso_files"
|
||||
echo "=== GRUB theme validation OK ==="
|
||||
echo "=== GRUB asset validation OK ==="
|
||||
}
|
||||
|
||||
validate_iso_nvidia_runtime() {
|
||||
@@ -610,29 +608,37 @@ validate_iso_nvidia_runtime() {
|
||||
|
||||
squashfs_tmp="$(mktemp)"
|
||||
squashfs_list="$(mktemp)"
|
||||
iso_read_member "$iso_path" live/filesystem.squashfs "$squashfs_tmp" || {
|
||||
rm -f "$squashfs_tmp" "$squashfs_list"
|
||||
nvidia_runtime_fail "failed to extract live/filesystem.squashfs from ISO"
|
||||
}
|
||||
unsquashfs -ll "$squashfs_tmp" > "$squashfs_list" 2>/dev/null || {
|
||||
rm -f "$squashfs_tmp" "$squashfs_list"
|
||||
nvidia_runtime_fail "failed to inspect filesystem.squashfs from ISO"
|
||||
iso_files="$(mktemp)"
|
||||
iso_list_files "$iso_path" > "$iso_files" || {
|
||||
rm -f "$squashfs_tmp" "$squashfs_list" "$iso_files"
|
||||
nvidia_runtime_fail "failed to list ISO files for NVIDIA runtime validation"
|
||||
}
|
||||
grep '^live/.*\.squashfs$' "$iso_files" | while IFS= read -r squashfs_member; do
|
||||
iso_read_member "$iso_path" "$squashfs_member" "$squashfs_tmp" || {
|
||||
rm -f "$squashfs_tmp" "$squashfs_list" "$iso_files"
|
||||
nvidia_runtime_fail "failed to extract $squashfs_member from ISO"
|
||||
}
|
||||
unsquashfs -ll "$squashfs_tmp" >> "$squashfs_list" 2>/dev/null || {
|
||||
rm -f "$squashfs_tmp" "$squashfs_list" "$iso_files"
|
||||
nvidia_runtime_fail "failed to inspect $squashfs_member from ISO"
|
||||
}
|
||||
: > "$squashfs_tmp"
|
||||
done
|
||||
|
||||
grep -Eq 'usr/bin/dcgmi$' "$squashfs_list" || {
|
||||
rm -f "$squashfs_tmp" "$squashfs_list"
|
||||
rm -f "$squashfs_tmp" "$squashfs_list" "$iso_files"
|
||||
nvidia_runtime_fail "dcgmi missing from final NVIDIA ISO"
|
||||
}
|
||||
grep -Eq 'usr/bin/nv-hostengine$' "$squashfs_list" || {
|
||||
rm -f "$squashfs_tmp" "$squashfs_list"
|
||||
rm -f "$squashfs_tmp" "$squashfs_list" "$iso_files"
|
||||
nvidia_runtime_fail "nv-hostengine missing from final NVIDIA ISO"
|
||||
}
|
||||
grep -Eq 'usr/bin/dcgmproftester([0-9]+)?$' "$squashfs_list" || {
|
||||
rm -f "$squashfs_tmp" "$squashfs_list"
|
||||
rm -f "$squashfs_tmp" "$squashfs_list" "$iso_files"
|
||||
nvidia_runtime_fail "dcgmproftester missing from final NVIDIA ISO"
|
||||
}
|
||||
|
||||
rm -f "$squashfs_tmp" "$squashfs_list"
|
||||
rm -f "$squashfs_tmp" "$squashfs_list" "$iso_files"
|
||||
echo "=== NVIDIA runtime validation OK ==="
|
||||
}
|
||||
|
||||
@@ -674,6 +680,184 @@ label memtest
|
||||
EOF
|
||||
}
|
||||
|
||||
extract_live_grub_entry() {
|
||||
cfg="$1"
|
||||
live_linux="$(awk '/^[[:space:]]*linux[[:space:]]+\/live\// { print; exit }' "$cfg")"
|
||||
live_initrd="$(awk '/^[[:space:]]*initrd[[:space:]]+\/live\// { print; exit }' "$cfg")"
|
||||
[ -n "$live_linux" ] || return 1
|
||||
[ -n "$live_initrd" ] || return 1
|
||||
|
||||
grub_kernel="$(printf '%s\n' "$live_linux" | awk '{print $2}')"
|
||||
grub_append="$(printf '%s\n' "$live_linux" | cut -d' ' -f3-)"
|
||||
grub_initrd="$(printf '%s\n' "$live_initrd" | awk '{print $2}')"
|
||||
[ -n "$grub_kernel" ] || return 1
|
||||
[ -n "$grub_append" ] || return 1
|
||||
[ -n "$grub_initrd" ] || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
load_live_build_append() {
|
||||
lb_dir="$1"
|
||||
binary_cfg="$lb_dir/config/binary"
|
||||
[ -f "$binary_cfg" ] || return 1
|
||||
|
||||
# config/binary is generated by live-build and contains shell variable
|
||||
# assignments such as LB_BOOTAPPEND_LIVE="boot=live ...".
|
||||
# shellcheck disable=SC1090
|
||||
. "$binary_cfg"
|
||||
|
||||
[ -n "${LB_BOOTAPPEND_LIVE:-}" ] || return 1
|
||||
live_build_append="$LB_BOOTAPPEND_LIVE"
|
||||
return 0
|
||||
}
|
||||
|
||||
extract_live_isolinux_entry() {
|
||||
cfg="$1"
|
||||
isolinux_linux="$(awk '/^[[:space:]]*linux[[:space:]]+\/live\// { print; exit }' "$cfg")"
|
||||
isolinux_initrd="$(awk '/^[[:space:]]*initrd[[:space:]]+\/live\// { print; exit }' "$cfg")"
|
||||
isolinux_append="$(awk '/^[[:space:]]*append[[:space:]]+/ { sub(/^[[:space:]]*append[[:space:]]+/, ""); print; exit }' "$cfg")"
|
||||
[ -n "$isolinux_linux" ] || return 1
|
||||
[ -n "$isolinux_initrd" ] || return 1
|
||||
[ -n "$isolinux_append" ] || return 1
|
||||
|
||||
isolinux_kernel="$(printf '%s\n' "$isolinux_linux" | awk '{print $2}')"
|
||||
isolinux_initrd_path="$(printf '%s\n' "$isolinux_initrd" | awk '{print $2}')"
|
||||
[ -n "$isolinux_kernel" ] || return 1
|
||||
[ -n "$isolinux_initrd_path" ] || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
write_canonical_grub_cfg() {
|
||||
cfg="$1"
|
||||
kernel="$2"
|
||||
append_live="$3"
|
||||
initrd="$4"
|
||||
version_label="${PROJECT_VERSION_EFFECTIVE}"
|
||||
|
||||
cat > "$cfg" <<EOF
|
||||
source /boot/grub/config.cfg
|
||||
|
||||
menuentry "EASY-BEE v${version_label}" {
|
||||
linux ${kernel} ${append_live} nomodeset bee.nvidia.mode=normal pci=realloc net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
initrd ${initrd}
|
||||
}
|
||||
|
||||
menuentry "EASY-BEE v${version_label} -- load to RAM (toram)" {
|
||||
linux ${kernel} ${append_live} toram nomodeset bee.nvidia.mode=normal pci=realloc net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
initrd ${initrd}
|
||||
}
|
||||
|
||||
menuentry "EASY-BEE v${version_label} -- no GUI / no X11" {
|
||||
linux ${kernel} ${append_live} nomodeset bee.gui=off bee.nvidia.mode=gsp-off pci=realloc net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
initrd ${initrd}
|
||||
}
|
||||
|
||||
if [ "\${grub_platform}" = "efi" ]; then
|
||||
menuentry "Memory Test (memtest86+)" {
|
||||
chainloader /boot/memtest86+x64.efi
|
||||
}
|
||||
else
|
||||
menuentry "Memory Test (memtest86+)" {
|
||||
linux16 /boot/memtest86+x64.bin
|
||||
}
|
||||
fi
|
||||
|
||||
if [ "\${grub_platform}" = "efi" ]; then
|
||||
menuentry "UEFI Firmware Settings" {
|
||||
fwsetup
|
||||
}
|
||||
fi
|
||||
EOF
|
||||
}
|
||||
|
||||
write_canonical_isolinux_cfg() {
|
||||
cfg="$1"
|
||||
kernel="$2"
|
||||
initrd="$3"
|
||||
append_live="$4"
|
||||
version_label="${PROJECT_VERSION_EFFECTIVE}"
|
||||
|
||||
cat > "$cfg" <<EOF
|
||||
label live-@FLAVOUR@-normal
|
||||
menu label ^EASY-BEE v${version_label}
|
||||
linux ${kernel}
|
||||
initrd ${initrd}
|
||||
append ${append_live} nomodeset bee.nvidia.mode=normal net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
|
||||
label live-@FLAVOUR@-toram
|
||||
menu label EASY-BEE v${version_label} (^load to RAM)
|
||||
menu default
|
||||
linux ${kernel}
|
||||
initrd ${initrd}
|
||||
append ${append_live} toram nomodeset bee.nvidia.mode=normal net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
|
||||
label live-@FLAVOUR@-console
|
||||
menu label EASY-BEE v${version_label} (^no GUI / no X11)
|
||||
linux ${kernel}
|
||||
initrd ${initrd}
|
||||
append ${append_live} nomodeset bee.gui=off bee.nvidia.mode=gsp-off net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
|
||||
label live-@FLAVOUR@-gsp-off
|
||||
menu label EASY-BEE (^NVIDIA GSP=off)
|
||||
linux ${kernel}
|
||||
initrd ${initrd}
|
||||
append ${append_live} nomodeset bee.nvidia.mode=gsp-off net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
|
||||
label live-@FLAVOUR@-kms
|
||||
menu label EASY-BEE (^KMS, no nomodeset)
|
||||
linux ${kernel}
|
||||
initrd ${initrd}
|
||||
append ${append_live} bee.nvidia.mode=normal net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
|
||||
label live-@FLAVOUR@-kms-gsp-off
|
||||
menu label EASY-BEE (KMS, ^GSP=off)
|
||||
linux ${kernel}
|
||||
initrd ${initrd}
|
||||
append ${append_live} bee.nvidia.mode=gsp-off net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
|
||||
label live-@FLAVOUR@-failsafe
|
||||
menu label EASY-BEE (^fail-safe)
|
||||
linux ${kernel}
|
||||
initrd ${initrd}
|
||||
append ${append_live} nomodeset bee.nvidia.mode=gsp-off noapic noapm nodma nomce nolapic nosmp vga=normal net.ifnames=0 biosdevname=0
|
||||
|
||||
label memtest
|
||||
menu label ^Memory Test (memtest86+)
|
||||
linux /boot/memtest86+x64.bin
|
||||
EOF
|
||||
}
|
||||
|
||||
enforce_live_build_bootloader_assets() {
|
||||
lb_dir="$1"
|
||||
grub_cfg="$lb_dir/binary/boot/grub/grub.cfg"
|
||||
grub_dir="$lb_dir/binary/boot/grub"
|
||||
isolinux_cfg="$lb_dir/binary/isolinux/live.cfg"
|
||||
|
||||
if ! load_live_build_append "$lb_dir"; then
|
||||
echo "bootloader sync: WARNING: could not load LB_BOOTAPPEND_LIVE from $lb_dir/config/binary" >&2
|
||||
live_build_append=""
|
||||
fi
|
||||
|
||||
if [ -f "$grub_cfg" ]; then
|
||||
if extract_live_grub_entry "$grub_cfg"; then
|
||||
cp "${BUILDER_DIR}/config/bootloaders/grub-efi/config.cfg" "$grub_dir/config.cfg"
|
||||
write_canonical_grub_cfg "$grub_cfg" "$grub_kernel" "${live_build_append:-$grub_append}" "$grub_initrd"
|
||||
echo "bootloader sync: rewrote binary/boot/grub/grub.cfg with canonical EASY-BEE menu"
|
||||
else
|
||||
echo "bootloader sync: WARNING: could not extract live entry from $grub_cfg" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "$isolinux_cfg" ]; then
|
||||
if extract_live_isolinux_entry "$isolinux_cfg"; then
|
||||
write_canonical_isolinux_cfg "$isolinux_cfg" "$isolinux_kernel" "$isolinux_initrd_path" "${live_build_append:-$isolinux_append}"
|
||||
echo "bootloader sync: rewrote binary/isolinux/live.cfg with canonical EASY-BEE menu"
|
||||
else
|
||||
echo "bootloader sync: WARNING: could not extract live entry from $isolinux_cfg" >&2
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
copy_memtest_from_deb() {
|
||||
deb="$1"
|
||||
dst_boot="$2"
|
||||
@@ -710,8 +894,11 @@ FULL_BUILD_MARKER="${BUILD_WORK_DIR}/.bee-full-build-marker"
|
||||
# hooks, archives, Dockerfile, auto/config) require a full lb build.
|
||||
needs_full_build() {
|
||||
[ -f "${FULL_BUILD_MARKER}" ] || return 0
|
||||
[ -f "${BUILD_WORK_DIR}/binary/live/filesystem.squashfs" ] || return 0
|
||||
[ -f "${BUILD_WORK_DIR}/live-image-amd64.hybrid.iso" ] || return 0
|
||||
# Accept any versioned squashfs (filesystem-v*.squashfs or legacy filesystem.squashfs)
|
||||
_any_sq=$(find "${BUILD_WORK_DIR}/binary/live" -maxdepth 1 \
|
||||
-name 'filesystem*.squashfs' 2>/dev/null | head -1)
|
||||
[ -n "$_any_sq" ] || return 0
|
||||
|
||||
_heavy=$(find \
|
||||
"${BUILDER_DIR}/VERSIONS" \
|
||||
@@ -734,40 +921,109 @@ needs_full_build() {
|
||||
# Fast-path: unsquash existing filesystem, rsync overlay on top, repack.
|
||||
# Requires ~10 GB free in BEE_CACHE_DIR for the unpacked squashfs.
|
||||
fast_path_repack_squashfs() {
|
||||
_sq="${BUILD_WORK_DIR}/binary/live/filesystem.squashfs"
|
||||
_old_sq=$(find "${BUILD_WORK_DIR}/binary/live" -maxdepth 1 \
|
||||
-name 'filesystem*.squashfs' | sort | head -1)
|
||||
_sq="${BUILD_WORK_DIR}/binary/live/${SQUASHFS_FILENAME}"
|
||||
_tmp="${BEE_CACHE_DIR}/fast-unsquash-${BUILD_VARIANT}"
|
||||
echo "=== fast-path: unsquash ($(du -sh "$_sq" | cut -f1) compressed) ==="
|
||||
echo "=== fast-path: unsquash $(basename "$_old_sq") ($(du -sh "$_old_sq" | cut -f1) compressed) ==="
|
||||
rm -rf "$_tmp"
|
||||
unsquashfs -d "$_tmp" "$_sq"
|
||||
unsquashfs -d "$_tmp" "$_old_sq"
|
||||
echo "=== fast-path: syncing overlay stage ==="
|
||||
rsync -a --checksum "${OVERLAY_STAGE_DIR}/" "$_tmp/"
|
||||
echo "=== fast-path: repacking squashfs ==="
|
||||
echo "=== fast-path: repacking as ${SQUASHFS_FILENAME} ==="
|
||||
_sq_new="${_sq}.new"
|
||||
rm -f "$_sq_new"
|
||||
mksquashfs "$_tmp" "$_sq_new" -comp zstd -b 1048576 -noappend -no-progress
|
||||
mksquashfs "$_tmp" "$_sq_new" -comp zstd -b 1048576 -noappend -no-progress -no-xattrs
|
||||
mv "$_sq_new" "$_sq"
|
||||
rm -rf "$_tmp"
|
||||
[ "$_old_sq" != "$_sq" ] && rm -f "$_old_sq"
|
||||
echo "=== fast-path: squashfs repacked ($(du -sh "$_sq" | cut -f1)) ==="
|
||||
}
|
||||
|
||||
# Fast-path: rebuild ISO by replacing only live/filesystem.squashfs via xorriso.
|
||||
# Fast-path: rebuild ISO replacing the squashfs via xorriso.
|
||||
# Boot structure (El Torito, EFI, MBR hybrid) is replayed from the prior ISO.
|
||||
fast_path_rebuild_iso() {
|
||||
_sq="${BUILD_WORK_DIR}/binary/live/filesystem.squashfs"
|
||||
_sq="${BUILD_WORK_DIR}/binary/live/${SQUASHFS_FILENAME}"
|
||||
_prior="${BUILD_WORK_DIR}/live-image-amd64.hybrid.iso"
|
||||
_new="${BUILD_WORK_DIR}/live-image-amd64.hybrid.iso.new"
|
||||
echo "=== fast-path: rebuilding ISO with xorriso ==="
|
||||
rm -f "$_new"
|
||||
# Remove any old squashfs entries from the prior ISO before adding the new one
|
||||
_old_entries=$(xorriso -indev "$_prior" -find /live -name 'filesystem*.squashfs' -- 2>/dev/null \
|
||||
| grep -E '^/live/filesystem.*\.squashfs$' || true)
|
||||
_rm_args=""
|
||||
for _e in $_old_entries; do
|
||||
_rm_args="$_rm_args -rm $_e --"
|
||||
done
|
||||
# shellcheck disable=SC2086
|
||||
xorriso \
|
||||
-indev "$_prior" \
|
||||
-outdev "$_new" \
|
||||
-map "$_sq" /live/filesystem.squashfs \
|
||||
${_rm_args} \
|
||||
-map "$_sq" /live/${SQUASHFS_FILENAME} \
|
||||
-boot_image any replay \
|
||||
-commit
|
||||
mv "$_new" "$_prior"
|
||||
echo "=== fast-path: ISO rebuilt ==="
|
||||
}
|
||||
|
||||
dir_has_entries() {
|
||||
_dir="$1"
|
||||
[ -d "$_dir" ] || return 1
|
||||
find "$_dir" -mindepth 1 -print -quit 2>/dev/null | grep -q .
|
||||
}
|
||||
|
||||
move_tree_to_layer() {
|
||||
_src_root="$1"
|
||||
_rel="$2"
|
||||
_dst_root="$3"
|
||||
[ -e "${_src_root}/${_rel}" ] || return 0
|
||||
mkdir -p "${_dst_root}/$(dirname "$_rel")"
|
||||
mv "${_src_root}/${_rel}" "${_dst_root}/${_rel}"
|
||||
}
|
||||
|
||||
split_live_squashfs_layers() {
|
||||
lb_dir="$1"
|
||||
live_dir="${lb_dir}/binary/live"
|
||||
base_sq="${live_dir}/filesystem.squashfs"
|
||||
usr_sq="${live_dir}/10-usr.squashfs"
|
||||
fw_sq="${live_dir}/20-firmware.squashfs"
|
||||
|
||||
[ -f "$base_sq" ] || return 0
|
||||
command -v unsquashfs >/dev/null 2>&1 || return 0
|
||||
command -v mksquashfs >/dev/null 2>&1 || return 0
|
||||
|
||||
tmp_root="$(mktemp -d)"
|
||||
tmp_usr="$(mktemp -d)"
|
||||
tmp_fw="$(mktemp -d)"
|
||||
|
||||
echo "=== splitting live squashfs into smaller layers ==="
|
||||
unsquashfs -d "$tmp_root/root" "$base_sq" >/dev/null
|
||||
mkdir -p "$tmp_usr/root" "$tmp_fw/root"
|
||||
|
||||
move_tree_to_layer "$tmp_root/root" "usr" "$tmp_usr/root"
|
||||
move_tree_to_layer "$tmp_root/root" "lib/firmware" "$tmp_fw/root"
|
||||
move_tree_to_layer "$tmp_root/root" "usr/lib/firmware" "$tmp_fw/root"
|
||||
move_tree_to_layer "$tmp_root/root" "boot/firmware" "$tmp_fw/root"
|
||||
|
||||
rm -f "$usr_sq" "$fw_sq"
|
||||
mksquashfs "$tmp_root/root" "${base_sq}.new" -comp zstd -b 1048576 -noappend -no-progress -no-xattrs >/dev/null
|
||||
mv "${base_sq}.new" "$base_sq"
|
||||
|
||||
if dir_has_entries "$tmp_usr/root"; then
|
||||
mksquashfs "$tmp_usr/root" "${usr_sq}.new" -comp zstd -b 1048576 -noappend -no-progress -no-xattrs >/dev/null
|
||||
mv "${usr_sq}.new" "$usr_sq"
|
||||
fi
|
||||
if dir_has_entries "$tmp_fw/root"; then
|
||||
mksquashfs "$tmp_fw/root" "${fw_sq}.new" -comp zstd -b 1048576 -noappend -no-progress -no-xattrs >/dev/null
|
||||
mv "${fw_sq}.new" "$fw_sq"
|
||||
fi
|
||||
|
||||
echo "=== live squashfs layers ==="
|
||||
find "$live_dir" -maxdepth 1 -type f -name '*.squashfs' -exec du -sh {} \; | sort
|
||||
rm -rf "$tmp_root" "$tmp_usr" "$tmp_fw"
|
||||
}
|
||||
|
||||
recover_iso_memtest() {
|
||||
lb_dir="$1"
|
||||
iso_path="$2"
|
||||
@@ -846,6 +1102,7 @@ recover_iso_memtest() {
|
||||
}
|
||||
|
||||
PROJECT_VERSION_EFFECTIVE="$(resolve_project_version)"
|
||||
SQUASHFS_FILENAME="filesystem-v${PROJECT_VERSION_EFFECTIVE}.squashfs"
|
||||
ISO_BASENAME="easy-bee-${BUILD_VARIANT}-v${PROJECT_VERSION_EFFECTIVE}-amd64"
|
||||
# Versioned output directory: dist/easy-bee-v4.1/ — all final artefacts live here.
|
||||
OUT_DIR="${DIST_DIR}/easy-bee-v${PROJECT_VERSION_EFFECTIVE}"
|
||||
@@ -1416,7 +1673,7 @@ if ! needs_full_build; then
|
||||
fast_path_rebuild_iso
|
||||
ISO_RAW="${LB_DIR}/live-image-amd64.hybrid.iso"
|
||||
validate_iso_live_boot_entries "$ISO_RAW"
|
||||
validate_iso_grub_theme_assets "$ISO_RAW"
|
||||
validate_iso_grub_assets "$ISO_RAW"
|
||||
validate_iso_nvidia_runtime "$ISO_RAW"
|
||||
cp "$ISO_RAW" "$ISO_OUT"
|
||||
echo ""
|
||||
@@ -1438,7 +1695,24 @@ cd "${LB_DIR}"
|
||||
run_step_sh "live-build clean" "80-lb-clean" "lb clean --all 2>&1 | tail -3"
|
||||
run_step_sh "live-build config" "81-lb-config" "lb config 2>&1 | tail -5"
|
||||
dump_memtest_debug "pre-build" "${LB_DIR}"
|
||||
export MKSQUASHFS_OPTIONS="-no-xattrs"
|
||||
run_step_sh "live-build build" "90-lb-build" "lb build 2>&1"
|
||||
echo "=== enforcing canonical bootloader assets ==="
|
||||
enforce_live_build_bootloader_assets "${LB_DIR}"
|
||||
# Rename lb's default filesystem.squashfs to the versioned filename so the
|
||||
# ISO contains a version-stamped squashfs (e.g. filesystem-v10.15.squashfs).
|
||||
_std_sq="${LB_DIR}/binary/live/filesystem.squashfs"
|
||||
_ver_sq="${LB_DIR}/binary/live/${SQUASHFS_FILENAME}"
|
||||
if [ -f "${_std_sq}" ] && [ "${_std_sq}" != "${_ver_sq}" ]; then
|
||||
mv "${_std_sq}" "${_ver_sq}"
|
||||
echo "=== squashfs renamed: filesystem.squashfs → ${SQUASHFS_FILENAME} ==="
|
||||
fi
|
||||
reset_live_build_stage "${LB_DIR}" "binary_checksums"
|
||||
reset_live_build_stage "${LB_DIR}" "binary_iso"
|
||||
reset_live_build_stage "${LB_DIR}" "binary_zsync"
|
||||
run_step_sh "rebuild live-build checksums after bootloader sync" "91b-lb-checksums" "lb binary_checksums 2>&1"
|
||||
run_step_sh "rebuild ISO after bootloader sync" "91c-lb-binary-iso" "lb binary_iso 2>&1"
|
||||
run_step_sh "rebuild zsync after bootloader sync" "91d-lb-zsync" "lb binary_zsync 2>&1"
|
||||
|
||||
# --- persist deb package cache back to shared location ---
|
||||
# This allows the second variant to reuse all downloaded packages.
|
||||
@@ -1464,7 +1738,7 @@ if [ -f "$ISO_RAW" ]; then
|
||||
fi
|
||||
validate_iso_memtest "$ISO_RAW"
|
||||
validate_iso_live_boot_entries "$ISO_RAW"
|
||||
validate_iso_grub_theme_assets "$ISO_RAW"
|
||||
validate_iso_grub_assets "$ISO_RAW"
|
||||
validate_iso_nvidia_runtime "$ISO_RAW"
|
||||
cp "$ISO_RAW" "$ISO_OUT"
|
||||
touch "${FULL_BUILD_MARKER}"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
set default=1
|
||||
set timeout=10
|
||||
set color_normal=yellow/black
|
||||
set color_highlight=white/brown
|
||||
|
||||
if [ x$feature_default_font_path = xy ] ; then
|
||||
font=unicode
|
||||
@@ -26,6 +28,3 @@ insmod gfxterm
|
||||
|
||||
terminal_input console serial
|
||||
terminal_output gfxterm serial
|
||||
|
||||
insmod tga
|
||||
source /boot/grub/theme.cfg
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
source /boot/grub/config.cfg
|
||||
|
||||
menuentry "EASY-BEE" {
|
||||
menuentry "EASY-BEE v@VERSION@" {
|
||||
linux @KERNEL_LIVE@ @APPEND_LIVE@ nomodeset bee.nvidia.mode=normal pci=realloc net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
initrd @INITRD_LIVE@
|
||||
}
|
||||
|
||||
menuentry "EASY-BEE -- load to RAM (toram)" {
|
||||
menuentry "EASY-BEE v@VERSION@ -- load to RAM (toram)" {
|
||||
linux @KERNEL_LIVE@ @APPEND_LIVE@ toram nomodeset bee.nvidia.mode=normal pci=realloc net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
initrd @INITRD_LIVE@
|
||||
}
|
||||
|
||||
menuentry "EASY-BEE -- no GUI / no X11" {
|
||||
menuentry "EASY-BEE v@VERSION@ -- no GUI / no X11" {
|
||||
linux @KERNEL_LIVE@ @APPEND_LIVE@ nomodeset bee.gui=off bee.nvidia.mode=gsp-off pci=realloc net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
initrd @INITRD_LIVE@
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
label live-@FLAVOUR@-normal
|
||||
menu label ^EASY-BEE
|
||||
menu label ^EASY-BEE v@VERSION@
|
||||
linux @LINUX@
|
||||
initrd @INITRD@
|
||||
append @APPEND_LIVE@ nomodeset bee.nvidia.mode=normal net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
|
||||
label live-@FLAVOUR@-toram
|
||||
menu label EASY-BEE (^load to RAM)
|
||||
menu label EASY-BEE v@VERSION@ (^load to RAM)
|
||||
menu default
|
||||
linux @LINUX@
|
||||
initrd @INITRD@
|
||||
append @APPEND_LIVE@ toram nomodeset bee.nvidia.mode=normal net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
|
||||
label live-@FLAVOUR@-console
|
||||
menu label EASY-BEE (^no GUI / no X11)
|
||||
menu label EASY-BEE v@VERSION@ (^no GUI / no X11)
|
||||
linux @LINUX@
|
||||
initrd @INITRD@
|
||||
append @APPEND_LIVE@ nomodeset bee.gui=off bee.nvidia.mode=gsp-off net.ifnames=0 biosdevname=0 mitigations=off transparent_hugepage=always numa_balancing=disable pcie_aspm=off intel_idle.max_cstate=1 processor.max_cstate=1 nowatchdog nosoftlockup
|
||||
|
||||
37
iso/builder/config/hooks/normal/9998-strip-xattrs.hook.chroot
Executable file
37
iso/builder/config/hooks/normal/9998-strip-xattrs.hook.chroot
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python3
|
||||
# 9998-strip-xattrs.hook.chroot
|
||||
#
|
||||
# mksquashfs 4.5.1 (Debian bookworm) writes a non-INVALID xattr_id_table_start
|
||||
# even with -no-xattrs when the source tree contains POSIX ACL xattrs set by
|
||||
# dpkg/install-time. Linux 6.1 squashfs driver then fails with
|
||||
# "unable to read xattr id index table" and aborts the mount.
|
||||
#
|
||||
# Strip all xattrs from the live chroot before mksquashfs sees the tree so the
|
||||
# resulting squashfs has SQUASHFS_INVALID_BLK in xattr_id_table_start.
|
||||
|
||||
import os
|
||||
|
||||
def strip(path):
|
||||
try:
|
||||
for attr in os.listxattr(path, follow_symlinks=False):
|
||||
try:
|
||||
os.removexattr(path, attr, follow_symlinks=False)
|
||||
except OSError:
|
||||
pass
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
removed = 0
|
||||
for root, dirs, files in os.walk('/', topdown=True, followlinks=False):
|
||||
for name in dirs + files:
|
||||
p = os.path.join(root, name)
|
||||
try:
|
||||
attrs = os.listxattr(p, follow_symlinks=False)
|
||||
if attrs:
|
||||
strip(p)
|
||||
removed += len(attrs)
|
||||
except OSError:
|
||||
pass
|
||||
strip(root)
|
||||
|
||||
print(f"9998-strip-xattrs: removed xattrs from {removed} entries")
|
||||
@@ -8,7 +8,7 @@
|
||||
# Layout (UEFI): GPT, /dev/sdX1=EFI 512MB vfat, /dev/sdX2=root ext4
|
||||
# Layout (BIOS): MBR, /dev/sdX1=root ext4
|
||||
#
|
||||
# Squashfs source: /run/live/medium/live/filesystem.squashfs
|
||||
# Squashfs sources: /run/live/medium/live/*.squashfs
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -62,9 +62,9 @@ for tool in parted mkfs.vfat mkfs.ext4 unsquashfs grub-install update-grub; do
|
||||
fi
|
||||
done
|
||||
|
||||
SQUASHFS="/run/live/medium/live/filesystem.squashfs"
|
||||
if [ ! -f "$SQUASHFS" ]; then
|
||||
echo "ERROR: squashfs not found at $SQUASHFS" >&2
|
||||
mapfile -t SQUASHFS_FILES < <(find /run/live/medium/live -maxdepth 1 -type f -name '*.squashfs' | sort)
|
||||
if [ "${#SQUASHFS_FILES[@]}" -eq 0 ]; then
|
||||
echo "ERROR: no squashfs files found under /run/live/medium/live" >&2
|
||||
echo " The live medium may have been disconnected." >&2
|
||||
echo " Reconnect the disc and run: bee-remount-medium --wait" >&2
|
||||
echo " Then re-run bee-install." >&2
|
||||
@@ -106,7 +106,10 @@ log "=== BEE DISK INSTALLER ==="
|
||||
log "Target device : $DEVICE"
|
||||
log "Root partition: $PART_ROOT"
|
||||
[ "$UEFI" = "1" ] && log "EFI partition : $PART_EFI"
|
||||
log "Squashfs : $SQUASHFS ($(du -sh "$SQUASHFS" | cut -f1))"
|
||||
log "Squashfs : ${#SQUASHFS_FILES[@]} layer(s)"
|
||||
for sf in "${SQUASHFS_FILES[@]}"; do
|
||||
log " - $sf ($(du -sh "$sf" | cut -f1))"
|
||||
done
|
||||
log "Log : $LOGFILE"
|
||||
log ""
|
||||
|
||||
@@ -163,7 +166,9 @@ log " Mounted."
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
log "--- Step 5/7: Unpacking filesystem (this takes 10-20 minutes) ---"
|
||||
log " Source: $SQUASHFS"
|
||||
for sf in "${SQUASHFS_FILES[@]}"; do
|
||||
log " Source: $sf"
|
||||
done
|
||||
log " Target: $MOUNT_ROOT"
|
||||
|
||||
# unsquashfs does not support resume, so retry the entire unpack step if the
|
||||
@@ -177,9 +182,9 @@ while true; do
|
||||
fi
|
||||
[ "$UNPACK_ATTEMPTS" -gt 1 ] && log " Retry attempt $UNPACK_ATTEMPTS / $UNPACK_MAX ..."
|
||||
|
||||
# Re-check squashfs is reachable before each attempt
|
||||
if [ ! -f "$SQUASHFS" ]; then
|
||||
log " SOURCE LOST: $SQUASHFS not found."
|
||||
mapfile -t SQUASHFS_FILES < <(find /run/live/medium/live -maxdepth 1 -type f -name '*.squashfs' | sort)
|
||||
if [ "${#SQUASHFS_FILES[@]}" -eq 0 ]; then
|
||||
log " SOURCE LOST: no squashfs files found under /run/live/medium/live."
|
||||
log " Reconnect the disc and run 'bee-remount-medium --wait' in another terminal,"
|
||||
log " then press Enter here to retry."
|
||||
read -r _
|
||||
@@ -194,12 +199,17 @@ while true; do
|
||||
fi
|
||||
|
||||
UNPACK_OK=0
|
||||
unsquashfs -f -d "$MOUNT_ROOT" "$SQUASHFS" 2>&1 | \
|
||||
grep -E '^\[|^inod|^created|^extract|^ERROR|failed' | \
|
||||
while IFS= read -r line; do log " $line"; done || UNPACK_OK=$?
|
||||
for sf in "${SQUASHFS_FILES[@]}"; do
|
||||
log " Unpacking $(basename "$sf") ..."
|
||||
unsquashfs -f -d "$MOUNT_ROOT" "$sf" 2>&1 | \
|
||||
grep -E '^\[|^inod|^created|^extract|^ERROR|failed' | \
|
||||
while IFS= read -r line; do log " $line"; done || UNPACK_OK=$?
|
||||
[ "$UNPACK_OK" -eq 0 ] || break
|
||||
done
|
||||
|
||||
# Check squashfs is still reachable (gone = disc pulled during copy)
|
||||
if [ ! -f "$SQUASHFS" ]; then
|
||||
mapfile -t SQUASHFS_FILES < <(find /run/live/medium/live -maxdepth 1 -type f -name '*.squashfs' | sort)
|
||||
if [ "${#SQUASHFS_FILES[@]}" -eq 0 ]; then
|
||||
log " WARNING: source medium lost during unpack — will retry after remount."
|
||||
log " Run 'bee-remount-medium --wait' in another terminal, then press Enter."
|
||||
read -r _
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# bee-remount-medium — find and remount the live ISO medium to /run/live/medium
|
||||
#
|
||||
# Run this after reconnecting the ISO source disc (USB/CD) if the live medium
|
||||
# was lost and /run/live/medium/live/filesystem.squashfs is missing.
|
||||
# was lost and /run/live/medium/live/*.squashfs are missing.
|
||||
#
|
||||
# Usage: bee-remount-medium [--wait]
|
||||
# --wait keep retrying every 5 seconds until the medium is found (useful
|
||||
@@ -11,7 +11,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
MEDIUM_DIR="/run/live/medium"
|
||||
SQUASHFS_REL="live/filesystem.squashfs"
|
||||
SQUASHFS_GLOB="live/*.squashfs"
|
||||
WAIT_MODE=0
|
||||
|
||||
for arg in "$@"; do
|
||||
@@ -56,7 +56,7 @@ try_mount() {
|
||||
local tmpdir
|
||||
tmpdir=$(mktemp -d /tmp/bee-probe-XXXXXX)
|
||||
if mount -o ro "$dev" "$tmpdir" 2>/dev/null; then
|
||||
if [ -f "${tmpdir}/${SQUASHFS_REL}" ]; then
|
||||
if find "${tmpdir}/live" -maxdepth 1 -type f -name '*.squashfs' 2>/dev/null | grep -q .; then
|
||||
# Unmount probe mount and mount properly onto live path
|
||||
umount "$tmpdir" 2>/dev/null || true
|
||||
rmdir "$tmpdir" 2>/dev/null || true
|
||||
@@ -82,8 +82,9 @@ attempt() {
|
||||
for dev in $(find_candidates); do
|
||||
log " Trying $dev ..."
|
||||
if try_mount "$dev"; then
|
||||
local sq="${MEDIUM_DIR}/${SQUASHFS_REL}"
|
||||
log "SUCCESS: squashfs available at $sq ($(du -sh "$sq" | cut -f1))"
|
||||
local count
|
||||
count=$(find "${MEDIUM_DIR}/live" -maxdepth 1 -type f -name '*.squashfs' 2>/dev/null | wc -l | tr -d ' ')
|
||||
log "SUCCESS: ${count} squashfs layer(s) available under ${MEDIUM_DIR}/live"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
@@ -100,5 +101,5 @@ if [ "$WAIT_MODE" = "1" ]; then
|
||||
sleep 5
|
||||
done
|
||||
else
|
||||
attempt || die "No ISO medium with ${SQUASHFS_REL} found. Reconnect the disc and re-run, or use --wait."
|
||||
attempt || die "No ISO medium with ${SQUASHFS_GLOB} found. Reconnect the disc and re-run, or use --wait."
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user