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