#!/usr/bin/env bash # Ensure TFTP config.txt on the LXC has kernel=kernel8.img, initramfs initrd.img followkernel, # and uart_2ndstage=1 (GPU firmware logs to UART for netboot debugging). # 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 # enable_uart=1 must be present (and within first 4KB of config) so netboot firmware sets 8250.nr_uarts=1; else kernel has no serial console (Pi firmware #1575). if ! grep -qE 'enable_uart=1' "$CONFIG" 2>/dev/null; then echo "Adding enable_uart=1 to $CONFIG (required for kernel serial on netboot)" echo "enable_uart=1" >> "$CONFIG" CHANGED=1 fi 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 ! grep -qE 'uart_2ndstage=1' "$CONFIG" 2>/dev/null; then echo "Adding uart_2ndstage=1 to $CONFIG (GPU firmware logs to UART for netboot debug)" echo "" >> "$CONFIG" echo "# GPU firmware logs to UART (see MESS: lines after PCI0 reset)" >> "$CONFIG" echo "uart_2ndstage=1" >> "$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, initramfs and uart_2ndstage lines." fi grep -E 'enable_uart|kernel|initramfs|uart_2ndstage' "$CONFIG" 2>/dev/null || true # Ensure serial-prefix dirs get a real copy of config and symlinks to DTB files. # GPU loads kernel/initrd/dtb from the serial prefix; missing DTBs cause "Failed to load Device Tree file '?'" and the kernel can hang. for serial_dir in "$TFTP_ROOT"/[0-9a-f]*/; do [[ -d "$serial_dir" ]] || continue 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." for dtb in "$TFTP_ROOT"/*.dtb; do [[ -f "$dtb" ]] || continue base=$(basename "$dtb") if [[ ! -e "$serial_dir/$base" ]]; then ln -sf "../$base" "$serial_dir/$base" echo "Linked $base into $(basename "$serial_dir")/" fi done done