Path: blob/main/sys/contrib/dev/iwlwifi/zzz_fw_ports_fwget.sh
48253 views
#!/bin/sh1#-2# SPDX-License-Identifier: BSD-2-Clause3#4# Copyright (c) 2024-2025 The FreeBSD Foundation5#6# This software was developed by Björn Zeeb7# under sponsorship from the FreeBSD Foundation.8#9# This is neither efficient nor elegant but we need it few times10# a year and it does the job.11#12#13# USAGE: please check out the correct tag/hash for ports in the14# linux-firmware.git repository you point this script to.15#16# USAGE: please make sure to pre-load if_iwlwifi.ko so that we17# have access to the sysctl. You do not need to have a supported18# card in the system.19# In case that is not possible you can save the results to a file20# and provide that locally. It will be renamed at the end of the21# run.22#2324set -e2526# sysctl -n compat.linuxkpi.iwlwifi_pci_ids_name > iwlwifi_pci_ids_name.txt27PCI_IDS_FILE=iwlwifi_pci_ids_name.txt28D_PCI_IDS_FILE=`pwd`/${PCI_IDS_FILE}2930################################################################################31#32# Check pre-reqs33#34if [ $# -ne 1 ]; then35printf "USAGE: %s /path/to/linux-firmware.git\n" $0 >&236exit 137fi3839if [ ! -d cfg/ -o ! -e cfg/bz.c ]; then40printf "ERROR: run from iwlwifi driver directory; no cfg/bz.c here\n" >&241exit 142fi4344LFWDIR=${1}45if test ! -d ${LFWDIR} -o ! -e ${LFWDIR}/WHENCE; then46printf "ERROR: cannot find linux-firmware.git at '%s'\n" ${LFWDIR} >&247exit 148fi4950if test -r ${D_PCI_IDS_FILE}; then51printf "NOTICE: using proovided ${D_PCI_IDS_FILE}\n" >&252else5354kldstat -n if_iwlwifi.ko > /dev/null 2>&155rc=$?56case ${rc} in570) ;;58*) printf "ERROR: please pre-load if_iwlwifi.ko (you do not need a device)\n" >&259exit 160;;61esac6263sysctl -N compat.linuxkpi.iwlwifi_pci_ids_name > /dev/null 2>&164rc=$?65case ${rc} in660) sysctl -n compat.linuxkpi.iwlwifi_pci_ids_name > ${D_PCI_IDS_FILE}67;;68*) printf "ERROR: cannot get compat.linuxkpi.iwlwifi_pci_ids_name\n" >&269exit 170;;71esac72fi7374# We need to be in the config directory for simplicity.75cd cfg7677################################################################################7879# Get a list of all device/firmware flavors as seen/supported by the driver.80flavors=$(awk -F\\t '{81if (/^$/) { next; }82if ($5 == "undefined") { next; }83print tolower($5);84}' ${D_PCI_IDS_FILE} | sort -V | uniq)8586################################################################################87#88# Helper functions.89#9091#92# This uses a hack (cpp) to expand some macros for us and parses out the result93# which is the firmware name with the maximum FW version supported for that94# firmware.95# We then go and check that said firmware actually exists in linux-firmware.git.96# We try to find a lower version number if the "MAX" version given from the cpp97# output does not (yet) publicly exist.98# .pnvm files are now properly listed as MODULE_FIRMWARE so no more magic needed99# for them.100# Given the filename matches a "flavor" at this point, we then group all the101# available firmware files from this flavor together and print it as a ports102# Makefile variable.103#104# We also print some other meta-data that callers will filter out depending on105# their needs to generate other lists and mappings.106#107108# For each get a list of firmware names we know.109list_fw()110{111for f in ${flavors}; do112#echo "==> ${f}"113#awk -F \\t -v flav=${f} '{114# if ($5 != flav) { next; }115# # No firmwre; skip.116# if ($3 ~ /^$/) { next; }117# if ($3 == "(null)") { next; };118# print $3;119#}' ${D_PCI_IDS_FILE} | sort | uniq120121# For now the flavor names and the file names are 1:1 which makes this122# a lot easier (given some sysctl/file entries are not able to list123# their firmware but we know their "flavor".124l=$(cpp ${f}.c 2>&1 | awk '125/^MODULE_FIRMWARE\(/ {126gsub(/"/, "");127gsub("__stringify\\(", "");128gsub("\\);$", "");129gsub("\\)", "");130gsub("^MODULE_FIRMWARE\\(", "");131gsub(" ", "");132printf "%s\n", $0;133}' | sort -V | uniq)134#echo "${l}"135136lx=""137for fx in ${l}; do138if test -e ${LFWDIR}/${fx}; then139lx="${lx} ${fx}"140141# Check for matching .pnvm file.142# They are now properly listed in MODULE_FIRMWARE() as well so no more magic.143#px=$(echo ${fx} | awk '{ gsub("-[[:digit:]]*.ucode", ".pnvm"); print; }')144#if test -e ${LFWDIR}/${px}; then145# lx="${lx} ${px}"146#fi147else148case "${fx}" in149*.pnvm)150printf "NOTICE: pnvm file not found for '%s'\n" ${fx} >&2151;;152*.ucode)153# Try lowering the version number.154bn=$(echo ${fx} | awk '{ gsub("-[[:digit:]]*.ucode", ""); print; }')155vn=$(echo ${fx} | awk '{ gsub(".ucode$", ""); gsub("^.*-", ""); print; }')156#echo "BN ${bn} VN ${vn}"157# Single digits are not zero-padded so just ${i} will be fine.158for i in `jot ${vn} ${vn} 1`; do159xn="${bn}-${i}.ucode"160if test -e ${LFWDIR}/${xn}; then161lx="${lx} ${xn}"162break163fi164done165;;166*)167printf "NOTICE: file for unknown firmware type not found for '%s'\n" ${fx} >&2168;;169esac170fi171done172173# Get a count so we can automatically add \\ apart from the last line.174fn=$(echo "${lx}" | wc -w | awk '{ print $1 }')175176#echo "==> ${f} :: ${fn} :: ${lx}"177178if test ${fn} -gt 0; then179180# Ports FLAVOR names are [a-z0-9_]. If needed add more mangling magic here.181flav=`echo ${f} | awk '{ printf "%s", tolower($0); }'`182183echo "FWS ${flav}"184echo "DISTFILES_${flav}= \\"185for fz in ${lx}; do echo "${fz}"; done | \186awk -v fn=$fn -v fwg=${flav} '{187if (FNR == fn) { x="" } else { x=" \\" };188printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x;189fwn=$0;190gsub("-[[:digit:]]*\.ucode$", "", fwn);191printf "FWGET %s %s\n", fwg, fwn;192}'193fi194195done196}197198################################################################################199#200# Generate the PORTS file template.201#202203fwsl=$(list_fw | grep ^FWS | awk '{ print $2 }')204# Get a count so we can automatically add \\ apart from the last line.205fn=$(echo "${fwsl}" | wc -w | awk '{ print $1 }')206207if test ${fn} -gt 0; then208209portsfile=$(mktemp -p /tmp iwlwifi-fwport.XXXXXX)210211:> ${portsfile}212(213echo "FWSUBS= \\"214for sz in ${fwsl}; do echo "${sz}"; done | \215awk -v fn=$fn '{ if (FNR == fn) { x="" } else { x=" \\" }; printf "\t%s%s\n", $0, x; }'216217echo218echo "# Do not prefix with empty \${FWSUBDIR}/!"219list_fw | grep -v ^FWS | grep -v ^FWGET220221echo222echo "DISTFILES_\${FWDRV}= \\"223for sz in ${fwsl}; do echo "${sz}"; done | \224awk -v fn=$fn '{ if (FNR == fn) { x="" } else { x=" \\" }; printf "\t${DISTFILES_%s}%s\n", $0, x; }'225echo "DISTFILES_\${FWDRV}_lic="226) >> ${portsfile}227228printf "INFO: wifi-firmware-iwlwifi-kmod template at %s\n" ${portsfile} >&2229fi230231################################################################################232#233# Generate a temporary firmware -> flavor mapping table for fwget generation.234#235236mapfile=$(mktemp -p /tmp iwlwifi-mapfile.XXXXXX)237:> ${mapfile}238239fwgl=$(list_fw | grep FWGET)240# Get a count so we can automatically add \\ apart from the last line.241fn=$(echo "${fwgl}" | wc -w | awk '{ print $1 }')242if test ${fn} -gt 0; then243244(245list_fw | grep FWGET | grep -v '.pnvm' | \246while read x flav fw; do247printf "%s\t%s\n" ${fw} ${flav}248done | \249sort -n | uniq250) >> ${mapfile}251fi252253################################################################################254#255# Try to generate the PCI ID -> port flavor mapping256#257# We get PCI ID, description, firmware base from the sysctl and can work our258# way back from fw name base to flavor via the mapping table file.259#260261fwgetfile=$(mktemp -p /tmp iwlwifi-fwget.XXXXXX)262:> ${fwgetfile}263264awk 'BEGIN { FS="\t"; }265{266# Skip empty lines.267if (/^$/) { next; }268# Skip "undefined" flavors as we have no idea what chipset.269if ($5 == "undefined") { next; }270271# No firmware name; do not skip!272# All we need is the flavor, which we now always have.273#if ($3 == "(null)") { next; };274275FLAV=tolower($5);276277split($1, i, "/");278gsub("\t.*$", "", i[4]);279280# Not an Intel Vednor ID; skip.281if (i[1] != "0x8086") { next; };282283# No defined device ID; skip.284if (i[2] == "0xffff") { next; };285286# Adjust wildcards or a ill-printed 0.287if (i[3] == "0xffffffff") { i[3] = "*"; };288if (i[4] == "000000") { i[4] = "0x0000"; };289if (i[4] == "0xffffffff") { i[4] = "*"; };290if (i[4] == "0xffff") { i[4] = "*"; };291292printf "%s\t%s/%s/%s\n", FLAV, i[2], i[3], i[4];293}' ${D_PCI_IDS_FILE} | \294sort -V | uniq | \295while read flav match; do296297#flav=$(awk -v fw=$fw '{ if ($1 == fw) { print $2; } }' ${mapfile})298#echo "${fw} :: ${match} :: ${flav}"299300if test "${flav}" != ""; then301printf "${flav}\t${match}\t${flav}\n"302else303#echo "NO FLAV ${fw} ${match}" >&2304fi305306done | \307awk 'BEGIN { FS="\t"; FWN=""; }308{309FW=$1;310if (FWN != FW) { printf "\n\t# %s\n", FW; FWN=FW; };311312printf "\t%s) addpkg \"wifi-firmware-iwlwifi-kmod-%s\"; return 1 ;;\n", $2, $3;313} END {314printf "\n";315}' >> ${fwgetfile}316317printf "INFO: fwget pci_network_intel template at %s\n" ${fwgetfile} >&2318319################################################################################320#321# Try to build the iwlwififw.4 bits too.322#323324dl=$(grep -v ^$ ${D_PCI_IDS_FILE} | uniq | \325awk '326{327# Sourt out duplicate lines.328if (dup[$0]++) { next; }329330split($0, a, "\t");331ids=a[1];332name=a[2];333fw=a[3];334flavor=a[5];335336#my ($v, $d, $sv, $sd) = split("/", $ids);337split(ids, i, "/");338gsub("^0xffff+", "any", i[1]);339gsub("^0xffff+", "any", i[2]);340gsub("^0xffff+", "any", i[3]);341gsub("^0xffff+", "any", i[4]);342343if (name == "") { name="(unknown)"; }344if (fw == "") { fw="(unknown)"; }345if (flavor == "") { flavor="iwlwifi"; }346if (flavor == "undefined") { flavor="iwlwifi"; }347348# iwlwififw.4349printf ".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;350351# wiki352# XXX TODO possibly quote some in `` to avoid automatic linking?353# || PCI IDs || Chipset Name || Firmware prefix || Comment ||354printf "WIKI || %s / %s / %s / %s || %s || %s || ||\n", i[1], i[2], i[3], i[4], name, fw;355if ((FNR % 25) == 0) { printf "WIKI \n"; }356}')357358manfwfile=$(mktemp -p /tmp iwlwifi-iwlwififw4.XXXXXX)359:> ${manfwfile}360echo "${dl}" | grep -v ^WIKI >> ${manfwfile}361printf "INFO: share/man/man4/iwlwififw.4 template at %s\n" ${manfwfile} >&2362363wikifile=$(mktemp -p /tmp iwlwifi-wiki.XXXXXX)364:> ${wikifile}365echo "${dl}" | awk '/^WIKI / { gsub("^WIKI ", ""); print; }' >> ${wikifile}366printf "INFO: WIKI template at %s\n" ${wikifile} >&2367368369################################################################################370#371# Cleanup372#373rm ${mapfile}374mv -f ${D_PCI_IDS_FILE} ${D_PCI_IDS_FILE}.old375376# end377378379