xref: /freebsd/sys/contrib/dev/mediatek/mt76/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# Valid flavors: mt7915 mt792x {for the drivers with x=[15]} mt7996
18# To add a new one you need to add the mappings in the help functions.
19#
20
21set -e
22
23DRIVER=mt76
24FWSUBDIR=mediatek
25CHECKFILE=mt792x.h
26
27################################################################################
28#
29# Check pre-reqs
30#
31if [ $# -ne 1 ]; then
32	printf "USAGE: %s /path/to/linux-firmware.git\n" $0 >&2
33	exit 1
34fi
35
36if [ ! -e ${CHECKFILE} ]; then
37	printf "ERROR: run from %s driver directory; no %s.c here\n" ${DRIVER} ${CHECKFILE} >&2
38	exit 1
39fi
40
41LFWDIR=${1}
42if test ! -d ${LFWDIR} -o ! -e ${LFWDIR}/WHENCE; then
43	printf "ERROR: cannot find linux-firmware.git at '%s'\n" ${LFWDIR} >&2
44	exit 1
45fi
46
47################################################################################
48#
49# Helper functions.
50#
51
52get_device_ids_by_flav()
53{
54	for d in mt7915 mt7921 mt7925 mt7996; do
55
56		case ${d} in
57		mt7915)	flav=${d} ;;
58		mt7921)	flav=mt792x ;;
59		mt7925)	flav=mt792x ;;
60		mt7996)	flav=${d} ;;
61		*)	printf "ERROR: unsupported directory/flavor '%s'\n" ${d} >&2
62			exit 1
63			;;
64		esac
65
66		awk -v flav=${flav} -v rege="/${d}_pci_device_table/" 'BEGIN { x = 0; } {
67			if (rege) { x=1 };
68			if (/^\};/) { x=0 };
69			if (x==1 && /PCI_DEVICE\(PCI_VENDOR_ID_MEDIATEK,/) {
70				gsub(").*", "", $3);
71				#printf "%s)\taddpkg \"wifi-firmware-mt76-kmod-%s\"; return 1 ;;\n", tolower($3), tolower(flav);
72				printf "%s\t%s\n", tolower(flav), tolower($3);
73			}
74		}' ${d}/pci.c
75
76		#grep -1r 'PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK' ${flav}
77	done
78}
79
80get_firmwares_by_flavor()
81{
82	for h in mt7915/mt7915.h mt792x.h mt7996/mt7996.h; do
83
84		case ${h} in
85		mt7915/mt7915.h)	flav=mt7915 ;;
86		mt792x.h)		flav=mt792x ;;
87		mt7996/mt7996.h)	flav=mt7996 ;;
88		*)	printf "ERROR: unsupported header/flavor '%s'\n" ${h} >&2
89			exit 1
90			;;
91		esac
92
93		awk -v rege="${FWSUBDIR}/" -v flav=${flav} -F\" '{ if ($0 ~ rege) { printf "%s\t%s\n", tolower(flav), $2; } }' ${h} | \
94		while read flav fwn; do
95			if test ! -e ${LFWDIR}/${fwn}; then
96				#printf "Firmware %s (for %s) does not exist; skipping\n" ${fwn} ${flav} >&2
97				continue
98			fi
99			printf "%s\t%s\n" ${flav} ${fwn}
100		done
101	done
102}
103
104list_fw()
105{
106	# List of already seen flavor (firmware directory).
107	sfwl=""
108
109	# List of "supported" device IDs.
110	devidl=`get_device_ids_by_flav`
111	#echo "===> ${devidl}" >&2
112
113	# List of (flavor) -> (firmware) mappings.
114	l=`get_firmwares_by_flavor`
115	#echo "===> ${l}" >&2
116
117	# For each flavor check we have at least 1 firmware file or skip it.
118	flavs=$(echo "${devidl}" | awk '{ print $1 }' | sort | uniq)
119	for flav in ${flavs}; do
120
121		lx=$(echo "${l}" | awk -v flav=${flav} '{ if ($1 ~ flav) { print $2 } }' | sort | uniq)
122		fn=$(echo "${lx}" | wc -l | awk '{ print $1 }')
123		#printf "=+=> %s -- %s -- %s\n" ${flav} ${lx} ${fn} >&2
124		if test ${fn} -le 0; then
125			printf "Flavor %s has %s firmware files; skipping\n" ${flav} ${fn} >&2
126			continue
127		fi
128
129		# Output the PCI ID/flav combinations for this flav.
130		echo "${devidl}" | \
131		while read _flav did; do
132			if test "${_flav}" == "${flav}"; then
133				# Print this first or otherwise if two device IDs have the same firmware
134				# we may not see that.
135				echo "FWGET ${did} ${flav}"
136			fi
137		done
138
139		x=""
140		for zf in ${sfwl}; do
141			if test "${zf}" == "${flav}"; then
142				x="${zf}"
143				break
144			fi
145		done
146		if test "${x}" != ""; then
147			printf "Flavor %s already seen; skipping\n" ${flav} >&2
148			continue
149		fi
150		sfwl="${sfwl} ${flav}"
151
152		# Handle ports bits.
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=${FWSUBDIR} '{
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		# Known known to us, so no idea how to check for them.
165	done
166}
167
168################################################################################
169#
170# Generate the PORTS file template.
171#
172
173fwsl=$(list_fw | grep ^FWS | awk '{ print $2 }')
174# Get a count so we can automatically add \\ apart from the last line.
175fn=$(echo "${fwsl}" | wc -w | awk '{ print $1 }')
176
177if test ${fn} -gt 0; then
178
179	portsfile=$(mktemp -p /tmp ${DRIVER}-fwport.XXXXXX)
180
181	:> ${portsfile}
182	(
183	echo "FWSUBS= \\"
184	for sz in ${fwsl}; do echo "${sz}"; done | \
185	awk -v fn=$fn '{
186		if (FNR == fn) { x="" } else { x=" \\" };
187		printf "\t%s%s\n", $0, x;
188	}'
189
190	echo
191	list_fw | grep -v ^FWS | grep -v ^FWL | grep -v ^FWGET
192
193	echo
194	echo "DISTFILES_\${FWDRV}= \\"
195	for sz in ${fwsl}; do echo "${sz}"; done | \
196	awk -v fn=$fn '{
197		if (FNR == fn) { x="" } else { x=" \\" };
198		printf "\t${DISTFILES_%s}%s\n", $0, x;
199	}'
200
201	fwsl=$(list_fw | grep ^FWL | awk '{ print $2 }')
202	# Get a count so we can automatically add \\ apart from the last line.
203	fn=$(echo "${fwsl}" | wc -w | awk '{ print $1 }')
204	if test ${fn} -gt 0; then
205		echo "DISTFILES_\${FWDRV}_lic= \\"
206		for sz in ${fwsl}; do echo "${sz}"; done | \
207		awk -v fn=$fn '{
208			if (FNR == fn) { x="" } else { x=" \\" };
209			printf "\t${DISTFILES_%s_lic}%s\n", $0, x;
210		}'
211	else
212		echo "DISTFILES_\${FWDRV}_lic="
213	fi
214
215	) >> ${portsfile}
216
217	printf "INFO: wifi-firmware-%s-kmod template at %s\n" ${DRIVER} ${portsfile} >&2
218fi
219
220################################################################################
221#
222# Generate the fwget(8) case pattern table (PCI device ID -> fw port flavor).
223#
224
225fwgetfile=$(mktemp -p /tmp ${DRIVER}-fwget.XXXXXX)
226:> ${fwgetfile}
227
228fwsl=$(list_fw | grep ^FWGET | sort)
229# Get a count so we can automatically add \\ apart from the last line.
230fn=$(echo "${fwsl}" | grep -c FWGET | awk '{ print $1 }')
231
232if test ${fn} -gt 0; then
233
234	# We need to check for same ID with multiple firmware.
235	# The list ist sorted by ID so duplicates are next to each other.
236	cs=$(echo "${fwsl}" | awk '{ print $2 }' | uniq -c | awk '{ print $1 }')
237
238	#echo "==> cs=${cs}" >&2
239
240	for n in ${cs}; do
241
242		# Skip FWGET
243		fwsl=${fwsl#*[[:space:]]}
244		# get device ID
245		did=${fwsl%%[[:space:]]*}
246		fwsl=${fwsl#*[[:space:]]}
247		# get flavor
248		flav=${fwsl%%[[:space:]]*}
249		fwsl=${fwsl#*[[:space:]]}
250
251		# printf "===> did %s flav %s\n" ${did} ${flav} >&2
252
253		if test ${n} -eq 1; then
254			echo "${did} ${flav}" | awk -v drv=${FWSUBDIR} '{
255				printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"; return 1 ;;\n",
256				    tolower($1), drv, tolower($2);
257			}' >> ${fwgetfile}
258		else
259			echo "${did} ${flav}" | awk -v drv=${FWSUBDIR} '{
260				printf "\t%s)\taddpkg \"wifi-firmware-%s-kmod-%s\"\n",
261				    tolower($1), drv, tolower($2);
262			}' >> ${fwgetfile}
263
264			i=1
265			while test ${i} -lt ${n}; do
266				# Skip FWGET
267				fwsl=${fwsl#*[[:space:]]}
268				# get device ID
269				did=${fwsl%%[[:space:]]*}
270				fwsl=${fwsl#*[[:space:]]}
271				# get flavor
272				flav=${fwsl%%[[:space:]]*}
273				fwsl=${fwsl#*[[:space:]]}
274
275				#printf "===> did %s flav %s\n" ${did} ${flav} >&2
276
277				echo "${did} ${flav}" | awk -v drv=${FWSUBDIR} '{
278					printf "\t\taddpkg \"wifi-firmware-%s-kmod-%s\"\n",
279					    drv, tolower($2);
280				}' >> ${fwgetfile}
281
282				i=$((i + 1))
283			done
284
285			printf "\t\treturn 1 ;;\n" >> ${fwgetfile}
286		fi
287	done
288fi
289
290printf "INFO: fwget pci_network_qca %s template at %s\n" ${DRIVER} ${fwgetfile} >&2
291
292# end
293