diff --git a/sys/contrib/dev/iwlwifi/zzz_fw_ports_fwget.sh b/sys/contrib/dev/iwlwifi/zzz_fw_ports_fwget.sh index afbd52b9fa4..c817aff071b 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} +unsortedf=$(mktemp -p /tmp iwlwifi-fwget-unsorted.XXXXXX) +sortedf=$(mktemp -p /tmp iwlwifi-fwget-sorted.XXXXXX) +:> ${unsortedf} +:> ${sortedf} -################################################################################ -# -# 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. -# - -# 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; } + if (!/.vendor = 0x8086,/) { + printf "ERROR: %s\n", $0; + exit + } - # 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 + d=$6; + sv=$9; + sd=$12; + t=$15; -################################################################################ -# -# Cleanup -# -rm ${mapfile} -mv -f ${D_PCI_IDS_FILE} ${D_PCI_IDS_FILE}.old + 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