16aec1278SMax Laier#!/usr/bin/awk -f 26aec1278SMax Laier 36aec1278SMax Laier#- 44d846d26SWarner Losh# SPDX-License-Identifier: BSD-2-Clause 5fe267a55SPedro F. Giffuni# 66aec1278SMax Laier# Copyright (c) 2006 Max Laier. 76aec1278SMax Laier# All rights reserved. 86aec1278SMax Laier# 96aec1278SMax Laier# Redistribution and use in source and binary forms, with or without 106aec1278SMax Laier# modification, are permitted provided that the following conditions 116aec1278SMax Laier# are met: 126aec1278SMax Laier# 1. Redistributions of source code must retain the above copyright 136aec1278SMax Laier# notice, this list of conditions and the following disclaimer. 146aec1278SMax Laier# 2. Redistributions in binary form must reproduce the above copyright 156aec1278SMax Laier# notice, this list of conditions and the following disclaimer in the 166aec1278SMax Laier# documentation and/or other materials provided with the distribution. 176aec1278SMax Laier# 186aec1278SMax Laier# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS'' AND 196aec1278SMax Laier# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 206aec1278SMax Laier# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 216aec1278SMax Laier# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 226aec1278SMax Laier# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 236aec1278SMax Laier# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 246aec1278SMax Laier# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 256aec1278SMax Laier# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 266aec1278SMax Laier# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 276aec1278SMax Laier# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 286aec1278SMax Laier# SUCH DAMAGE. 296aec1278SMax Laier# 306aec1278SMax Laier 316aec1278SMax Laier# 326aec1278SMax Laier# Script to generate module .c file from a list of firmware images 336aec1278SMax Laier# 346aec1278SMax Laier 356aec1278SMax Laierfunction usage () 366aec1278SMax Laier{ 377bd6fde3SFlorent Thoumie print "usage: fw_stub <firmware:name>* [-l name] [-m modname] [-c outfile]"; 386aec1278SMax Laier exit 1; 396aec1278SMax Laier} 406aec1278SMax Laier 416aec1278SMax Laier# These are just for convenience ... 426aec1278SMax Laierfunction printc(s) 436aec1278SMax Laier{ 446aec1278SMax Laier if (opt_c) 456aec1278SMax Laier print s > ctmpfilename; 466aec1278SMax Laier else 476aec1278SMax Laier print s > "/dev/stdout"; 486aec1278SMax Laier} 496aec1278SMax Laier 506aec1278SMax LaierBEGIN { 516aec1278SMax Laier 526aec1278SMax Laier# 536aec1278SMax Laier# Process the command line. 546aec1278SMax Laier# 556aec1278SMax Laier 566aec1278SMax Laiernum_files = 0; 576aec1278SMax Laier 586aec1278SMax Laierfor (i = 1; i < ARGC; i++) { 596aec1278SMax Laier if (ARGV[i] ~ /^-/) { 606aec1278SMax Laier # 616aec1278SMax Laier # awk doesn't have getopt(), so we have to do it ourselves. 626aec1278SMax Laier # This is a bit clumsy, but it works. 636aec1278SMax Laier # 646aec1278SMax Laier for (j = 2; j <= length(ARGV[i]); j++) { 656aec1278SMax Laier o = substr(ARGV[i], j, 1); 666aec1278SMax Laier if (o == "c") { 676aec1278SMax Laier if (length(ARGV[i]) > j) { 686aec1278SMax Laier opt_c = substr(ARGV[i], j + 1); 696aec1278SMax Laier break; 706aec1278SMax Laier } 716aec1278SMax Laier else { 726aec1278SMax Laier if (++i < ARGC) 736aec1278SMax Laier opt_c = ARGV[i]; 746aec1278SMax Laier else 756aec1278SMax Laier usage(); 766aec1278SMax Laier } 776aec1278SMax Laier } else if (o == "m") { 786aec1278SMax Laier if (length(ARGV[i]) > j) { 796aec1278SMax Laier opt_m = substr(ARGV[i], j + 1); 806aec1278SMax Laier break; 816aec1278SMax Laier } 826aec1278SMax Laier else { 836aec1278SMax Laier if (++i < ARGC) 846aec1278SMax Laier opt_m = ARGV[i]; 856aec1278SMax Laier else 866aec1278SMax Laier usage(); 876aec1278SMax Laier } 887bd6fde3SFlorent Thoumie } else if (o == "l") { 897bd6fde3SFlorent Thoumie if (length(ARGV[i]) > j) { 907bd6fde3SFlorent Thoumie opt_l = substr(ARGV[i], j + 1); 917bd6fde3SFlorent Thoumie break; 927bd6fde3SFlorent Thoumie } 937bd6fde3SFlorent Thoumie else { 947bd6fde3SFlorent Thoumie if (++i < ARGC) 957bd6fde3SFlorent Thoumie opt_l = ARGV[i]; 967bd6fde3SFlorent Thoumie else 977bd6fde3SFlorent Thoumie usage(); 987bd6fde3SFlorent Thoumie } 996aec1278SMax Laier } else 1006aec1278SMax Laier usage(); 1016aec1278SMax Laier } 1026aec1278SMax Laier } else { 1036aec1278SMax Laier split(ARGV[i], curr, ":"); 1046aec1278SMax Laier filenames[num_files] = curr[1]; 1056aec1278SMax Laier if (length(curr[2]) > 0) 1066aec1278SMax Laier shortnames[num_files] = curr[2]; 1076aec1278SMax Laier else 1084af453dbSFlorent Thoumie shortnames[num_files] = curr[1]; 1096aec1278SMax Laier if (length(curr[3]) > 0) 1106aec1278SMax Laier versions[num_files] = int(curr[3]); 1116aec1278SMax Laier else 1126aec1278SMax Laier versions[num_files] = 0; 1136aec1278SMax Laier num_files++; 1146aec1278SMax Laier } 1156aec1278SMax Laier} 1166aec1278SMax Laier 1176aec1278SMax Laierif (!num_files || !opt_m) 1186aec1278SMax Laier usage(); 1196aec1278SMax Laier 1206aec1278SMax Laiercfilename = opt_c; 1216aec1278SMax Laierctmpfilename = cfilename ".tmp"; 122b352b7ccSMax Khonmodname = opt_m; 123b352b7ccSMax Khongsub(/[-\.]/, "_", modname); 1246aec1278SMax Laier 1259a069ff5SEd Maste# Avoid a literal generated file tag here. 1269a069ff5SEd Mastegenerated = "@" "generated"; 127f91c218bSRui Pauloprintc("/*\ 128*fa12e8feSWarner Losh * Automatically " generated "\ 12904af6e96SRyan Stone */"); 13004af6e96SRyan Stoneprintc("#include <sys/param.h>"); 13104af6e96SRyan Stoneprintc("#include <sys/errno.h>"); 13204af6e96SRyan Stoneprintc("#include <sys/kernel.h>"); 13304af6e96SRyan Stoneprintc("#include <sys/module.h>"); 13404af6e96SRyan Stoneprintc("#include <sys/linker.h>"); 13504af6e96SRyan Stoneprintc("#include <sys/firmware.h>"); 13604af6e96SRyan Stoneprintc("#include <sys/systm.h>\n"); 1377bd6fde3SFlorent Thoumie 1387bd6fde3SFlorent Thoumieif (opt_l) { 1397bd6fde3SFlorent Thoumie printc("static long " opt_l "_license_ack = 0;"); 1407bd6fde3SFlorent Thoumie} 1416aec1278SMax Laier 1426aec1278SMax Laierfor (file_i = 0; file_i < num_files; file_i++) { 1436aec1278SMax Laier symb = filenames[file_i]; 144628a4156SJohn Baldwin # '-', '.', '/', and '@' are converted to '_' 145628a4156SJohn Baldwin gsub(/-|\.|\/|@/, "_", symb); 1466aec1278SMax Laier printc("extern char _binary_" symb "_start[], _binary_" symb "_end[];"); 1476aec1278SMax Laier} 1486aec1278SMax Laier 1496aec1278SMax Laierprintc("\nstatic int\n"\ 150b352b7ccSMax Khonmodname "_fw_modevent(module_t mod, int type, void *unused)\ 1516aec1278SMax Laier{\ 152b394e16eSBjoern A. Zeeb const struct firmware *fp;"); 153b394e16eSBjoern A. Zeebif (num_files > 1) 154b394e16eSBjoern A. Zeeb printc("\tconst struct firmware *parent;"); 155b394e16eSBjoern A. Zeebprintc("\tint error;\ 1566aec1278SMax Laier switch (type) {\ 1577bd6fde3SFlorent Thoumie case MOD_LOAD:\n"); 1587bd6fde3SFlorent Thoumie 1597bd6fde3SFlorent Thoumieif (opt_l) { 1607bd6fde3SFlorent Thoumie printc("\ 1617bd6fde3SFlorent Thoumie TUNABLE_LONG_FETCH(\"legal." opt_l ".license_ack\", &" opt_l "_license_ack);\ 1627bd6fde3SFlorent Thoumie if (!" opt_l "_license_ack) {\ 163cada39d8SBryan Drewery printf(\"" opt_m ": You need to read the LICENSE file in /usr/share/doc/legal/" opt_l ".LICENSE.\\n\");\ 1647bd6fde3SFlorent Thoumie printf(\"" opt_m ": If you agree with the license, set legal." opt_l ".license_ack=1 in /boot/loader.conf.\\n\");\ 1657bd6fde3SFlorent Thoumie return(EPERM);\ 1667bd6fde3SFlorent Thoumie }\n"); 1677bd6fde3SFlorent Thoumie} 1686aec1278SMax Laier 1696aec1278SMax Laierfor (file_i = 0; file_i < num_files; file_i++) { 1706aec1278SMax Laier short = shortnames[file_i]; 1716aec1278SMax Laier symb = filenames[file_i]; 1726aec1278SMax Laier version = versions[file_i]; 173628a4156SJohn Baldwin # '-', '.', '/', and '@' are converted to '_' 174628a4156SJohn Baldwin gsub(/-|\.|\/|@/, "_", symb); 1756aec1278SMax Laier 1766aec1278SMax Laier reg = "\t\tfp = "; 1776aec1278SMax Laier reg = reg "firmware_register(\"" short "\", _binary_" symb "_start , "; 1786aec1278SMax Laier reg = reg "(size_t)(_binary_" symb "_end - _binary_" symb "_start), "; 1796aec1278SMax Laier reg = reg version ", "; 1806aec1278SMax Laier 1816aec1278SMax Laier if (file_i == 0) 1826aec1278SMax Laier reg = reg "NULL);"; 1836aec1278SMax Laier else 184c3e7da2bSJohn Baldwin reg = reg "parent);"; 1856aec1278SMax Laier 1866aec1278SMax Laier printc(reg); 187c3e7da2bSJohn Baldwin 188c3e7da2bSJohn Baldwin printc("\t\tif (fp == NULL)"); 189c3e7da2bSJohn Baldwin printc("\t\t\tgoto fail_" file_i ";"); 190b394e16eSBjoern A. Zeeb if (file_i == 0 && num_files > 1) 191c3e7da2bSJohn Baldwin printc("\t\tparent = fp;"); 1926aec1278SMax Laier} 1936aec1278SMax Laier 194c3e7da2bSJohn Baldwinprintc("\t\treturn (0);"); 195c3e7da2bSJohn Baldwin 196c3e7da2bSJohn Baldwinfor (file_i = num_files - 1; file_i > 0; file_i--) { 1977bd6fde3SFlorent Thoumie printc("fail_" file_i ":") 198c3e7da2bSJohn Baldwin printc("\t\t(void)firmware_unregister(\"" shortnames[file_i - 1] "\");"); 199c3e7da2bSJohn Baldwin} 200c3e7da2bSJohn Baldwin 201c3e7da2bSJohn Baldwinprintc("\tfail_0:"); 202c3e7da2bSJohn Baldwinprintc("\t\treturn (ENXIO);"); 203c3e7da2bSJohn Baldwin 204c3e7da2bSJohn Baldwinprintc("\tcase MOD_UNLOAD:"); 2056aec1278SMax Laier 2066aec1278SMax Laierfor (file_i = 1; file_i < num_files; file_i++) { 207c3e7da2bSJohn Baldwin printc("\t\terror = firmware_unregister(\"" shortnames[file_i] "\");"); 208c3e7da2bSJohn Baldwin printc("\t\tif (error)"); 209c3e7da2bSJohn Baldwin printc("\t\t\treturn (error);"); 2106aec1278SMax Laier} 2116aec1278SMax Laier 212c3e7da2bSJohn Baldwinprintc("\t\terror = firmware_unregister(\"" shortnames[0] "\");"); 2136aec1278SMax Laier 214c3e7da2bSJohn Baldwinprintc("\t\treturn (error);\ 2156aec1278SMax Laier }\ 2166aec1278SMax Laier return (EINVAL);\ 2176aec1278SMax Laier}\ 2186aec1278SMax Laier\ 219b352b7ccSMax Khonstatic moduledata_t " modname "_fw_mod = {\ 220b352b7ccSMax Khon \"" modname "_fw\",\ 221b352b7ccSMax Khon " modname "_fw_modevent,\ 2229823d527SKevin Lo 0\ 2236aec1278SMax Laier};\ 224b352b7ccSMax KhonDECLARE_MODULE(" modname "_fw, " modname "_fw_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);\ 225b352b7ccSMax KhonMODULE_VERSION(" modname "_fw, 1);\ 226b352b7ccSMax KhonMODULE_DEPEND(" modname "_fw, firmware, 1, 1, 1);\ 2276aec1278SMax Laier"); 2286aec1278SMax Laier 2296aec1278SMax Laierif (opt_c) 2306aec1278SMax Laier if ((rc = system("mv -f " ctmpfilename " " cfilename))) { 2316aec1278SMax Laier print "'mv -f " ctmpfilename " " cfilename "' failed: " rc \ 2326aec1278SMax Laier > "/dev/stderr"; 2336aec1278SMax Laier exit 1; 2346aec1278SMax Laier } 2356aec1278SMax Laier 2366aec1278SMax Laierexit 0; 2376aec1278SMax Laier 2386aec1278SMax Laier} 239