fw_stub.awk revision 220227
1154974Smlaier#!/usr/bin/awk -f 2154974Smlaier 3154974Smlaier#- 4154974Smlaier# Copyright (c) 2006 Max Laier. 5154974Smlaier# All rights reserved. 6154974Smlaier# 7154974Smlaier# Redistribution and use in source and binary forms, with or without 8154974Smlaier# modification, are permitted provided that the following conditions 9154974Smlaier# are met: 10154974Smlaier# 1. Redistributions of source code must retain the above copyright 11154974Smlaier# notice, this list of conditions and the following disclaimer. 12154974Smlaier# 2. Redistributions in binary form must reproduce the above copyright 13154974Smlaier# notice, this list of conditions and the following disclaimer in the 14154974Smlaier# documentation and/or other materials provided with the distribution. 15154974Smlaier# 16154974Smlaier# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS'' AND 17154974Smlaier# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18154974Smlaier# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19154974Smlaier# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20154974Smlaier# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21154974Smlaier# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22154974Smlaier# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23154974Smlaier# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24154974Smlaier# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25154974Smlaier# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26154974Smlaier# SUCH DAMAGE. 27154974Smlaier# 28154974Smlaier# $FreeBSD: head/sys/tools/fw_stub.awk 220227 2011-03-31 21:33:33Z rstone $ 29154974Smlaier 30154974Smlaier# 31154974Smlaier# Script to generate module .c file from a list of firmware images 32154974Smlaier# 33154974Smlaier 34154974Smlaierfunction usage () 35154974Smlaier{ 36167165Sflz print "usage: fw_stub <firmware:name>* [-l name] [-m modname] [-c outfile]"; 37154974Smlaier exit 1; 38154974Smlaier} 39154974Smlaier 40154974Smlaier# These are just for convenience ... 41154974Smlaierfunction printc(s) 42154974Smlaier{ 43154974Smlaier if (opt_c) 44154974Smlaier print s > ctmpfilename; 45154974Smlaier else 46154974Smlaier print s > "/dev/stdout"; 47154974Smlaier} 48154974Smlaier 49154974SmlaierBEGIN { 50154974Smlaier 51154974Smlaier# 52154974Smlaier# Process the command line. 53154974Smlaier# 54154974Smlaier 55154974Smlaiernum_files = 0; 56154974Smlaier 57154974Smlaierfor (i = 1; i < ARGC; i++) { 58154974Smlaier if (ARGV[i] ~ /^-/) { 59154974Smlaier # 60154974Smlaier # awk doesn't have getopt(), so we have to do it ourselves. 61154974Smlaier # This is a bit clumsy, but it works. 62154974Smlaier # 63154974Smlaier for (j = 2; j <= length(ARGV[i]); j++) { 64154974Smlaier o = substr(ARGV[i], j, 1); 65154974Smlaier if (o == "c") { 66154974Smlaier if (length(ARGV[i]) > j) { 67154974Smlaier opt_c = substr(ARGV[i], j + 1); 68154974Smlaier break; 69154974Smlaier } 70154974Smlaier else { 71154974Smlaier if (++i < ARGC) 72154974Smlaier opt_c = ARGV[i]; 73154974Smlaier else 74154974Smlaier usage(); 75154974Smlaier } 76154974Smlaier } else if (o == "m") { 77154974Smlaier if (length(ARGV[i]) > j) { 78154974Smlaier opt_m = substr(ARGV[i], j + 1); 79154974Smlaier break; 80154974Smlaier } 81154974Smlaier else { 82154974Smlaier if (++i < ARGC) 83154974Smlaier opt_m = ARGV[i]; 84154974Smlaier else 85154974Smlaier usage(); 86154974Smlaier } 87167165Sflz } else if (o == "l") { 88167165Sflz if (length(ARGV[i]) > j) { 89167165Sflz opt_l = substr(ARGV[i], j + 1); 90167165Sflz break; 91167165Sflz } 92167165Sflz else { 93167165Sflz if (++i < ARGC) 94167165Sflz opt_l = ARGV[i]; 95167165Sflz else 96167165Sflz usage(); 97167165Sflz } 98154974Smlaier } else 99154974Smlaier usage(); 100154974Smlaier } 101154974Smlaier } else { 102154974Smlaier split(ARGV[i], curr, ":"); 103154974Smlaier filenames[num_files] = curr[1]; 104154974Smlaier if (length(curr[2]) > 0) 105154974Smlaier shortnames[num_files] = curr[2]; 106154974Smlaier else 107167077Sflz shortnames[num_files] = curr[1]; 108154974Smlaier if (length(curr[3]) > 0) 109154974Smlaier versions[num_files] = int(curr[3]); 110154974Smlaier else 111154974Smlaier versions[num_files] = 0; 112154974Smlaier num_files++; 113154974Smlaier } 114154974Smlaier} 115154974Smlaier 116154974Smlaierif (!num_files || !opt_m) 117154974Smlaier usage(); 118154974Smlaier 119154974Smlaiercfilename = opt_c; 120154974Smlaierctmpfilename = cfilename ".tmp"; 121198277Sfjoemodname = opt_m; 122198277Sfjoegsub(/[-\.]/, "_", modname); 123154974Smlaier 124198466Srpauloprintc("/*\ 125198466Srpaulo * Automatically generated by:\ 126198466Srpaulo * $FreeBSD: head/sys/tools/fw_stub.awk 220227 2011-03-31 21:33:33Z rstone $\ 127220227Srstone */"); 128220227Srstoneprintc("#include <sys/param.h>"); 129220227Srstoneprintc("#include <sys/errno.h>"); 130220227Srstoneprintc("#include <sys/kernel.h>"); 131220227Srstoneprintc("#include <sys/module.h>"); 132220227Srstoneprintc("#include <sys/linker.h>"); 133220227Srstoneprintc("#include <sys/firmware.h>"); 134220227Srstoneprintc("#include <sys/systm.h>\n"); 135154974Smlaier 136167165Sflzif (opt_l) { 137167165Sflz printc("static long " opt_l "_license_ack = 0;"); 138167165Sflz} 139167165Sflz 140154974Smlaierfor (file_i = 0; file_i < num_files; file_i++) { 141154974Smlaier symb = filenames[file_i]; 142154974Smlaier # '-', '.' and '/' are converted to '_' by ld/objcopy 143154974Smlaier gsub(/-|\.|\//, "_", symb); 144154974Smlaier printc("extern char _binary_" symb "_start[], _binary_" symb "_end[];"); 145154974Smlaier} 146154974Smlaier 147154974Smlaierprintc("\nstatic int\n"\ 148198277Sfjoemodname "_fw_modevent(module_t mod, int type, void *unused)\ 149154974Smlaier{\ 150166756Sluigi const struct firmware *fp, *parent;\ 151159670Sjhb int error;\ 152154974Smlaier switch (type) {\ 153167165Sflz case MOD_LOAD:\n"); 154154974Smlaier 155167165Sflzif (opt_l) { 156167165Sflz printc("\ 157167165Sflz TUNABLE_LONG_FETCH(\"legal." opt_l ".license_ack\", &" opt_l "_license_ack);\ 158167165Sflz if (!" opt_l "_license_ack) {\ 159167165Sflz printf(\"" opt_m ": You need to read the LICENSE file in /usr/share/doc/legal/" opt_l "/.\\n\");\ 160167165Sflz printf(\"" opt_m ": If you agree with the license, set legal." opt_l ".license_ack=1 in /boot/loader.conf.\\n\");\ 161167165Sflz return(EPERM);\ 162167165Sflz }\n"); 163167165Sflz} 164167165Sflz 165154974Smlaierfor (file_i = 0; file_i < num_files; file_i++) { 166154974Smlaier short = shortnames[file_i]; 167154974Smlaier symb = filenames[file_i]; 168154974Smlaier version = versions[file_i]; 169154974Smlaier # '-', '.' and '/' are converted to '_' by ld/objcopy 170154974Smlaier gsub(/-|\.|\//, "_", symb); 171154974Smlaier 172159670Sjhb reg = "\t\tfp = "; 173154974Smlaier reg = reg "firmware_register(\"" short "\", _binary_" symb "_start , "; 174154974Smlaier reg = reg "(size_t)(_binary_" symb "_end - _binary_" symb "_start), "; 175154974Smlaier reg = reg version ", "; 176154974Smlaier 177154974Smlaier if (file_i == 0) 178154974Smlaier reg = reg "NULL);"; 179154974Smlaier else 180159670Sjhb reg = reg "parent);"; 181154974Smlaier 182154974Smlaier printc(reg); 183159670Sjhb 184159670Sjhb printc("\t\tif (fp == NULL)"); 185159670Sjhb printc("\t\t\tgoto fail_" file_i ";"); 186159670Sjhb if (file_i == 0) 187159670Sjhb printc("\t\tparent = fp;"); 188154974Smlaier} 189154974Smlaier 190159670Sjhbprintc("\t\treturn (0);"); 191154974Smlaier 192159670Sjhbfor (file_i = num_files - 1; file_i > 0; file_i--) { 193167165Sflz printc("fail_" file_i ":") 194159670Sjhb printc("\t\t(void)firmware_unregister(\"" shortnames[file_i - 1] "\");"); 195159670Sjhb} 196159670Sjhb 197159670Sjhbprintc("\tfail_0:"); 198159670Sjhbprintc("\t\treturn (ENXIO);"); 199159670Sjhb 200159670Sjhbprintc("\tcase MOD_UNLOAD:"); 201159670Sjhb 202154974Smlaierfor (file_i = 1; file_i < num_files; file_i++) { 203159670Sjhb printc("\t\terror = firmware_unregister(\"" shortnames[file_i] "\");"); 204159670Sjhb printc("\t\tif (error)"); 205159670Sjhb printc("\t\t\treturn (error);"); 206154974Smlaier} 207154974Smlaier 208159670Sjhbprintc("\t\terror = firmware_unregister(\"" shortnames[0] "\");"); 209154974Smlaier 210159670Sjhbprintc("\t\treturn (error);\ 211154974Smlaier }\ 212154974Smlaier return (EINVAL);\ 213154974Smlaier}\ 214154974Smlaier\ 215198277Sfjoestatic moduledata_t " modname "_fw_mod = {\ 216198277Sfjoe \"" modname "_fw\",\ 217198277Sfjoe " modname "_fw_modevent,\ 218154974Smlaier 0\ 219154974Smlaier};\ 220198277SfjoeDECLARE_MODULE(" modname "_fw, " modname "_fw_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);\ 221198277SfjoeMODULE_VERSION(" modname "_fw, 1);\ 222198277SfjoeMODULE_DEPEND(" modname "_fw, firmware, 1, 1, 1);\ 223154974Smlaier"); 224154974Smlaier 225154974Smlaierif (opt_c) 226154974Smlaier if ((rc = system("mv -f " ctmpfilename " " cfilename))) { 227154974Smlaier print "'mv -f " ctmpfilename " " cfilename "' failed: " rc \ 228154974Smlaier > "/dev/stderr"; 229154974Smlaier exit 1; 230154974Smlaier } 231154974Smlaier 232154974Smlaierexit 0; 233154974Smlaier 234154974Smlaier} 235