From: Andrew Hewus Fresh Subject: fw_update(8) allow using a different firmware. To: tech@openbsd.org Date: Fri, 7 Mar 2025 18:08:20 -0800 It's been a while, but I finally had time to get back to reworking this patch to add "-D dmesg" support to fw_update(8). I see it being useful in a few ways, the first being to download firmware for a machine that can't access the Internet or for copying a dmesg from an install image for testing changes to the patterns file more easily. As a side effect, it fixes some weirdness that jmc noticed with using "-p path" to install from, and I couldn't help but fix the bug where it left a SHA256.sig in the current directory when using "-nF". It also now complains instead of uselessly letting someone use "-Fp". Another side effect is that it now uses the version from the dmesg instead of the kern.version sysctl to figure out the correct download subdirectory and signify key. Are we allowed to use the "untrusted comment" in the SHA256.sig to pick the correct signify key to use? With that, I could remove the undocumented feature that sysupgrade(8) uses to override the "VNAME" and choose a different key. Comments, testing results, OK? I will be away from my computer and mostly the Internet for the next week, but should be able to respond after that. Index: fw_update.8 =================================================================== RCS file: /cvs/src/usr.sbin/fw_update/fw_update.8,v diff -u -p -r1.6 fw_update.8 --- fw_update.8 9 Nov 2024 02:19:48 -0000 1.6 +++ fw_update.8 8 Mar 2025 02:08:09 -0000 @@ -57,6 +57,14 @@ a driver. If used in conjunction with .Fl a , delete firmware for all drivers. +.It Fl D Ar path +Use the +.Xr dmesg 8 +output from +.Ar path +rather than +.Pa /var/run/dmesg.boot +to determine which firmware are needed. .It Fl F Download SHA256.sig and firmware .tgz to the current directory. .It Fl l Index: fw_update.sh =================================================================== RCS file: /cvs/src/usr.sbin/fw_update/fw_update.sh,v diff -u -p -r1.62 fw_update.sh --- fw_update.sh 24 Nov 2024 21:27:04 -0000 1.62 +++ fw_update.sh 8 Mar 2025 02:08:09 -0000 @@ -23,16 +23,9 @@ CFILE=SHA256.sig DESTDIR=${DESTDIR:-} FWPATTERNS="${DESTDIR}/usr/share/misc/firmware_patterns" -VNAME=${VNAME:-$(sysctl -n kern.osrelease)} -VERSION=${VERSION:-"${VNAME%.*}${VNAME#*.}"} - -HTTP_FWDIR="$VNAME" -VTYPE=$( sed -n "/^OpenBSD $VNAME\([^ ]*\).*$/s//\1/p" \ - /var/run/dmesg.boot | sed '$!d' ) -[ "$VTYPE" = -current ] && HTTP_FWDIR=snapshots - -FWURL=http://firmware.openbsd.org/firmware/${HTTP_FWDIR} -FWPUB_KEY=${DESTDIR}/etc/signify/openbsd-${VERSION}-fw.pub +unset DMESG +unset FWURL +unset FWPUB_KEY DRYRUN=false integer VERBOSE=0 @@ -251,7 +244,7 @@ devices_in_dmesg() { ' # The dmesg can contain multiple boots, only look in the last one - _dmesgtail="$( echo ; sed -n 'H;/^OpenBSD/h;${g;p;}' /var/run/dmesg.boot )" + _dmesgtail="$( echo ; sed -n 'H;/^OpenBSD/h;${g;p;}' "$DMESG" )" grep -v '^[[:space:]]*#' "$FWPATTERNS" | while read -r _d _m; do @@ -489,6 +482,31 @@ unregister_firmware() { return 1 } +set_fw_paths() { + local _version="${VNAME:-}" _fwdir + unset VNAME + + if [ ! "$_version" ]; then + _version=$(sed -nE \ + '/^OpenBSD ([0-9]+\.[0-9][^ ]*) .*/{s//\1/;h;};${g;p;}' \ + "$DMESG") + + # If VNAME was set in the environment instead of the DMESG, + # looking in the DMESG for "current" is wrong. + # Setting VNAME is undocumented anyway. + [ "${_version#*-}" = current ] && _fwdir=snapshots + + _version=${_version%-*} + fi + + [ "${FWURL:-}" ] || + FWURL=http://firmware.openbsd.org/firmware/${_fwdir:-$_version} + + # TODO: Would it be better to use the untrosted comment in CFILE? + _version=${_version%.*}${_version#*.} + FWPUB_KEY=${DESTDIR}/etc/signify/openbsd-${_version}-fw.pub +} + usage() { echo "usage: ${0##*/} [-adFlnv] [-p path] [driver | file ...]" exit 1 @@ -496,11 +514,14 @@ usage() { ALL=false LIST=false -while getopts :adFlnp:v name +DMESG=/var/run/dmesg.boot + +while getopts :adD:Flnp:v name do case "$name" in a) ALL=true ;; d) DELETE=true ;; + D) DMESG="$OPTARG" ;; F) INSTALL=false ;; l) LIST=true ;; n) DRYRUN=true ;; @@ -524,15 +545,6 @@ shift $((OPTIND - 1)) # Progress bars, not spinner When VERBOSE > 1 ((VERBOSE > 1)) && ENABLE_SPINNER=false -if [[ $FWURL != @(ftp|http?(s))://* ]]; then - FWURL="${FWURL#file:}" - ! [ -d "$FWURL" ] && - warn "The path must be a URL or an existing directory" && - exit 1 - DOWNLOAD=false - FWURL="file:$FWURL" -fi - if [ -x /usr/bin/id ] && [ "$(/usr/bin/id -u)" != 0 ]; then if ! "$INSTALL" || "$LIST"; then # When we aren't in the installer, @@ -544,6 +556,29 @@ if [ -x /usr/bin/id ] && [ "$(/usr/bin/i fi fi +if [ "${FWURL:-}" ] && ! "$INSTALL" ; then + warn "Cannot use -F and -p" + usage +fi + +if [ ! -s "$DMESG" ]; then + warn "${0##*/}: $DMESG: No such file or directory" + exit 1 +fi + +set_fw_paths + +if [[ $FWURL != @(ftp|http?(s))://* ]]; then + FWURL="${FWURL#file:}" + ! [ -d "$FWURL" ] && + warn "The path must be a URL or an existing directory" && + exit 1 + + DOWNLOAD=false + LOCALSRC="$FWURL" + FWURL="file:$FWURL" +fi + set -sA devices -- "$@" FD_DIR="$( tmpdir "${DESTDIR}/tmp/${0##*/}-fd" )" @@ -629,7 +664,7 @@ if "$DELETE"; then exit fi -! "$INSTALL" && ! "$LIST" && LOCALSRC="${LOCALSRC:-.}" +! "$INSTALL" && ! "$LIST" && ! "$DRYRUN" && LOCALSRC="${LOCALSRC:-.}" if [ ! "$LOCALSRC" ]; then LOCALSRC="$( tmpdir "${DESTDIR}/tmp/${0##*/}" )"