diff --git a/emmc-provisioning/docs/NETWORK-BOOT-TROUBLESHOOTING.md b/emmc-provisioning/docs/NETWORK-BOOT-TROUBLESHOOTING.md index 3fce839..49e4373 100644 --- a/emmc-provisioning/docs/NETWORK-BOOT-TROUBLESHOOTING.md +++ b/emmc-provisioning/docs/NETWORK-BOOT-TROUBLESHOOTING.md @@ -127,6 +127,28 @@ and you **never** see a line about network (e.g. "Trying DHCP", "TFTP", or "Boot --- +## Boot stops after start4.elf ("PCI0 reset" then nothing) + +If the serial log shows **TFTP** for config.txt, start4.elf, fixup4.dat, then **"Starting start4.elf"**, **"Stopping network"**, **"PCI0 reset"**, and **no** TFTP requests for **kernel8.img** or **initrd.img**, the bootloader is not loading the kernel. That usually means **config.txt** in the TFTP root does not have the **kernel** and **initramfs** lines. + +**Fix on the LXC:** ensure `/srv/tftpboot/config.txt` contains (and that `0d1ddbda/config.txt` is a symlink to it or has the same content): + +```ini +kernel=kernel8.img +initramfs initrd.img followkernel +``` + +You can run: + +```bash +# On the LXC (or from your machine) +ssh root@ 'bash -s' < emmc-provisioning/scripts/ensure-tftpboot-config-kernel-initrd.sh +``` + +Also ensure the TFTP root has **kernel8.img** and **initrd.img** (and the serial subdir has symlinks or copies). Then power-cycle the device; you should see TFTP_GET for kernel8.img and initrd.img, then the kernel and initramfs (e.g. rescue shell or provisioning client) run. + +--- + ## TFTP "file .../SERIAL/start4.elf not found" — serial-number prefix The Pi bootloader may request files under a path named after the board serial number (e.g. `0d1ddbda/start4.elf`). If the TFTP root has no such subdirectory, those requests fail and the bootloader falls back to the root (e.g. `start4.elf`). To avoid "not found" for the first requests, on the LXC create the serial directory and symlink the boot files: diff --git a/emmc-provisioning/network-boot-initramfs/initrd.img b/emmc-provisioning/network-boot-initramfs/initrd.img index 2ad9845..c3ca5b6 100644 Binary files a/emmc-provisioning/network-boot-initramfs/initrd.img and b/emmc-provisioning/network-boot-initramfs/initrd.img differ diff --git a/emmc-provisioning/scripts/ensure-tftpboot-config-kernel-initrd.sh b/emmc-provisioning/scripts/ensure-tftpboot-config-kernel-initrd.sh new file mode 100755 index 0000000..468af84 --- /dev/null +++ b/emmc-provisioning/scripts/ensure-tftpboot-config-kernel-initrd.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Ensure TFTP config.txt on the LXC has kernel=kernel8.img and initramfs initrd.img followkernel +# so the bootloader loads the kernel and initrd (otherwise boot stops after start4.elf). +# Run on LXC: bash ensure-tftpboot-config-kernel-initrd.sh +# Or: ssh root@10.20.30.153 'bash -s' < emmc-provisioning/scripts/ensure-tftpboot-config-kernel-initrd.sh + +set -e +TFTP_ROOT="${TFTP_ROOT:-/srv/tftpboot}" +CONFIG="$TFTP_ROOT/config.txt" + +if [[ ! -f "$CONFIG" ]]; then + echo "Error: $CONFIG not found." + exit 1 +fi + +CHANGED=0 +if ! grep -qE '^kernel=kernel8\.img' "$CONFIG" 2>/dev/null; then + echo "Adding kernel=kernel8.img to $CONFIG" + echo "kernel=kernel8.img" >> "$CONFIG" + CHANGED=1 +fi +if ! grep -qE 'initramfs initrd\.img' "$CONFIG" 2>/dev/null; then + echo "Adding initramfs initrd.img followkernel to $CONFIG" + echo "" >> "$CONFIG" + echo "# Provisioning initramfs (network-boot-initramfs)" >> "$CONFIG" + echo "initramfs initrd.img followkernel" >> "$CONFIG" + CHANGED=1 +fi + +if [[ "$CHANGED" -eq 1 ]]; then + echo "Config updated. Ensure $TFTP_ROOT has kernel8.img and initrd.img." +else + echo "Config already has kernel and initramfs lines." +fi +grep -E 'kernel|initramfs' "$CONFIG" 2>/dev/null || true + +# Ensure serial-prefix dir gets a real copy of config (some TFTP servers don't follow symlinks) +for serial_dir in "$TFTP_ROOT"/[0-9a-f]*/; do + [[ -d "$serial_dir" ]] || continue + if [[ -L "$serial_dir/config.txt" ]] || [[ ! -f "$serial_dir/config.txt" ]]; then + rm -f "$serial_dir/config.txt" + cp "$CONFIG" "$serial_dir/config.txt" + echo "Copied config.txt into $(basename "$serial_dir")/ (real file) so device gets full config." + fi +done