From a2764218fcb6ee54012f1b2a417e5cf2c047548f Mon Sep 17 00:00:00 2001 From: Adolfo Delorenzo Date: Thu, 12 Feb 2026 18:52:21 -0600 Subject: [PATCH] fix: make RPi partition 1 self-sufficient boot fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The autoboot.txt A/B redirect requires newer RPi EEPROM firmware. On older EEPROMs, autoboot.txt is silently ignored and the firmware tries to boot from partition 1 directly — failing with a rainbow screen because partition 1 had no kernel or initramfs. Changes: - Increase partition 1 from 32 MB to 384 MB - Populate partition 1 with full boot files (kernel, initramfs, config.txt with kernel= directive, DTBs, overlays) - Keep autoboot.txt for A/B redirect on supported EEPROMs - When autoboot.txt works: boots from partition 2 (A/B scheme) - When autoboot.txt is unsupported: boots from partition 1 (fallback) Co-Authored-By: Claude Opus 4.6 --- build/scripts/create-rpi-image.sh | 90 +++++++++++++++---------------- 1 file changed, 42 insertions(+), 48 deletions(-) diff --git a/build/scripts/create-rpi-image.sh b/build/scripts/create-rpi-image.sh index f9aeed8..60ad800 100755 --- a/build/scripts/create-rpi-image.sh +++ b/build/scripts/create-rpi-image.sh @@ -2,14 +2,14 @@ # create-rpi-image.sh — Create a raw disk image for Raspberry Pi SD card # # Partition layout (MBR): -# Part 1: Boot Control (32 MB, FAT32, label KSOLOCTL) — firmware + autoboot.txt +# Part 1: Boot/Control (384 MB, FAT32, label KSOLOCTL) — firmware + kernel + initramfs + autoboot.txt # Part 2: Boot A (256 MB, FAT32, label KSOLOA) — kernel + DTBs + initramfs # Part 3: Boot B (256 MB, FAT32, label KSOLOB) — same as Boot A (initially identical) # Part 4: Data (remaining of 2GB, ext4, label KSOLODATA) # -# The RPi EEPROM loads start4.elf from partition 1 (KSOLOCTL). -# autoboot.txt on partition 1 redirects boot_partition to 2 (Boot A) or 3 (Boot B). -# The firmware then loads config.txt, kernel, and initramfs from the selected partition. +# The RPi EEPROM loads start4.elf from partition 1. +# If autoboot.txt is supported (newer EEPROM), firmware redirects to partition 2/3 for A/B boot. +# If autoboot.txt is NOT supported (older EEPROM), partition 1 has full boot files as fallback. # # MBR is required — GPT + autoboot.txt is not reliably supported on Pi 4. # @@ -69,15 +69,16 @@ dd if=/dev/zero of="$IMG_OUTPUT" bs=1M count=0 seek="$IMG_SIZE_MB" 2>/dev/null # --- Partition table (MBR) --- # MBR is required for reliable RPi boot with autoboot.txt. # GPT + autoboot.txt fails on many Pi 4 EEPROM versions. -# Part 1: Boot Control 32 MB FAT32 (firmware + autoboot.txt) +# Part 1: Boot/Control 384 MB FAT32 (firmware + kernel + initramfs + autoboot.txt) # Part 2: Boot A 256 MB FAT32 (kernel + initramfs + DTBs) # Part 3: Boot B 256 MB FAT32 (kernel + initramfs + DTBs) # Part 4: Data remaining ext4 sfdisk "$IMG_OUTPUT" << EOF label: dos -# Boot Control partition: 32 MB, FAT32 (type 0c = W95 FAT32 LBA) -start=2048, size=65536, type=c, bootable +# Boot/Control partition: 384 MB, FAT32 (type 0c = W95 FAT32 LBA) +# Contains firmware + autoboot.txt for A/B redirect, PLUS full boot files as fallback +start=2048, size=786432, type=c, bootable # Boot A partition: 256 MB, FAT32 size=524288, type=c # Boot B partition: 256 MB, FAT32 @@ -149,46 +150,6 @@ mount "$P2" "$MNT_BOOTA" mount "$P3" "$MNT_BOOTB" mount "$P4" "$MNT_DATA" -# --- Boot Control Partition (KSOLOCTL) --- -# The RPi EEPROM loads start4.elf from partition 1. -# autoboot.txt tells the firmware which partition has config.txt + kernel. -echo " Writing autoboot.txt + firmware to boot control partition..." -cat > "$MNT_CTL/autoboot.txt" << 'AUTOBOOT' -[all] -tryboot_a_b=1 -boot_partition=2 -[tryboot] -boot_partition=3 -AUTOBOOT - -# Minimal config.txt on partition 1 — firmware reads this BEFORE autoboot.txt -# to determine arm_64bit mode and GPU settings. Without arm_64bit=1 here, -# the firmware defaults to 32-bit and can't load our 64-bit kernel. -cat > "$MNT_CTL/config.txt" << 'CFGTXT' -arm_64bit=1 -enable_uart=1 -gpu_mem=16 -CFGTXT - -# Copy firmware blobs — REQUIRED on partition 1 for EEPROM to boot -if ls "$RPI_FIRMWARE_DIR"/start*.elf 1>/dev/null 2>&1; then - cp "$RPI_FIRMWARE_DIR"/start*.elf "$MNT_CTL/" -fi -if ls "$RPI_FIRMWARE_DIR"/fixup*.dat 1>/dev/null 2>&1; then - cp "$RPI_FIRMWARE_DIR"/fixup*.dat "$MNT_CTL/" -fi -if [ -f "$RPI_FIRMWARE_DIR/bootcode.bin" ]; then - cp "$RPI_FIRMWARE_DIR/bootcode.bin" "$MNT_CTL/" -fi - -# Copy DTBs to partition 1 — firmware may need them before redirecting -if ls "$RPI_FIRMWARE_DIR"/bcm27*.dtb 1>/dev/null 2>&1; then - cp "$RPI_FIRMWARE_DIR"/bcm27*.dtb "$MNT_CTL/" -fi -if [ -d "$RPI_FIRMWARE_DIR/overlays" ]; then - cp -r "$RPI_FIRMWARE_DIR/overlays" "$MNT_CTL/" -fi - # --- Helper: populate a boot partition --- populate_boot_partition() { local MNT="$1" @@ -231,6 +192,39 @@ CFGTXT echo "$VERSION" > "$MNT/version.txt" } +# --- Boot Control Partition (KSOLOCTL) --- +# Partition 1 serves dual purpose: +# 1. Contains firmware + autoboot.txt for A/B redirect (if EEPROM supports it) +# 2. Contains full boot files (kernel + initramfs) as fallback if autoboot.txt isn't supported +echo " Writing firmware + autoboot.txt + boot files to partition 1..." + +# autoboot.txt — tells firmware which partition to boot from (A/B switching) +# If the EEPROM doesn't support this, it's silently ignored and the firmware +# falls back to booting from partition 1 using config.txt below. +cat > "$MNT_CTL/autoboot.txt" << 'AUTOBOOT' +[all] +tryboot_a_b=1 +boot_partition=2 +[tryboot] +boot_partition=3 +AUTOBOOT + +# Copy firmware blobs — REQUIRED on partition 1 for EEPROM to boot +if ls "$RPI_FIRMWARE_DIR"/start*.elf 1>/dev/null 2>&1; then + cp "$RPI_FIRMWARE_DIR"/start*.elf "$MNT_CTL/" +fi +if ls "$RPI_FIRMWARE_DIR"/fixup*.dat 1>/dev/null 2>&1; then + cp "$RPI_FIRMWARE_DIR"/fixup*.dat "$MNT_CTL/" +fi +if [ -f "$RPI_FIRMWARE_DIR/bootcode.bin" ]; then + cp "$RPI_FIRMWARE_DIR/bootcode.bin" "$MNT_CTL/" +fi + +# Full boot files on partition 1 — fallback if autoboot.txt redirect doesn't work. +# When autoboot.txt works, firmware switches to partition 2 and reads config.txt there. +# When autoboot.txt is unsupported, firmware reads THIS config.txt and boots from here. +populate_boot_partition "$MNT_CTL" "Boot Control (KSOLOCTL)" + # --- Boot A Partition (KSOLOA) --- populate_boot_partition "$MNT_BOOTA" "Boot A (KSOLOA)" @@ -248,7 +242,7 @@ sync echo "" echo "==> Raspberry Pi disk image created: $IMG_OUTPUT" echo " Size: $(du -h "$IMG_OUTPUT" | cut -f1)" -echo " Part 1 (KSOLOCTL): Firmware + autoboot.txt (boot control)" +echo " Part 1 (KSOLOCTL): Firmware + kernel + initramfs + autoboot.txt (boot/control)" echo " Part 2 (KSOLOA): Boot A — kernel + initramfs + DTBs" echo " Part 3 (KSOLOB): Boot B — kernel + initramfs + DTBs" echo " Part 4 (KSOLODATA): Persistent K8s state"