#!/bin/sh # Rescue script: set EEPROM boot order directly from the initramfs (no chroot needed). # Uses rpi-eeprom-config + pieeprom.bin bundled in the Alpine-based initramfs. # Sets BOOT_ORDER=0xf21 (eMMC first, then network, restart) with fast network timeouts. # Run from the initramfs rescue shell (after booting with provisioning_rescue=1 in cmdline). # Pass --edit to open the editor manually instead of applying automatically. set -e EEPROM_FW="/lib/firmware/raspberrypi/bootloader/default/pieeprom.bin" BOOT_MNT="/mnt/boot" MANUAL=0 [ "$1" = "--edit" ] && MANUAL=1 # Clean up any previous mounts umount "$BOOT_MNT" 2>/dev/null || true umount /mnt/emmc 2>/dev/null || true # --- Read current EEPROM config --- echo "=== EEPROM rescue (Alpine initramfs) ===" if ! command -v rpi-eeprom-config >/dev/null 2>&1; then echo "ERROR: rpi-eeprom-config not found in initramfs." echo "This initramfs was not built with the Alpine build script." exit 1 fi if [ ! -f "$EEPROM_FW" ]; then echo "ERROR: EEPROM firmware not found at $EEPROM_FW" echo "Rebuild the initramfs with build.sh to include it." exit 1 fi echo "Reading current EEPROM config from running bootloader..." CURRENT_CONF="/tmp/eeprom-current.conf" rpi-eeprom-config 2>/dev/null > "$CURRENT_CONF" || true if [ ! -s "$CURRENT_CONF" ]; then echo "Could not read current EEPROM config via vcgencmd." echo "Extracting config from firmware image instead..." rpi-eeprom-config "$EEPROM_FW" > "$CURRENT_CONF" 2>/dev/null || true fi if [ ! -s "$CURRENT_CONF" ]; then echo "ERROR: Could not read EEPROM config from either source." exit 1 fi echo "Current config:" cat "$CURRENT_CONF" echo "" # --- Manual mode: mount eMMC boot, chroot, edit --- if [ "$MANUAL" -eq 1 ]; then echo "Manual mode: mounting eMMC for interactive editing..." mkdir -p /mnt/emmc mount /dev/mmcblk0p2 /mnt/emmc 2>/dev/null || true BOOT="/mnt/emmc/boot/firmware" [ ! -d "$BOOT" ] && BOOT="/mnt/emmc/boot" if [ -b /dev/mmcblk0p1 ]; then mkdir -p "$BOOT" mount /dev/mmcblk0p1 "$BOOT" 2>/dev/null || true fi mount -t proc none /mnt/emmc/proc 2>/dev/null || true mount -t sysfs none /mnt/emmc/sys 2>/dev/null || true mount --bind /dev /mnt/emmc/dev 2>/dev/null || true if [ -x /mnt/emmc/usr/bin/rpi-eeprom-config ]; then chroot /mnt/emmc /usr/bin/rpi-eeprom-config --edit else echo "rpi-eeprom-config not found on eMMC. Dropping to shell." chroot /mnt/emmc /bin/sh -i fi exit 0 fi # --- Automatic mode: build new config and apply --- NEW_CONF="/tmp/eeprom-new.conf" # Keep settings we don't modify, strip the ones we replace grep -v '^BOOT_ORDER=' "$CURRENT_CONF" \ | grep -v '^NET_BOOT_MAX_RETRIES=' \ | grep -v '^DHCP_TIMEOUT=' \ | grep -v '^DHCP_REQ_TIMEOUT=' \ | grep -v '^TFTP_IP=' \ | grep -v '^NET_INSTALL_AT_POWER_ON=' \ > "$NEW_CONF" || true echo 'BOOT_ORDER=0xf21' >> "$NEW_CONF" echo 'NET_BOOT_MAX_RETRIES=3' >> "$NEW_CONF" echo 'DHCP_TIMEOUT=1500' >> "$NEW_CONF" echo 'DHCP_REQ_TIMEOUT=500' >> "$NEW_CONF" echo 'NET_INSTALL_AT_POWER_ON=0' >> "$NEW_CONF" echo "New config to apply:" cat "$NEW_CONF" echo "" # Create the modified EEPROM image with the new config embedded EEPROM_OUT="/tmp/pieeprom.upd" echo "Embedding config into EEPROM firmware image..." rpi-eeprom-config --config "$NEW_CONF" --out "$EEPROM_OUT" "$EEPROM_FW" if [ ! -f "$EEPROM_OUT" ] || [ ! -s "$EEPROM_OUT" ]; then echo "ERROR: Failed to create modified EEPROM image." exit 1 fi # Generate the signature file (sha256 of the .upd, named .sig) EEPROM_SIG="/tmp/pieeprom.sig" sha256sum "$EEPROM_OUT" | awk '{print $1}' > "$EEPROM_SIG" # Mount eMMC boot partition and copy the update files echo "Mounting eMMC boot partition..." if [ ! -b /dev/mmcblk0p1 ]; then echo "ERROR: /dev/mmcblk0p1 not found. Is eMMC present?" exit 1 fi mkdir -p "$BOOT_MNT" mount /dev/mmcblk0p1 "$BOOT_MNT" || { echo "ERROR: Could not mount boot partition"; exit 1; } cp "$EEPROM_OUT" "$BOOT_MNT/pieeprom.upd" cp "$EEPROM_SIG" "$BOOT_MNT/pieeprom.sig" sync echo "" echo "=== EEPROM update written to eMMC boot partition ===" echo " BOOT_ORDER=0xf21 (eMMC first, then network, restart)" echo " NET_BOOT_MAX_RETRIES=3, DHCP_TIMEOUT=1500ms" echo " Files: pieeprom.upd + pieeprom.sig on /dev/mmcblk0p1" echo "" echo "The bootloader will apply this update on next boot from eMMC." echo "" echo "Next steps:" echo " 1. Disable network boot on the LXC (so next boot falls through to eMMC)" echo " 2. Reboot: reboot -f (or: echo b > /proc/sysrq-trigger)" umount "$BOOT_MNT" 2>/dev/null || true rm -f "$CURRENT_CONF" "$NEW_CONF" "$EEPROM_OUT" "$EEPROM_SIG"