#!/usr/bin/env bash # Fetch Fedora's Microsoft-signed Secure Boot chain — shim + GRUB — and # place the EFI binaries under assets/ipxe/ with the filenames OpenPXE's # DriverMode::Shim mapping expects: # # shimx64.efi x86_64: Microsoft-signed shim (first stage) # grubx64.efi x86_64: Fedora-signed GRUB (loaded by shim, fetches # the server-rendered grub.cfg over TFTP/HTTP) # shimaa64.efi arm64 equivalents (best-effort — see below) # grubaa64.efi # # Why Fedora: a supply-chain decision made deliberately (v0.7.0) — one # vendor, fast security turnaround, and the same chain most netboot # projects redistribute. The binaries are extracted from the official # distro RPMs and shipped BYTE-FOR-BYTE UNMODIFIED; their signatures are # what make the chain work, and modifying them would break it. This is # the standard documented netboot path for Secure Boot (Red Hat # Satellite, SUSE HTTPBoot) and involves no test certificates and no # client trust-store changes. # # Trust model matches fetch-ipxe.sh: HTTPS to the official distribution # point, no sha pinning because we track the latest signed build (which # rotates on SBAT revocations — pinning would mean shipping revoked # shims). Mirror to your own artifact store for deterministic builds. set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" DEST="${1:-$ROOT/assets/ipxe}" mkdir -p "$DEST" FEDORA_RELEASE="${FEDORA_RELEASE:-43}" BASE="${FEDORA_MIRROR:-https://dl.fedoraproject.org/pub/fedora/linux/releases/$FEDORA_RELEASE/Everything}" WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT # Find the newest RPM in a repo directory whose name starts with # `$pattern` followed by a version digit (anchoring on the digit keeps # `grub2-efi-x64` from matching `grub2-efi-x64-cdboot`). latest_rpm() { local dir_url="$1" pattern="$2" curl -fsSL "$dir_url/" \ | grep -oE "href=\"${pattern}-[0-9][^\"]*\.rpm\"" \ | sed 's/^href="//; s/"$//' \ | sort -V | tail -1 } # fetch_chain fetch_chain() { local arch="$1" shim_pkg="$2" grub_pkg="$3" shim_out="$4" grub_out="$5" mode="$6" local pkg_base="$BASE/$arch/os/Packages" local sdir="$pkg_base/${shim_pkg:0:1}" gdir="$pkg_base/${grub_pkg:0:1}" local shim_rpm grub_rpm shim_rpm="$(latest_rpm "$sdir" "$shim_pkg" || true)" grub_rpm="$(latest_rpm "$gdir" "$grub_pkg" || true)" if [ -z "$shim_rpm" ] || [ -z "$grub_rpm" ]; then echo "!! could not locate $shim_pkg/$grub_pkg RPMs under $pkg_base" [ "$mode" = "hard" ] && exit 2 echo " skipping $arch Secure Boot chain (best-effort)" return 0 fi echo ">> $arch: $shim_rpm + $grub_rpm" local exdir="$WORK/$arch" mkdir -p "$exdir" curl -fsSL -o "$exdir/shim.rpm" "$sdir/$shim_rpm" curl -fsSL -o "$exdir/grub.rpm" "$gdir/$grub_rpm" ( cd "$exdir" \ && rpm2cpio shim.rpm | cpio -idm --quiet "./boot/efi/EFI/*/$shim_out" \ && rpm2cpio grub.rpm | cpio -idm --quiet "./boot/efi/EFI/*/$grub_out" ) local shim_path grub_path shim_path="$(find "$exdir/boot" -name "$shim_out" | head -1)" grub_path="$(find "$exdir/boot" -name "$grub_out" | head -1)" if [ -z "$shim_path" ] || [ -z "$grub_path" ]; then echo "!! RPM layout changed — $shim_out/$grub_out not found inside the packages" [ "$mode" = "hard" ] && exit 2 return 0 fi cp "$shim_path" "$DEST/$shim_out" cp "$grub_path" "$DEST/$grub_out" echo " installed $shim_out + $grub_out" } # x86_64 is the headline Secure Boot audience — fail the build if it # can't be assembled so a regression is loud, not silent. fetch_chain x86_64 shim-x64 grub2-efi-x64 shimx64.efi grubx64.efi hard # arm64 is best-effort: skipping just means no Shim escalation rung for # that arch (logged at startup by ipxe-assets::log_availability). fetch_chain aarch64 shim-aa64 grub2-efi-aa64 shimaa64.efi grubaa64.efi soft echo echo "Secure Boot chain assets now in $DEST:" ls -lh "$DEST"/shim*.efi "$DEST"/grub*.efi 2>/dev/null || true