git: 31c97d270796 - stable/15 - iwlwifi: firmware: reduce script to extract fwget information

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Tue, 19 May 2026 00:43:36 UTC
The branch stable/15 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=31c97d270796ef0626b2cd9e979553ebc61007f1

commit 31c97d270796ef0626b2cd9e979553ebc61007f1
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-05-17 23:25:21 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-05-19 00:43:14 +0000

    iwlwifi: firmware: reduce script to extract fwget information
    
    Due to driver changes it is no longer feasible to extract the full
    PCI ID / firmware / card type information in one go as we used to
    be able to.
    We have already changed the way we extract firmware information for
    ports and marked the iwlwififw.4 man page as obsolete.
    
    Reduce the script to simply extarct the fwget(8) information and,
    compared to the old times, sort each section so diffs will be easier
    to see in the future.  This was particular helpful this time to make
    sure we do not lose entries with the change of technique.
    
    We also keep the script in the best perl spirit to do the job but
    not to win a price, especially given it seems we have to change
    matters every (other) year.
    
    Given we can no longer extract firmware information for the PCI IDs,
    we need to "manually" check against the ports that names match.
    Ideally we will simplify things for everything "mld-only" one day
    to only have a single firmware package for these (even if size
    increases slightly).
    
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit 4f6c60c3d3c44aa3df23f280f2fe247f7a930efa)
---
 sys/contrib/dev/iwlwifi/zzz_fw_ports_fwget.sh | 444 +++++---------------------
 1 file changed, 85 insertions(+), 359 deletions(-)

diff --git a/sys/contrib/dev/iwlwifi/zzz_fw_ports_fwget.sh b/sys/contrib/dev/iwlwifi/zzz_fw_ports_fwget.sh
index afbd52b9fa40..c817aff071bf 100644
--- a/sys/contrib/dev/iwlwifi/zzz_fw_ports_fwget.sh
+++ b/sys/contrib/dev/iwlwifi/zzz_fw_ports_fwget.sh
@@ -2,376 +2,102 @@
 #-
 # SPDX-License-Identifier: BSD-2-Clause
 #
-# Copyright (c) 2024-2025 The FreeBSD Foundation
+# Copyright (c) 2024-2026 The FreeBSD Foundation
 #
 # This software was developed by Björn Zeeb
 # under sponsorship from the FreeBSD Foundation.
 #
 # This is neither efficient nor elegant but we need it few times
-# a year and it does the job.
-#
-#
-# USAGE: please check out the correct tag/hash for ports in the
-# linux-firmware.git repository you point this script to.
-#
-# USAGE: please make sure to pre-load if_iwlwifi.ko so that we
-# have access to the sysctl.  You do not need to have a supported
-# card in the system.
-# In case that is not possible you can save the results to a file
-# and provide that locally.  It will be renamed at the end of the
-# run.
+# a year and it does the job.  And it turns out there is a lot of
+# churn so keep the solutions quick and dirty.
 #
 
 set -e
 
-# sysctl -n compat.linuxkpi.iwlwifi_pci_ids_name > iwlwifi_pci_ids_name.txt
-PCI_IDS_FILE=iwlwifi_pci_ids_name.txt
-D_PCI_IDS_FILE=`pwd`/${PCI_IDS_FILE}
-
-################################################################################
-#
-# Check pre-reqs
-#
-if [ $# -ne 1 ]; then
-	printf "USAGE: %s /path/to/linux-firmware.git\n" $0 >&2
-	exit 1
-fi
-
-if [ ! -d cfg/ -o ! -e cfg/bz.c ]; then
-	printf "ERROR: run from iwlwifi driver directory; no cfg/bz.c here\n" >&2
-	exit 1
-fi
-
-LFWDIR=${1}
-if test ! -d ${LFWDIR} -o ! -e ${LFWDIR}/WHENCE; then
-	printf "ERROR: cannot find linux-firmware.git at '%s'\n" ${LFWDIR} >&2
-	exit 1
-fi
-
-if test -r ${D_PCI_IDS_FILE}; then
-	printf "NOTICE: using proovided ${D_PCI_IDS_FILE}\n" >&2
-else
-
-	kldstat -n if_iwlwifi.ko > /dev/null 2>&1
-	rc=$?
-	case ${rc} in
-	0)	;;
-	*)	printf "ERROR: please pre-load if_iwlwifi.ko (you do not need a device)\n" >&2
-		exit 1
-		;;
-	esac
-
-	sysctl -N compat.linuxkpi.iwlwifi_pci_ids_name > /dev/null 2>&1
-	rc=$?
-	case ${rc} in
-	0)	sysctl -n compat.linuxkpi.iwlwifi_pci_ids_name > ${D_PCI_IDS_FILE}
-		;;
-	*)	printf "ERROR: cannot get compat.linuxkpi.iwlwifi_pci_ids_name\n" >&2
-		exit 1
-		;;
-	esac
-fi
-
-# We need to be in the config directory for simplicity.
-cd cfg
-
-################################################################################
-
-# Get a list of all device/firmware flavors as seen/supported by the driver.
-flavors=$(awk -F\\t '{
-	if (/^$/) { next; }
-	if ($5 == "undefined") { next; }
-	print tolower($5);
-}' ${D_PCI_IDS_FILE} | sort -V | uniq)
-
-################################################################################
-#
-# Helper functions.
-#
-
-#
-# This uses a hack (cpp) to expand some macros for us and parses out the result
-# which is the firmware name with the maximum FW version supported for that
-# firmware.
-# We then go and check that said firmware actually exists in linux-firmware.git.
-# We try to find a lower version number if the "MAX" version given from the cpp
-# output does not (yet) publicly exist.
-# .pnvm files are now properly listed as MODULE_FIRMWARE so no more magic needed
-# for them.
-# Given the filename matches a "flavor" at this point, we then group all the
-# available firmware files from this flavor together and print it as a ports
-# Makefile variable.
-#
-# We also print some other meta-data that callers will filter out depending on
-# their needs to generate other lists and mappings.
-#
+unsortedf=$(mktemp -p /tmp iwlwifi-fwget-unsorted.XXXXXX)
+sortedf=$(mktemp -p /tmp iwlwifi-fwget-sorted.XXXXXX)
+:> ${unsortedf}
+:> ${sortedf}
 
-# For each get a list of firmware names we know.
-list_fw()
-{
-	for f in ${flavors}; do
-		#echo "==> ${f}"
-		#awk -F \\t -v flav=${f} '{
-		#	if ($5 != flav) { next; }
-		#	# No firmwre; skip.
-		#	if ($3 ~ /^$/) { next; }
-		#	if ($3 == "(null)") { next; };
-		#	print $3;
-		#}' ${D_PCI_IDS_FILE} | sort | uniq
-
-		# For now the flavor names and the file names are 1:1 which makes this
-		# a lot easier (given some sysctl/file entries are not able to list
-		# their firmware but we know their "flavor".
-		l=$(cpp ${f}.c 2>&1 | awk '
-			/^MODULE_FIRMWARE\(/ {
-				gsub(/"/, "");
-				gsub("__stringify\\(", "");
-				gsub("\\);$", "");
-				gsub("\\)", "");
-				gsub("^MODULE_FIRMWARE\\(", "");
-				gsub(" ", "");
-				printf "%s\n", $0;
-		}' | sort -V | uniq)
-		#echo "${l}"
-
-		lx=""
-		for fx in ${l}; do
-			if test -e ${LFWDIR}/${fx}; then
-				lx="${lx} ${fx}"
-
-				# Check for matching .pnvm file.
-				# They are now properly listed in MODULE_FIRMWARE() as well so no more magic.
-				#px=$(echo ${fx} | awk '{ gsub("-[[:digit:]]*.ucode", ".pnvm"); print; }')
-				#if test -e ${LFWDIR}/${px}; then
-				#	lx="${lx} ${px}"
-				#fi
-			else
-				case "${fx}" in
-				*.pnvm)
-					printf "NOTICE: pnvm file not found for '%s'\n" ${fx} >&2
-					;;
-				*.ucode)
-					# Try lowering the version number.
-					bn=$(echo ${fx} | awk '{ gsub("-[[:digit:]]*.ucode", ""); print; }')
-					vn=$(echo ${fx} | awk '{ gsub(".ucode$", ""); gsub("^.*-", ""); print; }')
-					#echo "BN ${bn} VN ${vn}"
-					# Single digits are not zero-padded so just ${i} will be fine.
-					for i in `jot ${vn} ${vn} 1`; do
-						xn="${bn}-${i}.ucode"
-						if test -e ${LFWDIR}/${xn}; then
-							lx="${lx} ${xn}"
-							break
-						fi
-					done
-					;;
-				*)
-					printf "NOTICE: file for unknown firmware type not found for '%s'\n" ${fx} >&2
-					;;
-				esac
-			fi
-		done
-
-		# Get a count so we can automatically add \\ apart from the last line.
-		fn=$(echo "${lx}" | wc -w | awk '{ print $1 }')
-
-		#echo "==> ${f} :: ${fn} :: ${lx}"
-
-		if test ${fn} -gt 0; then
-
-			# Ports FLAVOR names are [a-z0-9_].  If needed add more mangling magic here.
-			flav=`echo ${f} | awk '{ printf "%s", tolower($0); }'`
-
-			echo "FWS ${flav}"
-			echo "DISTFILES_${flav}= \\"
-			for fz in ${lx}; do echo "${fz}"; done | \
-			awk -v fn=$fn -v fwg=${flav} '{
-				if (FNR == fn) { x="" } else { x=" \\" };
-				printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x;
-				fwn=$0;
-				gsub("-[[:digit:]]*\.ucode$", "", fwn);
-				printf "FWGET %s %s\n", fwg, fwn;
-			}'
-		fi
-
-	done
+cpp -DCONFIG_IWLMVM -DCONFIG_IWLMLD \
+    -I../../../compat/linuxkpi/common/include pcie/drv.c 2> /dev/null | \
+grep __builtin_choose_expr | \
+awk 'BEGIN {
+	lt=""
 }
-
-################################################################################
-#
-# Generate the PORTS file template.
-#
-
-fwsl=$(list_fw | grep ^FWS | awk '{ print $2 }')
-# Get a count so we can automatically add \\ apart from the last line.
-fn=$(echo "${fwsl}" | wc -w | awk '{ print $1 }')
-
-if test ${fn} -gt 0; then
-
-	portsfile=$(mktemp -p /tmp iwlwifi-fwport.XXXXXX)
-
-	:> ${portsfile}
-	(
-	echo "FWSUBS= \\"
-	for sz in ${fwsl}; do echo "${sz}"; done | \
-	awk -v fn=$fn '{ if (FNR == fn) { x="" } else { x=" \\" }; printf "\t%s%s\n", $0, x; }'
-
-	echo
-	echo "# Do not prefix with empty \${FWSUBDIR}/!"
-	list_fw | grep -v ^FWS | grep -v ^FWGET
-
-	echo
-	echo "DISTFILES_\${FWDRV}= \\"
-	for sz in ${fwsl}; do echo "${sz}"; done | \
-	awk -v fn=$fn '{ if (FNR == fn) { x="" } else { x=" \\" }; printf "\t${DISTFILES_%s}%s\n", $0, x; }'
-	echo "DISTFILES_\${FWDRV}_lic="
-	) >> ${portsfile}
-
-	printf "INFO: wifi-firmware-iwlwifi-kmod template at %s\n" ${portsfile} >&2
-fi
-
-################################################################################
-#
-# Generate a temporary firmware -> flavor mapping table for fwget generation.
-#
-
-mapfile=$(mktemp -p /tmp iwlwifi-mapfile.XXXXXX)
-:> ${mapfile}
-
-fwgl=$(list_fw | grep FWGET)
-# Get a count so we can automatically add \\ apart from the last line.
-fn=$(echo "${fwgl}" | wc -w | awk '{ print $1 }')
-if test ${fn} -gt 0; then
-
-	(
-	list_fw | grep FWGET | grep -v '.pnvm' | \
-	while read x flav fw; do
-		printf "%s\t%s\n" ${fw} ${flav}
-	done | \
-	sort -n | uniq
-	) >> ${mapfile}
-fi
-
-################################################################################
-#
-# Try to generate the PCI ID -> port flavor mapping
-#
-# We get PCI ID, description, firmware base from the sysctl and can work our
-# way back from fw name base to flavor via the mapping table file.
-#
-
-fwgetfile=$(mktemp -p /tmp iwlwifi-fwget.XXXXXX)
-:> ${fwgetfile}
-
-awk 'BEGIN { FS="\t"; }
 {
-	# Skip empty lines.
-	if (/^$/) { next; }
-	# Skip "undefined" flavors as we have no idea what chipset.
-	if ($5 == "undefined") { next; }
-
-	# No firmware name; do not skip!
-	# All we need is the flavor, which we now always have.
-	#if ($3 == "(null)") { next; };
-
-	FLAV=tolower($5);
-
-	split($1, i, "/");
-	gsub("\t.*$", "", i[4]);
-
-	# Not an Intel Vednor ID; skip.
-	if (i[1] != "0x8086") { next; };
-
-	# No defined device ID; skip.
-	if (i[2] == "0xffff") { next; };
-
-	# Adjust wildcards or a ill-printed 0.
-	if (i[3] == "0xffffffff") { i[3] = "*"; };
-	if (i[4] == "000000") { i[4] = "0x0000"; };
-	if (i[4] == "0xffffffff") { i[4] = "*"; };
-	if (i[4] == "0xffff") { i[4] = "*"; };
-
-	printf "%s\t%s/%s/%s\n", FLAV, i[2], i[3], i[4];
-}' ${D_PCI_IDS_FILE} | \
-sort -V | uniq | \
-while read flav match; do
-
-	#flav=$(awk -v fw=$fw '{ if ($1 == fw) { print $2; } }' ${mapfile})
-	#echo "${fw} :: ${match} :: ${flav}"
-
-	if test "${flav}" != ""; then
-		printf "${flav}\t${match}\t${flav}\n"
-	else
-		#echo "NO FLAV ${fw} ${match}" >&2
-	fi
-
-done | \
-awk 'BEGIN { FS="\t"; FWN=""; }
-{
-	FW=$1;
-	if (FWN != FW) { printf "\n\t# %s\n", FW; FWN=FW; };
-
-	printf "\t%s) addpkg \"wifi-firmware-iwlwifi-kmod-%s\"; return 1 ;;\n", $2, $3;
-} END {
-	printf "\n";
-}' >> ${fwgetfile}
-
-printf "INFO: fwget pci_network_intel template at %s\n" ${fwgetfile} >&2
-
-################################################################################
-#
-# Try to build the iwlwififw.4 bits too.
-#
-
-dl=$(grep -v ^$ ${D_PCI_IDS_FILE} | uniq | \
-awk '
-{
-	# Sourt out duplicate lines.
-	if (dup[$0]++) { next; }
-
-	split($0, a, "\t");
-	ids=a[1];
-	name=a[2];
-	fw=a[3];
-	flavor=a[5];
-
-	#my ($v, $d, $sv, $sd) = split("/", $ids);
-	split(ids, i, "/");
-	gsub("^0xffff+", "any", i[1]);
-	gsub("^0xffff+", "any", i[2]);
-	gsub("^0xffff+", "any", i[3]);
-	gsub("^0xffff+", "any", i[4]);
-
-	if (name == "") { name="(unknown)"; }
-	if (fw == "") { fw="(unknown)"; }
-	if (flavor == "") { flavor="iwlwifi"; }
-	if (flavor == "undefined") { flavor="iwlwifi"; }
-
-	# iwlwififw.4
-	printf ".It \"\"\n.It %s\n.It %s Ta %s Ta %s Ta %s Ta %s Ta %s\n", name, i[1], i[2], i[3], i[4], flavor, fw;
-
-	# wiki
-	# XXX TODO possibly quote some in `` to avoid automatic linking?
-	# || PCI IDs || Chipset Name || Firmware prefix || Comment ||
-	printf "WIKI || %s / %s / %s / %s || %s || %s || ||\n", i[1], i[2], i[3], i[4], name, fw;
-	if ((FNR % 25) == 0) { printf "WIKI \n"; }
-}')
-
-manfwfile=$(mktemp -p /tmp iwlwifi-iwlwififw4.XXXXXX)
-:> ${manfwfile}
-echo "${dl}" | grep -v ^WIKI >> ${manfwfile}
-printf "INFO: share/man/man4/iwlwififw.4 template at %s\n" ${manfwfile} >&2
-
-wikifile=$(mktemp -p /tmp iwlwifi-wiki.XXXXXX)
-:> ${wikifile}
-echo "${dl}" | awk '/^WIKI / { gsub("^WIKI ", ""); print; }' >> ${wikifile}
-printf "INFO: WIKI template at %s\n" ${wikifile} >&2
-
-
-################################################################################
-#
-# Cleanup
-#
-rm ${mapfile}
-mv -f ${D_PCI_IDS_FILE} ${D_PCI_IDS_FILE}.old
+	if (!/.vendor = 0x8086,/) {
+		printf "ERROR: %s\n", $0;
+		exit
+	}
+
+	d=$6;
+	sv=$9;
+	sd=$12;
+	t=$15;
+
+
+	gsub("\\(", "", d);
+	gsub(")", "", d);
+	gsub(",", "", d);
+
+	gsub("\\(", "", sv);
+	gsub(")", "", sv);
+	gsub(",", "", sv);
+
+	gsub("\\(", "", sd);
+	gsub(")", "", sd);
+	gsub(",", "", sd);
+
+	gsub("-1U", "*", d);
+	gsub("-1U", "*", sv);
+	gsub("-1U", "*", sd);
+
+	gsub("^.*\\(", "", t);
+	gsub(")", "", t);
+	gsub(",", "", t);
+	gsub("^iwl_", "", t);
+	gsub("^iwl", "", t);
+	gsub("_mac_cfg$", "", t);
+	gsub("_.*$", "", t);
+
+	t=tolower(t)
+	if (t != lt) {
+		printf "\n\t# %s\n", t;
+		lt = t;
+	}
+	if (t == "9560") { t = "9000"; }
+	if (t == "ax200") { t = "22000"; }
+	if (t == "qu") { t = "22000"; }
+	if (t == "cc") { t = "22000"; }
+	if (t == "ma") { t = "ax210"; }
+	if (t == "so") { t = "ax210"; }
+	if (t == "ty") { t = "ax210"; }
+	if (t == "gl") { t = "bz"; }
+	if (t != "7000" && t != "8000" && t != "9000" && t != "22000" && t != "ax210" && t != "bz" && t != "sc") {
+		printf "ERROR: invalid flavor '%s': %s\n", t, $0;
+		exit
+	}
+
+	printf "\t%s/%s/%s) addpkg \"wifi-firmware-iwlwifi-kmod-%s\"; return 1 ;;\n", tolower(d), tolower(sv), tolower(sd), t;
+
+}' > ${unsortedf}
+
+( for f in \
+        7000 \
+        8000 \
+        9000 \
+        22000 \
+        ax210 \
+        bz \
+        sc ; do
+
+	printf "\n\t# %s\n" ${f}
+	grep "wifi-firmware-iwlwifi-kmod-${f}" ${unsortedf} | sort -n
+
+done; echo ) > ${sortedf}
+
+rm -f ${unsortedf}
+printf "INFO: fwget(8) template at %s\n" ${sortedf} >&2
 
 # end