diff --git a/sys/contrib/dev/athk/ath10k/zzz_fw_ports_fwget.sh b/sys/contrib/dev/athk/ath10k/zzz_fw_ports_fwget.sh new file mode 100644 index 000000000000..71a11a890a48 --- /dev/null +++ b/sys/contrib/dev/athk/ath10k/zzz_fw_ports_fwget.sh @@ -0,0 +1,286 @@ +#!/bin/sh +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2024 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. +# + +set -e + +DRIVER=ath10k +CHECKFILE=qmi_wlfw_v01.c + +################################################################################ +# +# Check pre-reqs +# +if [ $# -ne 1 ]; then + printf "USAGE: %s /path/to/linux-firmware.git\n" $0 >&2 + exit 1 +fi + +if [ ! -e ${CHECKFILE} ]; then + printf "ERROR: run from %s driver directory; no %s.c here\n" ${DRIVER} ${CHECKFILE} >&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 + +################################################################################ +# +# Helper functions. +# +# This uses a hack (cpp) to expand some macros for us and parses out the result +# which is the PCI device ID or the firmware directory for that. +# Checking MODULE_FIRMWARE was pointless as it had too many "dead" entries: +# NOTICE: no firmware file found for 'ath10k/QCA6174/hw2.1/firmware-4.bin' +# NOTICE: no firmware file found for 'ath10k/QCA6174/hw3.0/firmware-5.bin' +# NOTICE: no firmware file found for 'ath10k/QCA9887/hw1.0/board-2.bin' +# NOTICE: no firmware file found for 'ath10k/QCA988X/hw2.0/board-2.bin' +# NOTICE: no firmware file found for 'ath10k/QCA988X/hw2.0/firmware-2.bin' +# NOTICE: no firmware file found for 'ath10k/QCA988X/hw2.0/firmware-3.bin' +# +list_fw() +{ + # List of already seen flavor (firmware directory). + sfwl="" + + # List of "supported" device IDs (ignoring Ubiquity). + devidl=$(cpp pci.c 2> /dev/null | awk '/PCI_VDEVICE\(ATHEROS,/ { gsub("^.*, \\(", ""); gsub("\\)\\) },$", ""); print tolower($0); }') + + # List of (device ID) -> (firware directory) mappings. + cpp core.c 2> /dev/null | egrep -E '\.(dev_id|dir) = ' | awk '{ if (/dev_id/) { printf "%s", $0; } else { print; } }' | grep -v 'dev_id = 0,' | sort | uniq | \ + awk '{ + gsub("^.*\\(", ""); + gsub("),.* = ", "\t"); + gsub(",$", ""); + gsub(/"/, ""); + gsub(" ", ""); + print; + }' | \ + while read did fwd; do + + x="" + for d in ${devidl}; do + if test "${did}" == "${d}"; then + x="${d}" + break + fi + done + if test "${x}" == ""; then + # Device ID not in the list of PCI IDs we support. + # At least the Ubiquity one we hit here. + #printf "Device ID %s (%s) not in PCI ID list; skipping\n" ${did} ${fwd} >&2 + continue + fi + + if test ! -d ${LFWDIR}/${fwd}; then + # Leave this on as it MUST not happen. + printf "Firmware dir %s (for %s) does not exist; skipping\n" ${fwd} ${did} >&2 + continue + fi + + flav=$(echo "${fwd}" | awk -v drv=${DRIVER} '{ + # Ports FLAVOR names are [a-z0-9_]. If needed add more mangling magic here. + gsub("^" drv "/", ""); + gsub("/", "_"); + gsub("\\.", ""); + print tolower($0); + }') + + # Print this first or otherwise if two device IDs have the same firmware + # we may not see that. + echo "FWGET ${did} ${flav}" + + x="" + for zf in ${sfwl}; do + if test "${zf}" == "${flav}"; then + x="${zf}" + break + fi + done + if test "${x}" != ""; then + #printf "Flavor %s (firmware directory %s) already seen; skipping\n" ${flav} ${fwd} >&2 + continue + fi + sfwl="${sfwl} ${flav}" + + #echo "==> ${did} -> ${fwd} -> ${flav}" + + lx=$(cd ${LFWDIR} && find ${fwd} -type f \! -name "*sdio*" -a \! -name "*.txt" -print) + + # Get a count so we can automatically add \\ apart from the last line. + fn=$(echo "${lx}" | wc -w | awk '{ print $1 }') + + #echo "==> ${flav} :: ${fn} :: ${lx}" >&2 + + if test ${fn} -gt 0; then + + echo "FWS ${flav}" + echo "DISTFILES_${flav}= \\" + for fz in ${lx}; do echo "${fz}"; done | \ + awk -v fn=$fn -v fwg=${flav} -v drv=${DRIVER} '{ + if (FNR == fn) { x="" } else { x=" \\" }; + gsub("^" drv "/", "${FWSUBDIR}/"); + printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; + }' + + # Check for "lic" files. + lx=$(cd ${LFWDIR} && find ${fwd} -type f \! -name "*sdio*" -a -name "*.txt" -print) + + # Get a count so we can automatically add \\ apart from the last line. + fn=$(echo "${lx}" | wc -w | awk '{ print $1 }') + + if test ${fn} -gt 0; then + echo "FWL ${flav}" + echo "DISTFILES_${flav}_lic= \\" + for fz in ${lx}; do echo "${fz}"; done | \ + awk -v fn=$fn -v fwg=${flav} -v drv=${DRIVER} '{ + if (FNR == fn) { x="" } else { x=" \\" }; + gsub("^" drv "/", "${FWSUBDIR}/"); + printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; + }' + fi + fi + done +} + +################################################################################ +# +# 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 ${DRIVER}-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 + list_fw | grep -v ^FWS | grep -v ^FWL | 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; + }' + + fwsl=$(list_fw | grep ^FWL | 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 + echo "DISTFILES_\${FWDRV}_lic= \\" + for sz in ${fwsl}; do echo "${sz}"; done | \ + awk -v fn=$fn '{ + if (FNR == fn) { x="" } else { x=" \\" }; + printf "\t${DISTFILES_%s_lic}%s\n", $0, x; + }' + else + echo "DISTFILES_\${FWDRV}_lic=" + fi + + ) >> ${portsfile} + + printf "INFO: wifi-firmware-%s-kmod template at %s\n" ${DRIVER} ${portsfile} >&2 +fi + +################################################################################ +# +# Generate the fwget(8) case pattern table (PCI device ID -> fw port flavor). +# + +fwgetfile=$(mktemp -p /tmp ${DRIVER}-fwget.XXXXXX) +:> ${fwgetfile} + +fwsl=$(list_fw | grep ^FWGET | sort) +# Get a count so we can automatically add \\ apart from the last line. +fn=$(echo "${fwsl}" | grep -c FWGET | awk '{ print $1 }') + +if test ${fn} -gt 0; then + + # We need to check for same ID with multiple firmware. + # The list ist sorted by ID so duplicates are next to each other. + cs=$(echo "${fwsl}" | awk '{ print $2 }' | uniq -c | awk '{ print $1 }') + + #echo "==> cs=${cs}" >&2 + + for n in ${cs}; do + + # Skip FWGET + fwsl=${fwsl#*[[:space:]]} + # get device ID + did=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + # get flavor + flav=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + + # printf "===> did %s flav %s\n" ${did} ${flav} >&2 + + if test ${n} -eq 1; then + echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ + printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"; return 1 ;;\n", + tolower($1), drv, tolower($2); + }' >> ${fwgetfile} + else + echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ + printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"\n", + tolower($1), drv, tolower($2); + }' >> ${fwgetfile} + + i=1 + while test ${i} -lt ${n}; do + # Skip FWGET + fwsl=${fwsl#*[[:space:]]} + # get device ID + did=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + # get flavor + flav=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + + #printf "===> did %s flav %s\n" ${did} ${flav} >&2 + + echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ + printf "\t\taddpkg \"wifi-firmware-%s-kmod-%s\"\n", + drv, tolower($2); + }' >> ${fwgetfile} + + i=$((i + 1)) + done + + printf "\t\treturn 1 ;;\n" >> ${fwgetfile} + fi + done +fi + +printf "INFO: fwget pci_network_qca %s template at %s\n" ${DRIVER} ${fwgetfile} >&2 + +# end diff --git a/sys/contrib/dev/athk/ath11k/zzz_fw_ports_fwget.sh b/sys/contrib/dev/athk/ath11k/zzz_fw_ports_fwget.sh new file mode 100644 index 000000000000..9de14ed45442 --- /dev/null +++ b/sys/contrib/dev/athk/ath11k/zzz_fw_ports_fwget.sh @@ -0,0 +1,317 @@ +#!/bin/sh +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2024 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. +# + +set -e + +DRIVER=ath11k +CHECKFILE=debugfs_htt_stats.c + +################################################################################ +# +# Check pre-reqs +# +if [ $# -ne 1 ]; then + printf "USAGE: %s /path/to/linux-firmware.git\n" $0 >&2 + exit 1 +fi + +if [ ! -e ${CHECKFILE} ]; then + printf "ERROR: run from %s driver directory; no %s.c here\n" ${DRIVER} ${CHECKFILE} >&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 +LFWDIR=${LFWDIR}/${DRIVER} + +################################################################################ +# +# Helper functions. +# +# This uses a hack (cpp) to expand some macros for us and parses out the result +# which is the PCI device ID or the firmware directory for that. +# +# Driver is there, the firmware not yet...? +# ==> 0x1101 -> ATH11K_HW_QCA6390_HW20 -> QCA6390/hw2.0 +# ==> 0x1104 -> ATH11K_HW_QCN9074_HW10 -> QCN9074/hw1.0 +# ==> 0x1103 -> ATH11K_HW_WCN6855_HW20 -> WCN6855/hw2.0 +# ==> 0x1103 -> ATH11K_HW_WCN6855_HW21 -> WCN6855/hw2.1 +# Firmware dir WCN6855/hw2.1 (for 0x1103) does not exist; skipping +# +list_fw() +{ + # List of already seen flavor (firmware directory). + sfwl="" + + # List of "supported" device IDs. + devidl=$(cpp pci.c 2> /dev/null | awk '/PCI_VDEVICE\(QCOM,/ { gsub("^.*, ", ""); gsub("\\) },$", ""); print tolower($0); }') + # Turn them into a regex. + didreg=$(echo "${devidl}" | xargs -J % echo -n % | sed -e 's, ,|,g') + # List the device ID cases along with their hw_rev which we can go and take to lookup fw. + hwrevs=$(cpp pci.c 2> /dev/null | egrep -E "(case (${didreg})|ab->hw_rev = )" | awk '{ + if (FNR > 1 && /case/) { + printf "\n"; + } + gsub("^.*case[[:space:]]*", ""); + gsub("[[:space:]]*ab->hw_rev = ", " "); + gsub("[:;]", ""); + printf "%s", $0; + }') + + # hwrevs is a list of (device IDs) -> (1..n hardware revisions) mappings. + #echo "==> ${devidl} :: ${didreg} :: ${hwrevs}" >&2 + + # List of (hardware revision) -> (firware directory) mappings. + l=$(cpp core.c 2> /dev/null | egrep -E '\.(hw_rev|dir) = ' | awk '{ if (/hw_rev/) { printf "%s", $0; } else { print; } }' | sort | uniq | \ + awk '{ + gsub("^.*hw_rev = ", ""); + gsub(",.* = ", "\t"); + gsub(",$", ""); + gsub(/"/, ""); + gsub(" ", ""); + gsub("\t", " "); + print; + }') + #echo "===> ${l}" >&2 + + ll=$(echo "${l}" | wc -w | awk '{ print $1 }') + while test "${ll}" -gt 1; do + hwr=${l%%[[:space:]]*} + l=${l#*[[:space:]]} + fwd=${l%%[[:space:]]*} + l=${l#*[[:space:]]} + + #echo "=+=> ${hwr} -> ${fwd}" >&2 + eval fwd_${hwr}=${fwd} + ll=$(echo "${l}" | wc -w | awk '{ print $1 }') + done + + echo "${hwrevs}" | \ + while read did hwrl; do + hwrn=$(echo "${hwrl}" | wc -w | awk '{ print $1 }') + if test ${hwrn} -lt 1; then + printf "Device ID %s has no hardware revisions (%s); skipping\n" "${did}" ${hwrn} >&2 + continue + fi + + for hwrx in ${hwrl}; do + + eval fwd=\${fwd_${hwrx}} + #echo "===> ${did} -> ${hwrx} -> ${fwd}" >&2 + + if test ! -d ${LFWDIR}/${fwd}; then + #printf "Firmware dir %s (for %s) does not exist; skipping\n" ${fwd} ${did} >&2 + continue + fi + + flav=$(echo "${fwd}" | awk -v drv=${DRIVER} '{ + # Ports FLAVOR names are [a-z0-9_]. If needed add more mangling magic here. + gsub("^" drv "/", ""); + gsub("/", "_"); + gsub("\\.", ""); + print tolower($0); + }') + + # Print this first or otherwise if two device IDs have the same firmware + # we may not see that. + echo "FWGET ${did} ${flav}" + + x="" + for zf in ${sfwl}; do + if test "${zf}" == "${flav}"; then + x="${zf}" + break + fi + done + if test "${x}" != ""; then + #printf "Flavor %s (firmware directory %s) already seen; skipping\n" ${flav} ${fwd} >&2 + continue + fi + sfwl="${sfwl} ${flav}" + + #echo "==> ${did} -> ${fwd} -> ${flav}" + + lx=$(cd ${LFWDIR} && find ${fwd} -type f \! -name "*sdio*" -a \! -name "*.txt" -print) + + # Get a count so we can automatically add \\ apart from the last line. + fn=$(echo "${lx}" | wc -w | awk '{ print $1 }') + + #echo "==> ${flav} :: ${fn} :: ${lx}" >&2 + + if test ${fn} -gt 0; then + + echo "FWS ${flav}" + echo "DISTFILES_${flav}= \\" + for fz in ${lx}; do echo "${fz}"; done | \ + awk -v fn=$fn -v fwg=${flav} -v drv=${DRIVER} '{ + if (FNR == fn) { x="" } else { x=" \\" }; + #gsub("^" drv "/", "${FWSUBDIR}/"); + gsub("^", "${FWSUBDIR}/"); + printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; + }' + + # Check for "lic" files. + lx=$(cd ${LFWDIR} && find ${fwd} -type f \! -name "*sdio*" -a -name "*.txt" -print) + + # Get a count so we can automatically add \\ apart from the last line. + fn=$(echo "${lx}" | wc -w | awk '{ print $1 }') + + if test ${fn} -gt 0; then + echo "FWL ${flav}" + echo "DISTFILES_${flav}_lic= \\" + for fz in ${lx}; do echo "${fz}"; done | \ + awk -v fn=$fn -v fwg=${flav} -v drv=${DRIVER} '{ + if (FNR == fn) { x="" } else { x=" \\" }; + #gsub("^" drv "/", "${FWSUBDIR}/"); + gsub("^", "${FWSUBDIR}/"); + printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; + }' + fi + fi + done + + done +} + +################################################################################ +# +# 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 ${DRIVER}-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 + list_fw | grep -v ^FWS | grep -v ^FWL | 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; + }' + + fwsl=$(list_fw | grep ^FWL | 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 + echo "DISTFILES_\${FWDRV}_lic= \\" + for sz in ${fwsl}; do echo "${sz}"; done | \ + awk -v fn=$fn '{ + if (FNR == fn) { x="" } else { x=" \\" }; + printf "\t${DISTFILES_%s_lic}%s\n", $0, x; + }' + else + echo "DISTFILES_\${FWDRV}_lic=" + fi + + ) >> ${portsfile} + + printf "INFO: wifi-firmware-%s-kmod template at %s\n" ${DRIVER} ${portsfile} >&2 +fi + +################################################################################ +# +# Generate the fwget(8) case pattern table (PCI device ID -> fw port flavor). +# + +fwgetfile=$(mktemp -p /tmp ${DRIVER}-fwget.XXXXXX) +:> ${fwgetfile} + +fwsl=$(list_fw | grep ^FWGET | sort) +# Get a count so we can automatically add \\ apart from the last line. +fn=$(echo "${fwsl}" | grep -c FWGET | awk '{ print $1 }') + +if test ${fn} -gt 0; then + + # We need to check for same ID with multiple firmware. + # The list ist sorted by ID so duplicates are next to each other. + cs=$(echo "${fwsl}" | awk '{ print $2 }' | uniq -c | awk '{ print $1 }') + + #echo "==> cs=${cs}" >&2 + + for n in ${cs}; do + + # Skip FWGET + fwsl=${fwsl#*[[:space:]]} + # get device ID + did=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + # get flavor + flav=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + + # printf "===> did %s flav %s\n" ${did} ${flav} >&2 + + if test ${n} -eq 1; then + echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ + printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"; return 1 ;;\n", + tolower($1), drv, tolower($2); + }' >> ${fwgetfile} + else + echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ + printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"\n", + tolower($1), drv, tolower($2); + }' >> ${fwgetfile} + + i=1 + while test ${i} -lt ${n}; do + # Skip FWGET + fwsl=${fwsl#*[[:space:]]} + # get device ID + did=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + # get flavor + flav=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + + #printf "===> did %s flav %s\n" ${did} ${flav} >&2 + + echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ + printf "\t\taddpkg \"wifi-firmware-%s-kmod-%s\"\n", + drv, tolower($2); + }' >> ${fwgetfile} + + i=$((i + 1)) + done + + printf "\t\treturn 1 ;;\n" >> ${fwgetfile} + fi + done +fi + +printf "INFO: fwget pci_network_qca %s template at %s\n" ${DRIVER} ${fwgetfile} >&2 + +# end diff --git a/sys/contrib/dev/athk/ath12k/zzz_fw_ports_fwget.sh b/sys/contrib/dev/athk/ath12k/zzz_fw_ports_fwget.sh new file mode 100644 index 000000000000..500f5de05cc4 --- /dev/null +++ b/sys/contrib/dev/athk/ath12k/zzz_fw_ports_fwget.sh @@ -0,0 +1,310 @@ +#!/bin/sh +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2024 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. +# + +set -e + +DRIVER=ath12k +CHECKFILE=dp_mon.c + +################################################################################ +# +# Check pre-reqs +# +if [ $# -ne 1 ]; then + printf "USAGE: %s /path/to/linux-firmware.git\n" $0 >&2 + exit 1 +fi + +if [ ! -e ${CHECKFILE} ]; then + printf "ERROR: run from %s driver directory; no %s.c here\n" ${DRIVER} ${CHECKFILE} >&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 +LFWDIR=${LFWDIR}/${DRIVER} + +################################################################################ +# +# Helper functions. +# +# This uses a hack (cpp) to expand some macros for us and parses out the result +# which is the PCI device ID or the firmware directory for that. +# +list_fw() +{ + # List of already seen flavor (firmware directory). + sfwl="" + + # List of "supported" device IDs. + devidl=$(cpp pci.c 2> /dev/null | awk '/PCI_VDEVICE\(QCOM,/ { gsub("^.*, ", ""); gsub("\\) },$", ""); print tolower($0); }') + # Turn them into a regex. + didreg=$(echo "${devidl}" | xargs -J % echo -n % | sed -e 's, ,|,g') + # List the device ID cases along with their hw_rev which we can go and take to lookup fw. + hwrevs=$(cpp pci.c 2> /dev/null | egrep -E "(case (${didreg})|ab->hw_rev = )" | awk '{ + if (FNR > 1 && /case/) { + printf "\n"; + } + gsub("^.*case[[:space:]]*", ""); + gsub("[[:space:]]*ab->hw_rev = ", " "); + gsub("[:;]", ""); + printf "%s", $0; + }') + + # hwrevs is a list of (device IDs) -> (1..n hardware revisions) mappings. + #echo "==> ${devidl} :: ${didreg} :: ${hwrevs}" >&2 + + # List of (hardware revision) -> (firware directory) mappings. + l=$(cpp hw.c 2> /dev/null | egrep -E '\.(hw_rev|dir) = ' | awk '{ if (/hw_rev/) { printf "%s", $0; } else { print; } }' | sort | uniq | \ + awk '{ + gsub("^.*hw_rev = ", ""); + gsub(",.* = ", "\t"); + gsub(",$", ""); + gsub(/"/, ""); + gsub(" ", ""); + gsub("\t", " "); + print; + }') + #echo "===> ${l}" >&2 + + ll=$(echo "${l}" | wc -w | awk '{ print $1 }') + while test "${ll}" -gt 1; do + hwr=${l%%[[:space:]]*} + l=${l#*[[:space:]]} + fwd=${l%%[[:space:]]*} + l=${l#*[[:space:]]} + + #echo "=+=> ${hwr} -> ${fwd}" >&2 + eval fwd_${hwr}=${fwd} + ll=$(echo "${l}" | wc -w | awk '{ print $1 }') + done + + echo "${hwrevs}" | \ + while read did hwrl; do + hwrn=$(echo "${hwrl}" | wc -w | awk '{ print $1 }') + if test ${hwrn} -lt 1; then + printf "Device ID %s has no hardware revisions (%s); skipping\n" "${did}" ${hwrn} >&2 + continue + fi + + for hwrx in ${hwrl}; do + + eval fwd=\${fwd_${hwrx}} + #echo "===> ${did} -> ${hwrx} -> ${fwd}" >&2 + + if test ! -d ${LFWDIR}/${fwd}; then + #printf "Firmware dir %s (for %s) does not exist; skipping\n" ${fwd} ${did} >&2 + continue + fi + + flav=$(echo "${fwd}" | awk -v drv=${DRIVER} '{ + # Ports FLAVOR names are [a-z0-9_]. If needed add more mangling magic here. + gsub("^" drv "/", ""); + gsub("/", "_"); + gsub("\\.", ""); + print tolower($0); + }') + + # Print this first or otherwise if two device IDs have the same firmware + # we may not see that. + echo "FWGET ${did} ${flav}" + + x="" + for zf in ${sfwl}; do + if test "${zf}" == "${flav}"; then + x="${zf}" + break + fi + done + if test "${x}" != ""; then + #printf "Flavor %s (firmware directory %s) already seen; skipping\n" ${flav} ${fwd} >&2 + continue + fi + sfwl="${sfwl} ${flav}" + + #echo "==> ${did} -> ${fwd} -> ${flav}" + + lx=$(cd ${LFWDIR} && find ${fwd} -type f \! -name "*sdio*" -a \! -name "*.txt" -print) + + # Get a count so we can automatically add \\ apart from the last line. + fn=$(echo "${lx}" | wc -w | awk '{ print $1 }') + + #echo "==> ${flav} :: ${fn} :: ${lx}" >&2 + + if test ${fn} -gt 0; then + + echo "FWS ${flav}" + echo "DISTFILES_${flav}= \\" + for fz in ${lx}; do echo "${fz}"; done | \ + awk -v fn=$fn -v fwg=${flav} -v drv=${DRIVER} '{ + if (FNR == fn) { x="" } else { x=" \\" }; + #gsub("^" drv "/", "${FWSUBDIR}/"); + gsub("^", "${FWSUBDIR}/"); + printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; + }' + + # Check for "lic" files. + lx=$(cd ${LFWDIR} && find ${fwd} -type f \! -name "*sdio*" -a -name "*.txt" -print) + + # Get a count so we can automatically add \\ apart from the last line. + fn=$(echo "${lx}" | wc -w | awk '{ print $1 }') + + if test ${fn} -gt 0; then + echo "FWL ${flav}" + echo "DISTFILES_${flav}_lic= \\" + for fz in ${lx}; do echo "${fz}"; done | \ + awk -v fn=$fn -v fwg=${flav} -v drv=${DRIVER} '{ + if (FNR == fn) { x="" } else { x=" \\" }; + #gsub("^" drv "/", "${FWSUBDIR}/"); + gsub("^", "${FWSUBDIR}/"); + printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; + }' + fi + fi + done + + done +} + +################################################################################ +# +# 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 ${DRIVER}-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 + list_fw | grep -v ^FWS | grep -v ^FWL | 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; + }' + + fwsl=$(list_fw | grep ^FWL | 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 + echo "DISTFILES_\${FWDRV}_lic= \\" + for sz in ${fwsl}; do echo "${sz}"; done | \ + awk -v fn=$fn '{ + if (FNR == fn) { x="" } else { x=" \\" }; + printf "\t${DISTFILES_%s_lic}%s\n", $0, x; + }' + else + echo "DISTFILES_\${FWDRV}_lic=" + fi + + ) >> ${portsfile} + + printf "INFO: wifi-firmware-%s-kmod template at %s\n" ${DRIVER} ${portsfile} >&2 +fi + +################################################################################ +# +# Generate the fwget(8) case pattern table (PCI device ID -> fw port flavor). +# + +fwgetfile=$(mktemp -p /tmp ${DRIVER}-fwget.XXXXXX) +:> ${fwgetfile} + +fwsl=$(list_fw | grep ^FWGET | sort) +# Get a count so we can automatically add \\ apart from the last line. +fn=$(echo "${fwsl}" | grep -c FWGET | awk '{ print $1 }') + +if test ${fn} -gt 0; then + + # We need to check for same ID with multiple firmware. + # The list ist sorted by ID so duplicates are next to each other. + cs=$(echo "${fwsl}" | awk '{ print $2 }' | uniq -c | awk '{ print $1 }') + + #echo "==> cs=${cs}" >&2 + + for n in ${cs}; do + + # Skip FWGET + fwsl=${fwsl#*[[:space:]]} + # get device ID + did=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + # get flavor + flav=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + + # printf "===> did %s flav %s\n" ${did} ${flav} >&2 + + if test ${n} -eq 1; then + echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ + printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"; return 1 ;;\n", + tolower($1), drv, tolower($2); + }' >> ${fwgetfile} + else + echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ + printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"\n", + tolower($1), drv, tolower($2); + }' >> ${fwgetfile} + + i=1 + while test ${i} -lt ${n}; do + # Skip FWGET + fwsl=${fwsl#*[[:space:]]} + # get device ID + did=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + # get flavor + flav=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + + #printf "===> did %s flav %s\n" ${did} ${flav} >&2 + + echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ + printf "\t\taddpkg \"wifi-firmware-%s-kmod-%s\"\n", + drv, tolower($2); + }' >> ${fwgetfile} + + i=$((i + 1)) + done + + printf "\t\treturn 1 ;;\n" >> ${fwgetfile} + fi + done +fi + +printf "INFO: fwget pci_network_qca %s template at %s\n" ${DRIVER} ${fwgetfile} >&2 + +# end diff --git a/sys/contrib/dev/iwlwifi/zzz_fw_ports_fwget.sh b/sys/contrib/dev/iwlwifi/zzz_fw_ports_fwget.sh new file mode 100644 index 000000000000..60c75c00cbc7 --- /dev/null +++ b/sys/contrib/dev/iwlwifi/zzz_fw_ports_fwget.sh @@ -0,0 +1,374 @@ +#!/bin/sh +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2024 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. +# + +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 + +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 + +if test -r ${D_PCI_IDS_FILE}; then + printf "NOTICE: using proovided ${D_PCI_IDS_FILE}\n" >&2 +else + 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} 1`; do + xn="${bn}-${i}.ucode" + if test -e ${LFWDIR}/${xn}; then + lx="${lx} ${xn}" + break 2; + 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 +} + +################################################################################ +# +# 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; } + + # my ($ids, $name, $fw) = split /\t/; + split($0, a, "\t"); + ids=a[1]; + name=a[2]; + fw=a[3]; + + #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)"; } + + # iwlwififw.4 + printf ".It \"\"\n.It %s\n.It %s Ta %s Ta %s Ta %s Ta %s\n", name, i[1], i[2], i[3], i[4], 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 + +# end diff --git a/sys/contrib/dev/mediatek/mt76/zzz_fw_ports_fwget.sh b/sys/contrib/dev/mediatek/mt76/zzz_fw_ports_fwget.sh new file mode 100644 index 000000000000..8747daeba35f --- /dev/null +++ b/sys/contrib/dev/mediatek/mt76/zzz_fw_ports_fwget.sh @@ -0,0 +1,292 @@ +#!/bin/sh +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2024 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. +# +# Valid flavors: mt7915 mt792x {for the drivers with x=[15]} mt7996 +# To add a new one you need to add the mappings in the help functions. +# + +set -e + +DRIVER=mt76 +FWSUBDIR=mediatek +CHECKFILE=mt792x.h + +################################################################################ +# +# Check pre-reqs +# +if [ $# -ne 1 ]; then + printf "USAGE: %s /path/to/linux-firmware.git\n" $0 >&2 + exit 1 +fi + +if [ ! -e ${CHECKFILE} ]; then + printf "ERROR: run from %s driver directory; no %s.c here\n" ${DRIVER} ${CHECKFILE} >&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 + +################################################################################ +# +# Helper functions. +# + +get_device_ids_by_flav() +{ + for d in mt7915 mt7921 mt7925 mt7996; do + + case ${d} in + mt7915) flav=${d} ;; + mt7921) flav=mt792x ;; + mt7925) flav=mt792x ;; + mt7996) flav=${d} ;; + *) printf "ERROR: unsupported directory/flavor '%s'\n" ${d} >&2 + exit 1 + ;; + esac + + awk -v flav=${flav} -v rege="/${d}_pci_device_table/" 'BEGIN { x = 0; } { + if (rege) { x=1 }; + if (/^\};/) { x=0 }; + if (x==1 && /PCI_DEVICE\(PCI_VENDOR_ID_MEDIATEK,/) { + gsub(").*", "", $3); + #printf "%s)\taddpkg \"wifi-firmware-mt76-kmod-%s\"; return 1 ;;\n", tolower($3), tolower(flav); + printf "%s\t%s\n", tolower(flav), tolower($3); + } + }' ${d}/pci.c + + #grep -1r 'PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK' ${flav} + done +} + +get_firmwares_by_flavor() +{ + for h in mt7915/mt7915.h mt792x.h mt7996/mt7996.h; do + + case ${h} in + mt7915/mt7915.h) flav=mt7915 ;; + mt792x.h) flav=mt792x ;; + mt7996/mt7996.h) flav=mt7996 ;; + *) printf "ERROR: unsupported header/flavor '%s'\n" ${h} >&2 + exit 1 + ;; + esac + + awk -v rege="${FWSUBDIR}/" -v flav=${flav} -F\" '{ if ($0 ~ rege) { printf "%s\t%s\n", tolower(flav), $2; } }' ${h} | \ + while read flav fwn; do + if test ! -e ${LFWDIR}/${fwn}; then + #printf "Firmware %s (for %s) does not exist; skipping\n" ${fwn} ${flav} >&2 + continue + fi + printf "%s\t%s\n" ${flav} ${fwn} + done + done +} + +list_fw() +{ + # List of already seen flavor (firmware directory). + sfwl="" + + # List of "supported" device IDs. + devidl=`get_device_ids_by_flav` + #echo "===> ${devidl}" >&2 + + # List of (flavor) -> (firmware) mappings. + l=`get_firmwares_by_flavor` + #echo "===> ${l}" >&2 + + # For each flavor check we have at least 1 firmware file or skip it. + flavs=$(echo "${devidl}" | awk '{ print $1 }' | sort | uniq) + for flav in ${flavs}; do + + lx=$(echo "${l}" | awk -v flav=${flav} '{ if ($1 ~ flav) { print $2 } }' | sort | uniq) + fn=$(echo "${lx}" | wc -l | awk '{ print $1 }') + #printf "=+=> %s -- %s -- %s\n" ${flav} ${lx} ${fn} >&2 + if test ${fn} -le 0; then + printf "Flavor %s has %s firmware files; skipping\n" ${flav} ${fn} >&2 + continue + fi + + # Output the PCI ID/flav combinations for this flav. + echo "${devidl}" | \ + while read _flav did; do + if test "${_flav}" == "${flav}"; then + # Print this first or otherwise if two device IDs have the same firmware + # we may not see that. + echo "FWGET ${did} ${flav}" + fi + done + + x="" + for zf in ${sfwl}; do + if test "${zf}" == "${flav}"; then + x="${zf}" + break + fi + done + if test "${x}" != ""; then + printf "Flavor %s already seen; skipping\n" ${flav} >&2 + continue + fi + sfwl="${sfwl} ${flav}" + + # Handle ports bits. + echo "FWS ${flav}" + echo "DISTFILES_${flav}= \\" + for fz in ${lx}; do echo "${fz}"; done | \ + awk -v fn=$fn -v fwg=${flav} -v drv=${FWSUBDIR} '{ + if (FNR == fn) { x="" } else { x=" \\" }; + gsub("^" drv "/", "${FWSUBDIR}/"); + #gsub("^", "${FWSUBDIR}/"); + printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; + }' + + # Check for "lic" files. + # Known known to us, so no idea how to check for them. + done +} + +################################################################################ +# +# 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 ${DRIVER}-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 + list_fw | grep -v ^FWS | grep -v ^FWL | 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; + }' + + fwsl=$(list_fw | grep ^FWL | 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 + echo "DISTFILES_\${FWDRV}_lic= \\" + for sz in ${fwsl}; do echo "${sz}"; done | \ + awk -v fn=$fn '{ + if (FNR == fn) { x="" } else { x=" \\" }; + printf "\t${DISTFILES_%s_lic}%s\n", $0, x; + }' + else + echo "DISTFILES_\${FWDRV}_lic=" + fi + + ) >> ${portsfile} + + printf "INFO: wifi-firmware-%s-kmod template at %s\n" ${DRIVER} ${portsfile} >&2 +fi + +################################################################################ +# +# Generate the fwget(8) case pattern table (PCI device ID -> fw port flavor). +# + +fwgetfile=$(mktemp -p /tmp ${DRIVER}-fwget.XXXXXX) +:> ${fwgetfile} + +fwsl=$(list_fw | grep ^FWGET | sort) +# Get a count so we can automatically add \\ apart from the last line. +fn=$(echo "${fwsl}" | grep -c FWGET | awk '{ print $1 }') + +if test ${fn} -gt 0; then + + # We need to check for same ID with multiple firmware. + # The list ist sorted by ID so duplicates are next to each other. + cs=$(echo "${fwsl}" | awk '{ print $2 }' | uniq -c | awk '{ print $1 }') + + #echo "==> cs=${cs}" >&2 + + for n in ${cs}; do + + # Skip FWGET + fwsl=${fwsl#*[[:space:]]} + # get device ID + did=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + # get flavor + flav=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + + # printf "===> did %s flav %s\n" ${did} ${flav} >&2 + + if test ${n} -eq 1; then + echo "${did} ${flav}" | awk -v drv=${FWSUBDIR} '{ + printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"; return 1 ;;\n", + tolower($1), drv, tolower($2); + }' >> ${fwgetfile} + else + echo "${did} ${flav}" | awk -v drv=${FWSUBDIR} '{ + printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"\n", + tolower($1), drv, tolower($2); + }' >> ${fwgetfile} + + i=1 + while test ${i} -lt ${n}; do + # Skip FWGET + fwsl=${fwsl#*[[:space:]]} + # get device ID + did=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + # get flavor + flav=${fwsl%%[[:space:]]*} + fwsl=${fwsl#*[[:space:]]} + + #printf "===> did %s flav %s\n" ${did} ${flav} >&2 + + echo "${did} ${flav}" | awk -v drv=${FWSUBDIR} '{ + printf "\t\taddpkg \"wifi-firmware-%s-kmod-%s\"\n", + drv, tolower($2); + }' >> ${fwgetfile} + + i=$((i + 1)) + done + + printf "\t\treturn 1 ;;\n" >> ${fwgetfile} + fi + done +fi + +printf "INFO: fwget pci_network_qca %s template at %s\n" ${DRIVER} ${fwgetfile} >&2 + +# end diff --git a/sys/contrib/dev/rtw88/zzz_fw_ports_fwget.sh b/sys/contrib/dev/rtw88/zzz_fw_ports_fwget.sh new file mode 100644 index 000000000000..ca181db92732 --- /dev/null +++ b/sys/contrib/dev/rtw88/zzz_fw_ports_fwget.sh @@ -0,0 +1,145 @@ +#!/bin/sh +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2024 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. +# + +set -e + +DRIVER=rtw88 +CHECKFILE=rtw8822c.c + +################################################################################ +# +# Check pre-reqs +# +if [ $# -ne 1 ]; then + printf "USAGE: %s /path/to/linux-firmware.git\n" $0 >&2 + exit 1 +fi + +if [ ! -e ${CHECKFILE} ]; then + printf "ERROR: run from %s driver directory; no %s.c here\n" ${DRIVER} ${CHECKFILE} >&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 + + +################################################################################ +# +# Helper functions. +# +list_fw() +{ + for f in `ls -1 rtw?????.c rtw?????e.c`; do + + l=$(awk '/^MODULE_FIRMWARE\(/ { gsub(/"/, ""); gsub("\\);$", ""); gsub("^MODULE_FIRMWARE\\(", ""); printf "%s\n", $0; }' ${f} | sort -n | uniq) + lx="" + for fx in ${l}; do + if test -e ${LFWDIR}/${fx}; then + lx="${lx} ${fx}" + # else + # printf "NOTICE: no firmware file found for '%s'\n" ${fx} >&2 + 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%%.c} | 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} -v drv=${DRIVER} '{ + if (FNR == fn) { x="" } else { x=" \\" }; + gsub("^" drv "/", "${FWSUBDIR}/"); + printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; + }' + fi + + done +} + +################################################################################ +# +# 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 ${DRIVER}-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 + list_fw | grep -v ^FWS + + 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; + }' + ) >> ${portsfile} + + printf "INFO: wifi-firmware-%s-kmod template at %s\n" ${DRIVER} ${portsfile} >&2 +fi + +################################################################################ +# +# Generate the fwget(8) case pattern table (PCI device ID -> fw port flavor). +# + +fwgetfile=$(mktemp -p /tmp ${DRIVER}-fwget.XXXXXX) +:> ${fwgetfile} + +for f in `ls -1 rtw?????.c rtw?????e.c`; do + + # Ports FLAVOR names are [a-z0-9_]. If needed add more mangling magic here. + n=${f%.c}; + n=${n%e}; + + awk -v n=${n} -v drv=${DRIVER} '/PCI_DEVICE\(PCI_VENDOR_ID_REALTEK,/ { + gsub(").*", "", $2); + printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"; return 1 ;;\n", + tolower($2), drv, tolower(n); + }' ${f} +done >> ${fwgetfile} + +printf "INFO: fwget pci_network_realtek %s template at %s\n" ${DRIVER} ${fwgetfile} >&2 + +# end diff --git a/sys/contrib/dev/rtw89/zzz_fw_ports_fwget.sh b/sys/contrib/dev/rtw89/zzz_fw_ports_fwget.sh new file mode 100644 index 000000000000..4ee0ab7a6fd1 --- /dev/null +++ b/sys/contrib/dev/rtw89/zzz_fw_ports_fwget.sh @@ -0,0 +1,152 @@ +#!/bin/sh +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2024 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. +# + +set -e + +DRIVER=rtw89 +CHECKFILE=rtw8922a.c + +################################################################################ +# +# Check pre-reqs +# +if [ $# -ne 1 ]; then + printf "USAGE: %s /path/to/linux-firmware.git\n" $0 >&2 + exit 1 +fi + +if [ ! -e ${CHECKFILE} ]; then + printf "ERROR: run from %s driver directory; no %s.c here\n" ${DRIVER} ${CHECKFILE} >&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 + + +################################################################################ +# +# 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 (where applicable). +# +list_fw() +{ + for f in `ls -1 rtw?????.c rtw?????e.c`; do + + l=$(cpp ${f} 2>&1 | awk '/^MODULE_FIRMWARE\(/ { gsub(/"/, ""); gsub("__stringify\\(", ""); gsub("\\);$", ""); gsub("\\)", ""); gsub("^MODULE_FIRMWARE\\(", ""); gsub(" ", ""); printf "%s\n", $0; }' | sort -n | uniq) + if test "${l}" == ""; then + continue + fi + lx="" + for fx in ${l}; do + if test -e ${LFWDIR}/${fx}; then + lx="${lx} ${fx}" + # else + # printf "NOTICE: no firmware file found for '%s'\n" ${fx} >&2 + 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%%.c} | 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} -v drv=${DRIVER} '{ + if (FNR == fn) { x="" } else { x=" \\" }; + gsub("^" drv "/", "${FWSUBDIR}/"); + printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; + }' + fi + + done +} + +################################################################################ +# +# 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 ${DRIVER}-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 + list_fw | grep -v ^FWS + + 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; + }' + ) >> ${portsfile} + + printf "INFO: wifi-firmware-%s-kmod template at %s\n" ${DRIVER} ${portsfile} >&2 +fi + +################################################################################ +# +# Generate the fwget(8) case pattern table (PCI device ID -> fw port flavor). +# + +fwgetfile=$(mktemp -p /tmp ${DRIVER}-fwget.XXXXXX) +:> ${fwgetfile} + +for f in `ls -1 rtw?????.c rtw?????e.c`; do + + # Ports FLAVOR names are [a-z0-9_]. If needed add more mangling magic here. + n=${f%.c}; + n=${n%e}; + + awk -v n=${n} -v drv=${DRIVER} '/PCI_DEVICE\(PCI_VENDOR_ID_REALTEK,/ { + gsub(").*", "", $2); + printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"; return 1 ;;\n", + tolower($2), drv, tolower(n); + }' ${f} +done >> ${fwgetfile} + +printf "INFO: fwget pci_network_realtek %s template at %s\n" ${DRIVER} ${fwgetfile} >&2 + +# end