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=ath12k 21CHECKFILE=dp_mon.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 42LFWDIR=${LFWDIR}/${DRIVER} 43 44################################################################################ 45# 46# Helper functions. 47# 48# This uses a hack (cpp) to expand some macros for us and parses out the result 49# which is the PCI device ID or the firmware directory for that. 50# 51list_fw() 52{ 53 # List of already seen flavor (firmware directory). 54 sfwl="" 55 56 # List of "supported" device IDs. 57 devidl=$(cpp pci.c 2> /dev/null | awk '/PCI_VDEVICE\(QCOM,/ { gsub("^.*, ", ""); gsub("\\) },$", ""); print tolower($0); }') 58 # Turn them into a regex. 59 didreg=$(echo "${devidl}" | xargs -J % echo -n % | sed -e 's, ,|,g') 60 # List the device ID cases along with their hw_rev which we can go and take to lookup fw. 61 hwrevs=$(cpp pci.c 2> /dev/null | egrep -E "(case (${didreg})|ab->hw_rev = )" | awk '{ 62 if (FNR > 1 && /case/) { 63 printf "\n"; 64 } 65 gsub("^.*case[[:space:]]*", ""); 66 gsub("[[:space:]]*ab->hw_rev = ", " "); 67 gsub("[:;]", ""); 68 printf "%s", $0; 69 }') 70 71 # hwrevs is a list of (device IDs) -> (1..n hardware revisions) mappings. 72 #echo "==> ${devidl} :: ${didreg} :: ${hwrevs}" >&2 73 74 # List of (hardware revision) -> (firware directory) mappings. 75 l=$(cpp hw.c 2> /dev/null | egrep -E '\.(hw_rev|dir) = ' | awk '{ if (/hw_rev/) { printf "%s", $0; } else { print; } }' | sort | uniq | \ 76 awk '{ 77 gsub("^.*hw_rev = ", ""); 78 gsub(",.* = ", "\t"); 79 gsub(",$", ""); 80 gsub(/"/, ""); 81 gsub(" ", ""); 82 gsub("\t", " "); 83 print; 84 }') 85 #echo "===> ${l}" >&2 86 87 ll=$(echo "${l}" | wc -w | awk '{ print $1 }') 88 while test "${ll}" -gt 1; do 89 hwr=${l%%[[:space:]]*} 90 l=${l#*[[:space:]]} 91 fwd=${l%%[[:space:]]*} 92 l=${l#*[[:space:]]} 93 94 #echo "=+=> ${hwr} -> ${fwd}" >&2 95 eval fwd_${hwr}=${fwd} 96 ll=$(echo "${l}" | wc -w | awk '{ print $1 }') 97 done 98 99 echo "${hwrevs}" | \ 100 while read did hwrl; do 101 hwrn=$(echo "${hwrl}" | wc -w | awk '{ print $1 }') 102 if test ${hwrn} -lt 1; then 103 printf "Device ID %s has no hardware revisions (%s); skipping\n" "${did}" ${hwrn} >&2 104 continue 105 fi 106 107 for hwrx in ${hwrl}; do 108 109 eval fwd=\${fwd_${hwrx}} 110 #echo "===> ${did} -> ${hwrx} -> ${fwd}" >&2 111 112 if test ! -d ${LFWDIR}/${fwd}; then 113 #printf "Firmware dir %s (for %s) does not exist; skipping\n" ${fwd} ${did} >&2 114 continue 115 fi 116 117 flav=$(echo "${fwd}" | awk -v drv=${DRIVER} '{ 118 # Ports FLAVOR names are [a-z0-9_]. If needed add more mangling magic here. 119 gsub("^" drv "/", ""); 120 gsub("/", "_"); 121 gsub("\\.", ""); 122 print tolower($0); 123 }') 124 125 # Print this first or otherwise if two device IDs have the same firmware 126 # we may not see that. 127 echo "FWGET ${did} ${flav}" 128 129 x="" 130 for zf in ${sfwl}; do 131 if test "${zf}" == "${flav}"; then 132 x="${zf}" 133 break 134 fi 135 done 136 if test "${x}" != ""; then 137 #printf "Flavor %s (firmware directory %s) already seen; skipping\n" ${flav} ${fwd} >&2 138 continue 139 fi 140 sfwl="${sfwl} ${flav}" 141 142 #echo "==> ${did} -> ${fwd} -> ${flav}" 143 144 lx=$(cd ${LFWDIR} && find ${fwd} -type f \! -name "*sdio*" -a \! -name "*.txt" -print) 145 146 # Get a count so we can automatically add \\ apart from the last line. 147 fn=$(echo "${lx}" | wc -w | awk '{ print $1 }') 148 149 #echo "==> ${flav} :: ${fn} :: ${lx}" >&2 150 151 if test ${fn} -gt 0; then 152 153 echo "FWS ${flav}" 154 echo "DISTFILES_${flav}= \\" 155 for fz in ${lx}; do echo "${fz}"; done | \ 156 awk -v fn=$fn -v fwg=${flav} -v drv=${DRIVER} '{ 157 if (FNR == fn) { x="" } else { x=" \\" }; 158 #gsub("^" drv "/", "${FWSUBDIR}/"); 159 gsub("^", "${FWSUBDIR}/"); 160 printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; 161 }' 162 163 # Check for "lic" files. 164 lx=$(cd ${LFWDIR} && find ${fwd} -type f \! -name "*sdio*" -a -name "*.txt" -print) 165 166 # Get a count so we can automatically add \\ apart from the last line. 167 fn=$(echo "${lx}" | wc -w | awk '{ print $1 }') 168 169 if test ${fn} -gt 0; then 170 echo "FWL ${flav}" 171 echo "DISTFILES_${flav}_lic= \\" 172 for fz in ${lx}; do echo "${fz}"; done | \ 173 awk -v fn=$fn -v fwg=${flav} -v drv=${DRIVER} '{ 174 if (FNR == fn) { x="" } else { x=" \\" }; 175 #gsub("^" drv "/", "${FWSUBDIR}/"); 176 gsub("^", "${FWSUBDIR}/"); 177 printf "\t%s${DISTURL_SUFFIX}%s\n", $0, x; 178 }' 179 fi 180 fi 181 done 182 183 done 184} 185 186################################################################################ 187# 188# Generate the PORTS file template. 189# 190 191fwsl=$(list_fw | grep ^FWS | awk '{ print $2 }') 192# Get a count so we can automatically add \\ apart from the last line. 193fn=$(echo "${fwsl}" | wc -w | awk '{ print $1 }') 194 195if test ${fn} -gt 0; then 196 197 portsfile=$(mktemp -p /tmp ${DRIVER}-fwport.XXXXXX) 198 199 :> ${portsfile} 200 ( 201 echo "FWSUBS= \\" 202 for sz in ${fwsl}; do echo "${sz}"; done | \ 203 awk -v fn=$fn '{ 204 if (FNR == fn) { x="" } else { x=" \\" }; 205 printf "\t%s%s\n", $0, x; 206 }' 207 208 echo 209 list_fw | grep -v ^FWS | grep -v ^FWL | grep -v ^FWGET 210 211 echo 212 echo "DISTFILES_\${FWDRV}= \\" 213 for sz in ${fwsl}; do echo "${sz}"; done | \ 214 awk -v fn=$fn '{ 215 if (FNR == fn) { x="" } else { x=" \\" }; 216 printf "\t${DISTFILES_%s}%s\n", $0, x; 217 }' 218 219 fwsl=$(list_fw | grep ^FWL | awk '{ print $2 }') 220 # Get a count so we can automatically add \\ apart from the last line. 221 fn=$(echo "${fwsl}" | wc -w | awk '{ print $1 }') 222 if test ${fn} -gt 0; then 223 echo "DISTFILES_\${FWDRV}_lic= \\" 224 for sz in ${fwsl}; do echo "${sz}"; done | \ 225 awk -v fn=$fn '{ 226 if (FNR == fn) { x="" } else { x=" \\" }; 227 printf "\t${DISTFILES_%s_lic}%s\n", $0, x; 228 }' 229 else 230 echo "DISTFILES_\${FWDRV}_lic=" 231 fi 232 233 ) >> ${portsfile} 234 235 printf "INFO: wifi-firmware-%s-kmod template at %s\n" ${DRIVER} ${portsfile} >&2 236fi 237 238################################################################################ 239# 240# Generate the fwget(8) case pattern table (PCI device ID -> fw port flavor). 241# 242 243fwgetfile=$(mktemp -p /tmp ${DRIVER}-fwget.XXXXXX) 244:> ${fwgetfile} 245 246fwsl=$(list_fw | grep ^FWGET | sort) 247# Get a count so we can automatically add \\ apart from the last line. 248fn=$(echo "${fwsl}" | grep -c FWGET | awk '{ print $1 }') 249 250if test ${fn} -gt 0; then 251 252 # We need to check for same ID with multiple firmware. 253 # The list ist sorted by ID so duplicates are next to each other. 254 cs=$(echo "${fwsl}" | awk '{ print $2 }' | uniq -c | awk '{ print $1 }') 255 256 #echo "==> cs=${cs}" >&2 257 258 for n in ${cs}; do 259 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 if test ${n} -eq 1; then 272 echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ 273 printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"; return 1 ;;\n", 274 tolower($1), drv, tolower($2); 275 }' >> ${fwgetfile} 276 else 277 echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ 278 printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"\n", 279 tolower($1), drv, tolower($2); 280 }' >> ${fwgetfile} 281 282 i=1 283 while test ${i} -lt ${n}; do 284 # Skip FWGET 285 fwsl=${fwsl#*[[:space:]]} 286 # get device ID 287 did=${fwsl%%[[:space:]]*} 288 fwsl=${fwsl#*[[:space:]]} 289 # get flavor 290 flav=${fwsl%%[[:space:]]*} 291 fwsl=${fwsl#*[[:space:]]} 292 293 #printf "===> did %s flav %s\n" ${did} ${flav} >&2 294 295 echo "${did} ${flav}" | awk -v drv=${DRIVER} '{ 296 printf "\t\taddpkg \"wifi-firmware-%s-kmod-%s\"\n", 297 drv, tolower($2); 298 }' >> ${fwgetfile} 299 300 i=$((i + 1)) 301 done 302 303 printf "\t\treturn 1 ;;\n" >> ${fwgetfile} 304 fi 305 done 306fi 307 308printf "INFO: fwget pci_network_qca %s template at %s\n" ${DRIVER} ${fwgetfile} >&2 309 310# end 311