- Dockerfile.builder: Go 1.24.0 → 1.25.5 (go.mod requires it) - test-boot.sh: use direct kernel boot via ISO extraction instead of broken -cdrom + -append; fix boot marker to "KubeSolo is running" (Stage 90 blocks on wait, never emits "complete") - test-security-hardening.sh: same direct kernel boot and marker fixes - run-vm.sh, dev-vm.sh, dev-vm-arm64.sh: quote QEMU -net args to silence shellcheck SC2054 - fetch-components.sh, fetch-rpi-firmware.sh, dev-vm-arm64.sh: fix trap quoting (SC2064) Validated: full Docker build, 94 Go tests pass, QEMU boot (73s), security hardening test (6/6 pass, 1 AppArmor skip pending kernel rebuild). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
89 lines
3.0 KiB
Bash
Executable File
89 lines
3.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# fetch-rpi-firmware.sh — Download Raspberry Pi firmware blobs for boot
|
|
#
|
|
# Downloads firmware from the official raspberrypi/firmware GitHub repository.
|
|
# Extracts only the boot files needed: start*.elf, fixup*.dat, DTBs, bootcode.bin.
|
|
#
|
|
# Output: build/cache/rpi-firmware/ containing all required boot files.
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
CACHE_DIR="${CACHE_DIR:-$PROJECT_ROOT/build/cache}"
|
|
|
|
# shellcheck source=../config/versions.env
|
|
. "$SCRIPT_DIR/../config/versions.env"
|
|
|
|
RPI_FW_DIR="$CACHE_DIR/rpi-firmware"
|
|
RPI_FW_ARCHIVE="$CACHE_DIR/rpi-firmware-${RPI_FIRMWARE_TAG}.tar.gz"
|
|
|
|
# --- Skip if already fetched ---
|
|
if [ -d "$RPI_FW_DIR" ] && [ -f "$RPI_FW_DIR/start4.elf" ]; then
|
|
echo "==> RPi firmware already cached: $RPI_FW_DIR"
|
|
echo " Files: $(ls "$RPI_FW_DIR" | wc -l)"
|
|
exit 0
|
|
fi
|
|
|
|
echo "==> Downloading Raspberry Pi firmware (tag: ${RPI_FIRMWARE_TAG})..."
|
|
mkdir -p "$CACHE_DIR" "$RPI_FW_DIR"
|
|
|
|
# --- Download firmware archive ---
|
|
if [ ! -f "$RPI_FW_ARCHIVE" ]; then
|
|
echo " URL: $RPI_FIRMWARE_URL"
|
|
wget -q --show-progress -O "$RPI_FW_ARCHIVE" "$RPI_FIRMWARE_URL" 2>/dev/null || \
|
|
curl -fSL "$RPI_FIRMWARE_URL" -o "$RPI_FW_ARCHIVE"
|
|
echo " Downloaded: $(du -h "$RPI_FW_ARCHIVE" | cut -f1)"
|
|
else
|
|
echo " Archive already cached: $(du -h "$RPI_FW_ARCHIVE" | cut -f1)"
|
|
fi
|
|
|
|
# --- Extract boot files only ---
|
|
echo "==> Extracting boot files..."
|
|
TEMP_DIR=$(mktemp -d)
|
|
trap 'rm -rf "$TEMP_DIR"' EXIT
|
|
|
|
# Extract only the boot/ directory from the archive
|
|
# Archive structure: firmware-<tag>/boot/...
|
|
tar -xzf "$RPI_FW_ARCHIVE" -C "$TEMP_DIR" --strip-components=1 '*/boot/'
|
|
|
|
BOOT_SRC="$TEMP_DIR/boot"
|
|
if [ ! -d "$BOOT_SRC" ]; then
|
|
echo "ERROR: boot/ directory not found in firmware archive"
|
|
ls -la "$TEMP_DIR"/
|
|
exit 1
|
|
fi
|
|
|
|
# Copy GPU firmware (required for boot)
|
|
for f in "$BOOT_SRC"/start*.elf "$BOOT_SRC"/fixup*.dat; do
|
|
[ -f "$f" ] && cp "$f" "$RPI_FW_DIR/"
|
|
done
|
|
|
|
# Copy bootcode.bin (first-stage boot for Pi 3 and older)
|
|
[ -f "$BOOT_SRC/bootcode.bin" ] && cp "$BOOT_SRC/bootcode.bin" "$RPI_FW_DIR/"
|
|
|
|
# Copy Device Tree Blobs for Pi 4 + Pi 5
|
|
for dtb in bcm2711-rpi-4-b.dtb bcm2711-rpi-400.dtb bcm2711-rpi-cm4.dtb \
|
|
bcm2712-rpi-5-b.dtb bcm2712d0-rpi-5-b.dtb; do
|
|
[ -f "$BOOT_SRC/$dtb" ] && cp "$BOOT_SRC/$dtb" "$RPI_FW_DIR/"
|
|
done
|
|
|
|
# Copy overlays directory (needed for config.txt dtoverlay= directives)
|
|
if [ -d "$BOOT_SRC/overlays" ]; then
|
|
mkdir -p "$RPI_FW_DIR/overlays"
|
|
# Only copy overlays we actually use (disable-wifi, disable-bt)
|
|
for overlay in disable-wifi.dtbo disable-bt.dtbo; do
|
|
[ -f "$BOOT_SRC/overlays/$overlay" ] && \
|
|
cp "$BOOT_SRC/overlays/$overlay" "$RPI_FW_DIR/overlays/"
|
|
done
|
|
fi
|
|
|
|
trap - EXIT
|
|
rm -rf "$TEMP_DIR"
|
|
|
|
# --- Summary ---
|
|
echo ""
|
|
echo "==> RPi firmware extracted to: $RPI_FW_DIR"
|
|
echo " Files:"
|
|
ls -1 "$RPI_FW_DIR" | head -20
|
|
echo " Total size: $(du -sh "$RPI_FW_DIR" | cut -f1)"
|