This patch will "unregister" a firmware package if we detect that it has
moved into the base system by removing the package files in /var/db/pkg
and leaving the files in /etc/firmware alone.

This situation is detected with a special entry in the firmware_patterns
file where the "pattern" is "INBASE" instead of an actual pattern.
Normally pkg_add stores that information in the quirks package, but we
don't have easy access to that, so overloading the firmware_patterns
file seemed the best course of action.  If folks have a better idea
where we could learn that a firmware now comes with the base system, I'd
be interested in suggestions.

Comments, OK?

Index: usr.sbin/fw_update/fw_update.sh
===================================================================
RCS file: /cvs/src/usr.sbin/fw_update/fw_update.sh,v
retrieving revision 1.31
diff -u -p -r1.31 fw_update.sh
--- usr.sbin/fw_update/fw_update.sh     22 Jan 2022 05:03:47 -0000      1.31
+++ usr.sbin/fw_update/fw_update.sh     24 Jan 2022 01:58:07 -0000
@@ -157,6 +157,7 @@ firmware_in_dmesg() {
        grep -v '^[[:space:]]*#' "$FWPATTERNS" |
            while read -r _d _m; do
                [ "$_d" = "$_last" ] && continue
+               [ "$_m" = INBASE ]   && continue
                [ "$_m" ]             || _m="${_nl}${_d}[0-9] at "
                [ "$_m" = "${_m#^}" ] || _m="${_nl}${_m#^}"
 
@@ -170,9 +171,7 @@ firmware_in_dmesg() {
 firmware_filename() {
        local _f
        [ -e "$CFILE" ] || fetch_cfile || return 1
-       _f="$( sed -n "s/.*(\($1-firmware-.*\.tgz\)).*/\1/p" "$CFILE" | sed 
'$!d' )"
-       ! [ "$_f" ] && echo "Unable to find firmware for $1" >&2 && return 1
-       echo "$_f"
+       sed -n "s/.*(\($1-firmware-.*\.tgz\)).*/\1/p" "$CFILE" | sed '$!d'
 }
 
 firmware_devicename() {
@@ -252,6 +251,21 @@ EOL
        unset FWPKGTMP
 }
 
+remove_files() {
+       # Use rm -f, not removing files/dirs is probably not worth failing over
+       for _r in "$@" ; do
+               if [ -d "$_r" ]; then
+                       # The installer lacks rmdir,
+                       # but we only want to remove empty directories.
+                       set +o noglob
+                       [ "$_r/*" = "$( echo "$_r"/* )" ] && rm -rf "$_r"
+                       set -o noglob
+               else
+                       rm -f "$_r"
+               fi
+       done
+}
+
 delete_firmware() {
        local _cwd _pkg="$1" _pkgdir="${DESTDIR}/var/db/pkg"
 
@@ -278,24 +292,32 @@ delete_firmware() {
                esac
        done < "${_pkgdir}/${_pkg}/+CONTENTS"
 
-       # Use rm -f, not removing files/dirs is probably not worth failing over
-       for _r in "${_remove[@]}" ; do
-               if [ -d "$_r" ]; then
-                       # The installer lacks rmdir,
-                       # but we only want to remove empty directories.
-                       set +o noglob
-                       [ "$_r/*" = "$( echo "$_r"/* )" ] && rm -rf "$_r"
-                       set -o noglob
-               else
-                       rm -f "$_r"
-               fi
-       done
+       remove_files "${_remove[@]}"
 
        ((VERBOSE > 2)) && echo " done."
 
        return 0
 }
 
+unregister_if_moved_to_base() {
+       local _d="$1" _pkgdir="${DESTDIR}/var/db/pkg"
+       grep -q "^$_d[[:space:]]*INBASE" "$FWPATTERNS" || return 1
+
+       set -A installed -- $( installed_firmware '' "$d-firmware-" '*' )
+       if [ "${installed:-}" ]; then
+               for fw in "${installed[@]}"; do
+                       ((VERBOSE)) && echo "Unregister $fw"
+                       "$DRYRUN" && continue
+                       remove_files \
+                           "$_pkgdir/$fw/+CONTENTS" \
+                           "$_pkgdir/$fw/+DESC" \
+                           "$_pkgdir/$fw/"
+               done
+       fi
+
+       return 0
+}
+
 usage() {
        echo "usage: ${0##*/} [-adFnv] [-p path] [driver | file ...]"
        exit 2
@@ -430,13 +452,21 @@ fi
 added=''
 updated=''
 kept=''
+unregister=''
 for f in "${devices[@]}"; do
        d="$( firmware_devicename "$f" )"
 
        verify_existing="$DOWNLOAD"
        if [ "$f" = "$d" ]; then
                f=$( firmware_filename "$d" || true )
-               [ "$f" ] || continue
+               if [ ! "$f" ]; then
+                       if "$INSTALL" && unregister_if_moved_to_base "$d"; then
+                               unregister="$unregister,$d"
+                       else
+                               echo "Unable to find firmware for $d" >&2
+                       fi
+                       continue
+               fi
                f="$LOCALSRC/$f"
        elif ! "$INSTALL" && ! grep -Fq "($f)" "$CFILE" ; then
                echo "Cannot download local file $f" >&2
@@ -532,8 +562,9 @@ done
 added="${added:#,}"
 updated="${updated:#,}"
 kept="${kept:#,}"
+[ "${unregister:-}" ] && unregister="; unregistered ${unregister:#,}"
 if "$INSTALL"; then
-       echo  "${0##*/}: added ${added:-none}; updated ${updated:-none}; kept 
${kept:-none}"
+       echo  "${0##*/}: added ${added:-none}; updated ${updated:-none}; kept 
${kept:-none}${unregister}"
 else
-       echo  "${0##*/}: downloaded ${added:-none}; kept ${kept:-none}"
+       echo  "${0##*/}: downloaded ${added:-none}; kept 
${kept:-none}${unregister}"
 fi
Index: usr.sbin/fw_update/patterns.c
===================================================================
RCS file: /cvs/src/usr.sbin/fw_update/patterns.c,v
retrieving revision 1.1
diff -u -p -r1.1 patterns.c
--- usr.sbin/fw_update/patterns.c       5 Jan 2022 16:24:29 -0000       1.1
+++ usr.sbin/fw_update/patterns.c       24 Jan 2022 01:58:07 -0000
@@ -109,10 +109,10 @@ main(void)
        printf("%s\n", "radeondrm");
        print_devices("radeondrm", radeon_devices, nitems(radeon_devices));
        printf("%s\n", "rsu");
-       printf("%s\n", "rtwn");
+       printf("%s\n", "rtwn INBASE");
        printf("%s\n", "uath");
        printf("%s\n", "upgt");
-       printf("%s\n", "urtwn");
+       printf("%s\n", "urtwn INBASE");
        printf("%s\n", "uvideo");
        printf("%s\n", "vmm");
        printf("%s\n", "wpi");

Reply via email to