xref: /freebsd/sys/contrib/dev/athk/ath12k/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=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