1#!/bin/sh 2#- 3# SPDX-License-Identifier: BSD-2-Clause 4# 5# Copyright (c) 2024 The FreeBSD Foundation 6# 7# This software was developed by Björn Zeeb 8# under sponsorship from the FreeBSD Foundation. 9# 10# This is neither efficient nor elegant but we need it few times 11# a year and it does the job. 12# 13# 14# USAGE: please check out the correct tag/hash for ports in the 15# linux-firmware.git repository you point this script to. 16# 17 18set -e 19 20DRIVER=ath10k 21CHECKFILE=qmi_wlfw_v01.c 22 23################################################################################ 24# 25# Check pre-reqs 26# 27if [ $# -ne 1 ]; then 28 printf "USAGE: %s /path/to/linux-firmware.git\n" $0 >&2 29 exit 1 30fi 31 32if [ ! -e ${CHECKFILE} ]; then 33 printf "ERROR: run from %s driver directory; no %s.c here\n" ${DRIVER} ${CHECKFILE} >&2 34 exit 1 35fi 36 37LFWDIR=${1} 38if test ! -d ${LFWDIR} -o ! -e ${LFWDIR}/WHENCE; then 39 printf "ERROR: cannot find linux-firmware.git at '%s'\n" ${LFWDIR} >&2 40 exit 1 41fi 42 43################################################################################ 44# 45# Helper functions. 46# 47# This uses a hack (cpp) to expand some macros for us and parses out the result 48# which is the PCI device ID or the firmware directory for that. 49# Checking MODULE_FIRMWARE was pointless as it had too many "dead" entries: 50# NOTICE: no firmware file found for 'ath10k/QCA6174/hw2.1/firmware-4.bin' 51# NOTICE: no firmware file found for 'ath10k/QCA6174/hw3.0/firmware-5.bin' 52# NOTICE: no firmware file found for 'ath10k/QCA9887/hw1.0/board-2.bin' 53# NOTICE: no firmware file found for 'ath10k/QCA988X/hw2.0/board-2.bin' 54# NOTICE: no firmware file found for 'ath10k/QCA988X/hw2.0/firmware-2.bin' 55# NOTICE: no firmware file found for 'ath10k/QCA988X/hw2.0/firmware-3.bin' 56# 57list_fw() 58{ 59 # List of already seen flavor (firmware directory). 60 sfwl="" 61 62 # List of "supported" device IDs (ignoring Ubiquity). 63 devidl=$(cpp pci.c 2> /dev/null | awk '/PCI_VDEVICE\(ATHEROS,/ { gsub("^.*, \\(", ""); gsub("\\)\\) },$", ""); print tolower($0); }') 64 65 # List of (device ID) -> (firware directory) mappings. 66 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 | \ 67 awk '{ 68 gsub("^.*\\(", ""); 69 gsub("),.* = ", "\t"); 70 gsub(",$", ""); 71 gsub(/"/, ""); 72 gsub(" ", ""); 73 print; 74 }' | \ 75 while read did fwd; do 76 77 x="" 78 for d in ${devidl}; do 79 if test "${did}" == "${d}"; then 80 x="${d}" 81 break 82 fi 83 done 84 if test "${x}" == ""; then 85 # Device ID not in the list of PCI IDs we support. 86 # At least the Ubiquity one we hit here. 87 #printf "Device ID %s (%s) not in PCI ID list; skipping\n" ${did} ${fwd} >&2 88 continue 89 fi 90 91 if test ! -d ${LFWDIR}/${fwd}; then 92 # Leave this on as it MUST not happen. 93 printf "Firmware dir %s (for %s) does not exist; skipping\n" ${fwd} ${did} >&2 94 continue 95 fi 96 97 flav=$(echo "${fwd}" | awk -v drv=${DRIVER} '{ 98 # Ports FLAVOR names are [a-z0-9_]. If needed add more mangling magic here. 99 gsub("^" drv "/", ""); 100 gsub("/", "_"); 101 gsub("\\.", ""); 102 print tolower($0); 103 }') 104 105 # Print this first or otherwise if two device IDs have the same firmware 106 # we may not see that. 107 echo "FWGET ${did} ${flav}" 108 109 x="" 110 for zf in ${sfwl}; do 111 if test "${zf}" == "${flav}"; then 112 x="${zf}" 113 break 114 fi 115 done 116 if test "${x}" != ""; then 117 #printf "Flavor %s (firmware directory %s) already seen; skipping\n" ${flav} ${fwd} >&2 118 continue 119 fi 120 sfwl="${sfwl} ${flav}" 121 122 #echo "==> ${did} -> ${fwd} -> ${flav}" 123 124 lx=$(cd ${LFWDIR} && find ${fwd} -type f \! -name "*sdio*" -a \! -name "*.txt" -print) 125 126 # Get a count so we can automatically add \\ apart from the last line. 127 fn=$(echo "${lx}" | wc -w | awk '{ print $1 }') 128 129 #echo "==> ${flav} :: ${fn} :: ${lx}" >&2 130 131 if test ${fn} -gt 0; then 132 133 echo "FWS ${flav}" 134 echo "DISTFILES_${flav}= \\" 135 for fz in ${lx}; do echo "${fz}"; done | \ 136 awk -v fn=$fn -v fwg=${flav} -v drv=${DRIVER} '{ 137 if (FNR == fn) { x="" } else { x=" \\" }; 138 gsub("^" drv "/", "${FWSUBDIR}/"); 139 printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; 140 }' 141 142 # Check for "lic" files. 143 lx=$(cd ${LFWDIR} && find ${fwd} -type f \! -name "*sdio*" -a -name "*.txt" -print) 144 145 # Get a count so we can automatically add \\ apart from the last line. 146 fn=$(echo "${lx}" | wc -w | awk '{ print $1 }') 147 148 if test ${fn} -gt 0; then 149 echo "FWL ${flav}" 150 echo "DISTFILES_${flav}_lic= \\" 151 for fz in ${lx}; do echo "${fz}"; done | \ 152 awk -v fn=$fn -v fwg=${flav} -v drv=${DRIVER} '{ 153 if (FNR == fn) { x="" } else { x=" \\" }; 154 gsub("^" drv "/", "${FWSUBDIR}/"); 155 printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; 156 }' 157 fi 158 fi 159 done 160} 161 162################################################################################ 163# 164# Generate the PORTS file template. 165# 166 167fwsl=$(list_fw | grep ^FWS | awk '{ print $2 }') 168# Get a count so we can automatically add \\ apart from the last line. 169fn=$(echo "${fwsl}" | wc -w | awk '{ print $1 }') 170 171if test ${fn} -gt 0; then 172 173 portsfile=$(mktemp -p /tmp ${DRIVER}-fwport.XXXXXX) 174 175 :> ${portsfile} 176 ( 177 echo "FWSUBS= \\" 178 for sz in ${fwsl}; do echo "${sz}"; done | \ 179 awk -v fn=$fn '{ 180 if (FNR == fn) { x="" } else { x=" \\" }; 181 printf "\t%s%s\n", $0, x; 182 }' 183 184 echo 185 list_fw | grep -v ^FWS | grep -v ^FWL | grep -v ^FWGET 186 187 echo 188 echo "DISTFILES_\${FWDRV}= \\" 189 for sz in ${fwsl}; do echo "${sz}"; done | \ 190 awk -v fn=$fn '{ 191 if (FNR == fn) { x="" } else { x=" \\" }; 192 printf "\t${DISTFILES_%s}%s\n", $0, x; 193 }' 194 195 fwsl=$(list_fw | grep ^FWL | awk '{ print $2 }') 196 # Get a count so we can automatically add \\ apart from the last line. 197 fn=$(echo "${fwsl}" | wc -w | awk '{ print $1 }') 198 if test ${fn} -gt 0; then 199 echo "DISTFILES_\${FWDRV}_lic= \\" 200 for sz in ${fwsl}; do echo "${sz}"; done | \ 201 awk -v fn=$fn '{ 202 if (FNR == fn) { x="" } else { x=" \\" }; 203 printf "\t${DISTFILES_%s_lic}%s\n", $0, x; 204 }' 205 else 206 echo "DISTFILES_\${FWDRV}_lic=" 207 fi 208 209 ) >> ${portsfile} 210 211 printf "INFO: wifi-firmware-%s-kmod template at %s\n" ${DRIVER} ${portsfile} >&2 212fi 213 214################################################################################ 215# 216# Generate the fwget(8) case pattern table (PCI device ID -> fw port flavor). 217# 218 219fwgetfile=$(mktemp -p /tmp ${DRIVER}-fwget.XXXXXX) 220:> ${fwgetfile} 221 222fwsl=$(list_fw | grep ^FWGET | sort) 223# Get a count so we can automatically add \\ apart from the last line. 224fn=$(echo "${fwsl}" | grep -c FWGET | awk '{ print $1 }') 225 226if test ${fn} -gt 0; then 227 228 # We need to check for same ID with multiple firmware. 229 # The list ist sorted by ID so duplicates are next to each other. 230 cs=$(echo "${fwsl}" | awk '{ print $2 }' | uniq -c | awk '{ print $1 }') 231 232 #echo "==> cs=${cs}" >&2 233 234 for n in ${cs}; do 235 236 # Skip FWGET 237 fwsl=${fwsl#*[[:space:]]} 238 # get device ID 239 did=${fwsl%%[[:space:]]*} 240 fwsl=${fwsl#*[[:space:]]} 241 # get flavor 242 flav=${fwsl%%[[:space:]]*} 243 fwsl=${fwsl#*[[:space:]]} 244 245 # printf "===> did %s flav %s\n" ${did} ${flav} >&2 246 247 if test ${n} -eq 1; then 248 echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ 249 printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"; return 1 ;;\n", 250 tolower($1), drv, tolower($2); 251 }' >> ${fwgetfile} 252 else 253 echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ 254 printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"\n", 255 tolower($1), drv, tolower($2); 256 }' >> ${fwgetfile} 257 258 i=1 259 while test ${i} -lt ${n}; do 260 # Skip FWGET 261 fwsl=${fwsl#*[[:space:]]} 262 # get device ID 263 did=${fwsl%%[[:space:]]*} 264 fwsl=${fwsl#*[[:space:]]} 265 # get flavor 266 flav=${fwsl%%[[:space:]]*} 267 fwsl=${fwsl#*[[:space:]]} 268 269 #printf "===> did %s flav %s\n" ${did} ${flav} >&2 270 271 echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ 272 printf "\t\taddpkg \"wifi-firmware-%s-kmod-%s\"\n", 273 drv, tolower($2); 274 }' >> ${fwgetfile} 275 276 i=$((i + 1)) 277 done 278 279 printf "\t\treturn 1 ;;\n" >> ${fwgetfile} 280 fi 281 done 282fi 283 284printf "INFO: fwget pci_network_qca %s template at %s\n" ${DRIVER} ${fwgetfile} >&2 285 286# end 287