diff --git a/build/scripts/create-rpi-image.sh b/build/scripts/create-rpi-image.sh index 1f17daa..57fd44d 100755 --- a/build/scripts/create-rpi-image.sh +++ b/build/scripts/create-rpi-image.sh @@ -1,15 +1,17 @@ #!/bin/bash # create-rpi-image.sh — Create a raw disk image for Raspberry Pi SD card # -# Partition layout (GPT): -# Part 1: Boot Control (16 MB, FAT32, label KSOLOCTL) — autoboot.txt only -# Part 2: Boot A (256 MB, FAT32, label KSOLOA) — firmware + kernel + DTBs + initramfs +# Partition layout (MBR): +# Part 1: Boot Control (32 MB, FAT32, label KSOLOCTL) — firmware + 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 uses autoboot.txt in the control partition to implement A/B boot -# via the tryboot mechanism (tryboot_a_b=1). Normal boot → partition 2 (Boot A), -# tryboot → partition 3 (Boot B). +# 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. +# +# MBR is required — GPT + autoboot.txt is not reliably supported on Pi 4. # # Usage: build/scripts/create-rpi-image.sh set -euo pipefail @@ -64,22 +66,24 @@ mkdir -p "$OUTPUT_DIR" # --- Create sparse image --- dd if=/dev/zero of="$IMG_OUTPUT" bs=1M count=0 seek="$IMG_SIZE_MB" 2>/dev/null -# --- Partition table (GPT) --- -# Part 1: Boot Control 16 MB FAT32 -# Part 2: Boot A 256 MB FAT32 -# Part 3: Boot B 256 MB FAT32 +# --- 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 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: gpt +label: dos -# Boot Control partition: 16 MB -start=2048, size=32768, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, name="BootCtl" -# Boot A partition: 256 MB -size=524288, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, name="BootA" -# Boot B partition: 256 MB -size=524288, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, name="BootB" -# Data partition: remaining -type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, name="Data" +# Boot Control partition: 32 MB, FAT32 (type 0c = W95 FAT32 LBA) +start=2048, size=65536, type=c, bootable +# Boot A partition: 256 MB, FAT32 +size=524288, type=c +# Boot B partition: 256 MB, FAT32 +size=524288, type=c +# Data partition: remaining, Linux +type=83 EOF # --- Set up loop device --- @@ -146,7 +150,9 @@ mount "$P3" "$MNT_BOOTB" mount "$P4" "$MNT_DATA" # --- Boot Control Partition (KSOLOCTL) --- -echo " Writing autoboot.txt..." +# 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 @@ -155,6 +161,17 @@ boot_partition=2 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 + # --- Helper: populate a boot partition --- populate_boot_partition() { local MNT="$1" @@ -183,17 +200,6 @@ CFGTXT # Copy initramfs cp "$INITRAMFS" "$MNT/kubesolo-os.gz" - # Copy firmware blobs (start*.elf, fixup*.dat) - if ls "$RPI_FIRMWARE_DIR"/start*.elf 1>/dev/null 2>&1; then - cp "$RPI_FIRMWARE_DIR"/start*.elf "$MNT/" - fi - if ls "$RPI_FIRMWARE_DIR"/fixup*.dat 1>/dev/null 2>&1; then - cp "$RPI_FIRMWARE_DIR"/fixup*.dat "$MNT/" - fi - if [ -f "$RPI_FIRMWARE_DIR/bootcode.bin" ]; then - cp "$RPI_FIRMWARE_DIR/bootcode.bin" "$MNT/" - fi - # Copy DTB overlays if [ -d "$RPI_FIRMWARE_DIR/overlays" ]; then cp -r "$RPI_FIRMWARE_DIR/overlays" "$MNT/" @@ -225,9 +231,9 @@ sync echo "" echo "==> Raspberry Pi disk image created: $IMG_OUTPUT" echo " Size: $(du -h "$IMG_OUTPUT" | cut -f1)" -echo " Part 1 (KSOLOCTL): Boot control (autoboot.txt)" -echo " Part 2 (KSOLOA): Boot A — firmware + kernel + initramfs" -echo " Part 3 (KSOLOB): Boot B — firmware + kernel + initramfs" +echo " Part 1 (KSOLOCTL): Firmware + 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" echo "" echo "Write to SD card with:"