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