firmware.sh (1647 bytes)
1 #!/bin/sh 2 # firmware.sh - install pinned linux-firmware files into /lib/firmware. 3 # sh firmware.sh [-r ROOT] TAG LIST for each "SHA256 PATH" line of LIST: fetch PATH from 4 # linux-firmware tag TAG, check the hash, install ROOT/lib/firmware/PATH 5 # sh firmware.sh -s TAG print LIST lines for files the kernel failed to load (dmesg); 6 # the hashes come from the download: review them before you pin 7 set -eu 8 URL=https://gitlab.com/kernel-firmware/linux-firmware/-/raw 9 die() { echo "firmware.sh: $*" >&2; exit 1; } 10 ROOT=; SCAN= 11 [ "${1:-}" = -r ] && { ROOT=$2; shift 2; } 12 [ "${1:-}" = -s ] && { SCAN=1; shift; } 13 [ $# -ge 1 ] || die "usage: firmware.sh [-r ROOT] TAG LIST | -s TAG" 14 TAG=$1 15 T=$(mktemp); trap 'rm -f "$T"' EXIT 16 fetch() { curl -fsSL --retry 5 --retry-all-errors --retry-delay 5 -o "$T" "$URL/$TAG/$1"; } 17 safe() { case $1 in /* | *..*) die "bad path: $1" ;; esac; } 18 19 if [ -n "$SCAN" ]; then 20 dmesg | sed -n 's/.*Direct firmware load for \(.*\) failed with error.*/\1/p' | sort -u | 21 while read -r p; do 22 safe "$p" 23 [ -e "/lib/firmware/$p" ] && continue 24 if fetch "$p" 2>/dev/null; then echo "$(sha256sum "$T" | cut -d' ' -f1) $p"; else echo "# not in $TAG: $p"; fi 25 done 26 exit 0 27 fi 28 29 [ -r "${2:-}" ] || die "list not readable: ${2:-}" 30 while read -r sum p; do 31 case $sum in '' | '#'*) continue ;; esac 32 safe "$p" 33 fetch "$p" || die "download failed: $p" 34 echo "$sum $T" | sha256sum -c -s - || die "hash mismatch: $p" 35 install -D -m 644 "$T" "$ROOT/lib/firmware/$p" 36 echo "firmware: $p" 37 done < "$2"