#!/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-/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)"