Files
reterminal-dm4/emmc-provisioning/network-boot-initramfs
nearxos 5238d457e8 Update boot order configuration for eMMC first, then network
Modify the first-boot script and documentation to set the EEPROM boot order to 0xf21, prioritizing eMMC boot followed by network boot. Adjust network boot settings for faster failure on DHCP timeouts and update related scripts and documentation to reflect these changes. Enhance the rescue script to directly modify EEPROM settings without requiring a chroot into eMMC, streamlining the recovery process for devices stuck in network-only boot. Update relevant documentation to ensure clarity on the new boot order and its implications.
2026-02-21 15:05:17 +02:00
..

Provisioning initramfs for network boot

Alpine Linux-based initramfs that runs provisioning-client.sh after bringing up the network. Used with Raspberry Pi 4 / CM4 (reTerminal) when booting via TFTP from the provisioning LXC.

Includes Python 3 and rpi-eeprom-config so EEPROM configuration can be modified directly from the initramfs without chrooting into eMMC.

What it does

  1. Mounts /proc, /sys, /dev, /dev/pts.
  2. Brings up eth0 and obtains a DHCP lease via udhcpc.
  3. Runs the provisioning client with PROVISIONING_SERVER (default http://10.20.50.1:5000, overridable via kernel cmdline).
  4. The client registers with the dashboard and polls for Deploy or Backup; on action it performs the dd + curl and reboots.

Build

The build script uses Docker or Podman with --platform linux/arm64 to create an Alpine aarch64 rootfs with Python 3, curl, and rpi-eeprom-config. Your host must support arm64 containers via QEMU emulation.

Prerequisites

  • Docker or Podman installed
  • arm64 emulation (QEMU user-static):
    # Fedora
    sudo dnf install -y qemu-user-static
    
    # Debian/Ubuntu
    sudo apt install -y qemu-user-static
    

Build the initramfs

cd emmc-provisioning/network-boot-initramfs
./build.sh

Optional: pass an output path:

./build.sh /path/to/initrd.img

The resulting initrd.img is approximately 25-35 MB compressed (Alpine base + Python + EEPROM firmware).

Deploy to TFTP root

  1. Copy initrd.img to the LXC TFTP root (e.g. /srv/tftpboot):

    scp initrd.img root@10.130.60.141:/srv/tftpboot/
    
  2. In the TFTP root, ensure config.txt (Raspberry Pi boot config) includes the initramfs line. If you use the stock config.txt from the RPi firmware repo, add:

    initramfs initrd.img followkernel
    

    So the firmware loads the kernel and then the initrd that "follows" it. The Pi will boot the kernel and run /init from the initrd.

  3. If your DHCP already points the Pi to this TFTP server and start4cd.elf, the Pi will load kernel + initrd from the same root. No NFS or extra server needed.

Kernel cmdline (optional)

To override the provisioning server URL (e.g. if the dashboard is on another IP), add to cmdline.txt in the TFTP root (or append to the kernel command line):

provisioning_server=http://10.20.50.1:5000

The init script reads provisioning_server= from /proc/cmdline and exports PROVISIONING_SERVER for the client.

Rescue mode (stuck in network-only boot)

If the device has BOOT_ORDER=0x2 (network only), it never boots from eMMC. To fix the EEPROM config, add provisioning_rescue=1 to the kernel cmdline (e.g. in the TFTP-served cmdline.txt for that device). The initramfs will start an interactive shell instead of the provisioning client.

Run /rescue-eeprom.sh to set BOOT_ORDER=0xf21 directly from the initramfs. The script:

  1. Reads the current EEPROM config using rpi-eeprom-config (included in the initramfs)
  2. Creates a modified config with BOOT_ORDER=0xf21 and tuned network timeouts
  3. Embeds the config into a new EEPROM image using the bundled pieeprom.bin firmware
  4. Copies the update (pieeprom.upd + pieeprom.sig) to the eMMC boot partition

No chroot, no EDITOR hack, no dependency on the eMMC OS.

After running the script, disable network boot on the LXC and reboot so the bootloader boots from eMMC and applies the update.

See docs/NETWORK-BOOT-TROUBLESHOOTING.md ("Stuck in network-only boot") for full steps.

What's included in the initramfs

Component Purpose
Alpine Linux base Minimal rootfs with apk package manager
BusyBox Core Unix utilities (sh, mount, ip, udhcpc, dd, etc.)
Python 3 Required by rpi-eeprom-config
curl HTTP client for provisioning dashboard API
rpi-eeprom-config EEPROM configuration tool (from rpi-eeprom repo)
pieeprom.bin EEPROM firmware image (for creating update files)
init Boot script: mounts fs, DHCP, rescue or provision
provisioning-client.sh Registers with dashboard, executes deploy/backup
rescue-eeprom.sh Sets EEPROM boot order directly
udhcpc.script Applies DHCP lease (IP, route, DNS)

Flow summary

  1. Pi does DHCP -> gets IP and TFTP server (e.g. 10.20.50.1).
  2. Pi loads via TFTP: start4cd.elf, fixup4cd.dat, config.txt, cmdline.txt, kernel8.img, initrd.img.
  3. Kernel boots with initrd as root; runs /init.
  4. Init mounts minimal fs, ensures network, runs /provisioning-client.sh.
  5. Client registers and polls; you choose Deploy or Backup in the dashboard; client runs dd + curl and reboots.
  6. After deploy, device boots from eMMC.

See docs/NETWORK-BOOT-DEPLOYMENT-FLOW.md for the full deployment flow.