From 9c460747707348ecd7fc076f30838ec6937aa8e4 Mon Sep 17 00:00:00 2001 From: Jeffrey Alan Scudder Date: Sun, 29 Mar 2026 13:34:11 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20universal=20boot=20=E2=80=94=20one=20US?= =?UTF-8?q?B=20image=20works=20on=20both=20Macs=20and=20ThinkPads?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Oven build now produces vmlinuz-slim (no embedded initramfs) + separate initramfs.cpio.gz alongside the full vmlinuz. Flash script auto-detects: if slim kernel exists, uses splash → systemd-boot → slim kernel chain (works on Mac EFI). Otherwise falls back to chainloader (ThinkPad). Co-Authored-By: Claude Opus 4.6 (1M context) --- fedac/native/Dockerfile.flash-helper | 1 + fedac/native/docker-build.sh | 23 ++++++++++++ fedac/native/scripts/flash-helper-runner.sh | 40 +++++++++++++-------- fedac/native/scripts/media-layout.sh | 12 ++++--- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/fedac/native/Dockerfile.flash-helper b/fedac/native/Dockerfile.flash-helper index 9d8ca21058..3b71c439bb 100644 --- a/fedac/native/Dockerfile.flash-helper +++ b/fedac/native/Dockerfile.flash-helper @@ -8,6 +8,7 @@ RUN dnf install -y --setopt=install_weak_deps=False \ COPY fedac/native/scripts/media-layout.sh /usr/local/lib/ac-media-layout.sh COPY fedac/native/scripts/flash-helper-runner.sh /usr/local/bin/ac-os-flash-helper COPY fedac/native/boot/systemd-bootx64.efi /usr/local/lib/systemd-bootx64.efi +COPY fedac/native/bootloader/splash.efi /usr/local/lib/splash.efi RUN chmod +x /usr/local/bin/ac-os-flash-helper diff --git a/fedac/native/docker-build.sh b/fedac/native/docker-build.sh index 44a2cbf908..8e588990f0 100644 --- a/fedac/native/docker-build.sh +++ b/fedac/native/docker-build.sh @@ -568,6 +568,29 @@ cp arch/x86/boot/bzImage "$OUT/vmlinuz" 2>/dev/null || true VMLINUZ_SIZE=$(stat -c%s "$BUILD/vmlinuz") SHA=$(sha256sum "$BUILD/vmlinuz" | awk '{print $1}') +# ══════════════════════════════════════════════ +# Step 4b: Build slim kernel (no embedded initramfs) for Mac EFI boot +# ══════════════════════════════════════════════ +log "Step 4b: Building slim kernel for Mac..." +sed -i 's|^CONFIG_INITRAMFS_SOURCE=.*|CONFIG_INITRAMFS_SOURCE=""|' .config +rm -f usr/initramfs_data.o usr/.initramfs_data.o.cmd +if run_make_with_heartbeat "$BUILD/kernel-slim.log" make -j"${KERNEL_JOBS}" bzImage; then + cp arch/x86/boot/bzImage "$BUILD/vmlinuz-slim" + cp arch/x86/boot/bzImage "$OUT/vmlinuz-slim" 2>/dev/null || true + SLIM_SIZE=$(stat -c%s "$BUILD/vmlinuz-slim") + log " Slim kernel: $((SLIM_SIZE / 1048576))MB" +else + err "Slim kernel build failed (non-fatal)" +fi +# Restore config for any subsequent builds +sed -i 's|^CONFIG_INITRAMFS_SOURCE=.*|CONFIG_INITRAMFS_SOURCE="initramfs.cpio.lz4"|' .config + +# Export initramfs as gzip (for systemd-boot on Mac) +log " Packing initramfs.cpio.gz..." +lz4 -d "$BUILD/initramfs.cpio.lz4" -c 2>/dev/null | gzip -c > "$BUILD/initramfs.cpio.gz" +cp "$BUILD/initramfs.cpio.gz" "$OUT/initramfs.cpio.gz" 2>/dev/null || true +log " initramfs.cpio.gz: $(($(stat -c%s "$BUILD/initramfs.cpio.gz") / 1048576))MB" + # ══════════════════════════════════════════════ # Step 5: Generate UEFI-bootable ISO # ══════════════════════════════════════════════ diff --git a/fedac/native/scripts/flash-helper-runner.sh b/fedac/native/scripts/flash-helper-runner.sh index c71fd6744e..42a53a1ff8 100644 --- a/fedac/native/scripts/flash-helper-runner.sh +++ b/fedac/native/scripts/flash-helper-runner.sh @@ -81,30 +81,37 @@ copy_boot_tree_to_vfat() { cp "${STAGED_ROOT}/EFI/BOOT/KERNEL.EFI" "${mountpoint}/EFI/BOOT/BOOTX64.EFI" ;; systemd-boot) - # Use systemd-boot as BOOTX64.EFI with SLIM kernel + separate initramfs. - # Mac EFI can't load a 270MB kernel. The slim kernel (~15MB) has no - # embedded initramfs. systemd-boot loads both via linux + initrd. + # Universal boot: splash.efi → systemd-boot → slim kernel + initramfs. + # splash.efi shows "Aesthetic.Computer" on black, chains to LOADER.EFI. + # Works on both Macs (can't load 270MB) and ThinkPads. local sdboot="/usr/local/lib/systemd-bootx64.efi" [ ! -f "${sdboot}" ] && sdboot="/repo/fedac/native/boot/systemd-bootx64.efi" [ ! -f "${sdboot}" ] && sdboot="/workspaces/aesthetic-computer/fedac/native/boot/systemd-bootx64.efi" - cp "${sdboot}" "${mountpoint}/EFI/BOOT/BOOTX64.EFI" + # splash.efi as BOOTX64.EFI (shows splash, chains to LOADER.EFI) + cp "${STAGED_ROOT}/EFI/BOOT/BOOTX64.EFI" "${mountpoint}/EFI/BOOT/BOOTX64.EFI" + # systemd-boot as LOADER.EFI (loads slim kernel + initramfs) + cp "${sdboot}" "${mountpoint}/EFI/BOOT/LOADER.EFI" # Use slim kernel if available, fall back to full kernel if [ -f "${STAGED_ROOT}/EFI/BOOT/KERNEL-SLIM.EFI" ]; then cp "${STAGED_ROOT}/EFI/BOOT/KERNEL-SLIM.EFI" "${mountpoint}/EFI/BOOT/KERNEL.EFI" else cp "${STAGED_ROOT}/EFI/BOOT/KERNEL.EFI" "${mountpoint}/EFI/BOOT/KERNEL.EFI" fi - # Separate initramfs for systemd-boot to load - if [ -f "${STAGED_ROOT}/initramfs.cpio.lz4" ]; then + # Separate initramfs for systemd-boot to load (prefer gzip, fall back to lz4) + if [ -f "${STAGED_ROOT}/initramfs.cpio.gz" ]; then + cp "${STAGED_ROOT}/initramfs.cpio.gz" "${mountpoint}/initramfs.cpio.gz" + elif [ -f "${STAGED_ROOT}/initramfs.cpio.lz4" ]; then cp "${STAGED_ROOT}/initramfs.cpio.lz4" "${mountpoint}/initramfs.cpio.lz4" fi # systemd-boot loader config mkdir -p "${mountpoint}/loader/entries" printf 'default ac-native.conf\ntimeout 0\n' > "${mountpoint}/loader/loader.conf" - cat > "${mountpoint}/loader/entries/ac-native.conf" << 'SDBOOT_EOF' + local initrd_file="initramfs.cpio.gz" + [ ! -f "${mountpoint}/initramfs.cpio.gz" ] && initrd_file="initramfs.cpio.lz4" + cat > "${mountpoint}/loader/entries/ac-native.conf" << SDBOOT_EOF title AC Native OS linux /EFI/BOOT/KERNEL.EFI -initrd /initramfs.cpio.lz4 +initrd /${initrd_file} options console=tty0 quiet loglevel=3 vt.global_cursor_default=0 init=/init efi=noruntime SDBOOT_EOF ;; @@ -266,12 +273,17 @@ partprobe "${USB_DEV}" 2>/dev/null || true # Partition 1 (ACBOOT): config + kernel as KERNEL.EFI (for AC initramfs to find) copy_boot_tree_to_vfat "${MAIN_PART}" /mnt/ac-main yes kernel-only -# Partition 2 (ACEFI): systemd-boot (134KB) + KERNEL.EFI (270MB) -# Mac EFI firmware can't LoadImage a 270MB PE/COFF. splash.efi also -# uses LoadImage internally and fails the same way. systemd-boot uses -# the EFI handover protocol to load the kernel directly into memory, -# bypassing LoadImage entirely. -copy_boot_tree_to_vfat "${EFI_PART}" /mnt/ac-efi no systemd-boot + +# Partition 2 (ACEFI): universal boot — splash → systemd-boot → slim kernel + initramfs +# Works on both Macs (can't load 270MB EFI app) and ThinkPads. +# If slim kernel isn't available, falls back to chainloader mode. +if [ -f "${STAGED_ROOT}/EFI/BOOT/KERNEL-SLIM.EFI" ] && [ -f "${STAGED_ROOT}/initramfs.cpio.gz" ]; then + log "Using universal boot: splash → systemd-boot → slim kernel + initramfs" + copy_boot_tree_to_vfat "${EFI_PART}" /mnt/ac-efi no systemd-boot +else + log "No slim kernel — using chainloader mode (ThinkPad only)" + copy_boot_tree_to_vfat "${EFI_PART}" /mnt/ac-efi no chainloader +fi populate_mac_partition "${MAC_PART}" /mnt/ac-mac sync diff --git a/fedac/native/scripts/media-layout.sh b/fedac/native/scripts/media-layout.sh index c40624783f..b9ccff667c 100644 --- a/fedac/native/scripts/media-layout.sh +++ b/fedac/native/scripts/media-layout.sh @@ -100,16 +100,20 @@ ac_media_stage_boot_tree() { cp "${kernel_path}" "${stage_root}/EFI/BOOT/KERNEL.EFI" cp "${config_path}" "${stage_root}/config.json" - # Stage slim kernel + initramfs for Mac boot (systemd-boot mode) + # Stage slim kernel + initramfs for universal boot (systemd-boot mode) local kernel_dir kernel_dir="$(dirname "${kernel_path}")" local slim="${kernel_dir}/vmlinuz-slim" - local initramfs="${kernel_dir}/initramfs.cpio.lz4" if [ -f "${slim}" ]; then cp "${slim}" "${stage_root}/EFI/BOOT/KERNEL-SLIM.EFI" fi - if [ -f "${initramfs}" ]; then - cp "${initramfs}" "${stage_root}/initramfs.cpio.lz4" + # Prefer gzip initramfs (universal), fall back to lz4 + local initramfs_gz="${kernel_dir}/initramfs.cpio.gz" + local initramfs_lz4="${kernel_dir}/initramfs.cpio.lz4" + if [ -f "${initramfs_gz}" ]; then + cp "${initramfs_gz}" "${stage_root}/initramfs.cpio.gz" + elif [ -f "${initramfs_lz4}" ]; then + cp "${initramfs_lz4}" "${stage_root}/initramfs.cpio.lz4" fi } -- 2.51.2