1#!/bin/sh 2 3set -e 4 5if [ "$#" -eq 0 ] || [ "$#" -gt 2 ]; then 6 echo "Usage: $(basename $0) fw.bin [module_prefix]" 7 exit 1 8fi 9 10if [ ! -f $1 ]; then 11 echo "File $1 does not exist" 12 exit 1 13fi 14 15if [ "$#" -eq 2 ]; then 16MOD_PREFIX=$2 17fi 18 19MODULEDIR=${MODULEDIR:-/boot/modules.local} 20WORKDIR=$(mktemp -d) 21CURDIR=$PWD 22 23FWFILE=$(basename "$1") 24# strip .bin and .fw extensions 25MODNAME=$(basename $(basename "$1" .bin) .fw) 26 27# if module_prefix is provided, append to module name 28if [ "$#" -eq 2 ]; then 29MODNAME=${MOD_PREFIX}${MODNAME} 30fi 31 32# copy firmware file to workdir 33cp -v "$1" "$WORKDIR"/"$FWFILE" 34 35# prefer to use /sys build but provide workaround too 36if [ -f /sys/tools/fw_stub.awk ]; 37then 38echo "KMOD= ${MODNAME}" > "$WORKDIR"/Makefile 39echo "FIRMWS= ${FWFILE}:${MODNAME}" >> "$WORKDIR"/Makefile 40echo ".include <bsd.kmod.mk>" >> "$WORKDIR"/Makefile 41 42(cd $WORKDIR && make) 43 44else 45# workaround case to build a local fw module version w/o kernel sources (should have no impact) 46set -x 47 48# ld/objcopy substitutes ' ', '-', '.' and '/' to '_' 49FWSYM=$(echo ${FWFILE} |sed 's/ /_/g' | sed 's/-/_/g' |sed 's/\./_/g' |sed 's/\/_//g') 50echo FWSYM=${FWSYM} 51 52cd $WORKDIR 53ld -b binary --no-warn-mismatch -r -d -o "${FWFILE}.fwo" "${FWFILE}" 54 55cat << EOF >> ${MODNAME}.c 56#include <sys/param.h> 57#include <sys/errno.h> 58#include <sys/kernel.h> 59#include <sys/module.h> 60#include <sys/linker.h> 61#include <sys/firmware.h> 62//#include <sys/systm.h> 63 64extern char _binary_${FWSYM}_start[], _binary_${FWSYM}_end[]; 65 66static int 67${MODNAME}_fw_modevent(module_t mod, int type, void *unused) 68{ 69 const struct firmware *fp; 70 int error; 71 switch (type) { 72 case MOD_LOAD: 73 fp = firmware_register("${MODNAME}", _binary_${FWSYM}_start , (size_t)(_binary_${FWSYM}_end - _binary_${FWSYM}_start), 0, NULL); 74 if (fp == NULL) 75 goto fail_0; 76 return (0); 77fail_0: 78 return (ENXIO); 79 case MOD_UNLOAD: 80 error = firmware_unregister("${MODNAME}"); 81 return (error); 82 } 83 return (EINVAL); 84} 85 86static moduledata_t ${MODNAME}_fw_mod = { 87 "${MODNAME}_fw", 88 ${MODNAME}_fw_modevent, 89 0 90}; 91DECLARE_MODULE(${MODNAME}_fw, ${MODNAME}_fw_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 92MODULE_VERSION(${MODNAME}_fw, 1); 93MODULE_DEPEND(${MODNAME}_fw, firmware, 1, 1, 1); 94EOF 95 96FFLAGS="-fno-common -ffreestanding -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -fno-stack-protector" 97cc -O -pipe -D_KERNEL -Wall -std=c99 -Werror -DKLD_MODULE ${FFLAGS} -mcmodel=kernel -mno-red-zone -c "${MODNAME}.c" 98ld -r -d -o "${MODNAME}.ko" "${FWFILE}.fwo" "${MODNAME}.o" 99 100fi 101 102 103# copy firmware module to external modules dir 104cp -v "$WORKDIR/$MODNAME.ko" "${MODULEDIR}/" 105 106rm -rf "${WORKDIR}" 107