fw_stub.awk revision 220227
1227825Stheraven#!/usr/bin/awk -f 2227825Stheraven 3227825Stheraven#- 4227825Stheraven# Copyright (c) 2006 Max Laier. 5227825Stheraven# All rights reserved. 6227825Stheraven# 7227825Stheraven# Redistribution and use in source and binary forms, with or without 8227825Stheraven# modification, are permitted provided that the following conditions 9227825Stheraven# are met: 10227825Stheraven# 1. Redistributions of source code must retain the above copyright 11227825Stheraven# notice, this list of conditions and the following disclaimer. 12227825Stheraven# 2. Redistributions in binary form must reproduce the above copyright 13227825Stheraven# notice, this list of conditions and the following disclaimer in the 14227825Stheraven# documentation and/or other materials provided with the distribution. 15227825Stheraven# 16227825Stheraven# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS'' AND 17227825Stheraven# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18227825Stheraven# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19227825Stheraven# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20227825Stheraven# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21227825Stheraven# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22227825Stheraven# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23227825Stheraven# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24232950Stheraven# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25227825Stheraven# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26227825Stheraven# SUCH DAMAGE. 27227825Stheraven# 28227825Stheraven# $FreeBSD: head/sys/tools/fw_stub.awk 220227 2011-03-31 21:33:33Z rstone $ 29227825Stheraven 30227825Stheraven# 31227825Stheraven# Script to generate module .c file from a list of firmware images 32227825Stheraven# 33227825Stheraven 34241903Sdimfunction usage () 35227825Stheraven{ 36241903Sdim print "usage: fw_stub <firmware:name>* [-l name] [-m modname] [-c outfile]"; 37241903Sdim exit 1; 38241903Sdim} 39241903Sdim 40227825Stheraven# These are just for convenience ... 41241903Sdimfunction printc(s) 42241903Sdim{ 43241903Sdim if (opt_c) 44241903Sdim print s > ctmpfilename; 45241903Sdim else 46227825Stheraven print s > "/dev/stdout"; 47227825Stheraven} 48227825Stheraven 49227825StheravenBEGIN { 50241903Sdim 51241903Sdim# 52227825Stheraven# Process the command line. 53227825Stheraven# 54227825Stheraven 55227825Stheravennum_files = 0; 56227825Stheraven 57227825Stheravenfor (i = 1; i < ARGC; i++) { 58227825Stheraven if (ARGV[i] ~ /^-/) { 59227825Stheraven # 60227825Stheraven # awk doesn't have getopt(), so we have to do it ourselves. 61227825Stheraven # This is a bit clumsy, but it works. 62227825Stheraven # 63227825Stheraven for (j = 2; j <= length(ARGV[i]); j++) { 64227825Stheraven o = substr(ARGV[i], j, 1); 65227825Stheraven if (o == "c") { 66227825Stheraven if (length(ARGV[i]) > j) { 67227825Stheraven opt_c = substr(ARGV[i], j + 1); 68227825Stheraven break; 69227825Stheraven } 70227825Stheraven else { 71227825Stheraven if (++i < ARGC) 72227825Stheraven opt_c = ARGV[i]; 73227825Stheraven else 74227825Stheraven usage(); 75227825Stheraven } 76227825Stheraven } else if (o == "m") { 77227825Stheraven if (length(ARGV[i]) > j) { 78227825Stheraven opt_m = substr(ARGV[i], j + 1); 79227825Stheraven break; 80227825Stheraven } 81227825Stheraven else { 82227825Stheraven if (++i < ARGC) 83227825Stheraven opt_m = ARGV[i]; 84227825Stheraven else 85227825Stheraven usage(); 86227825Stheraven } 87227825Stheraven } else if (o == "l") { 88227825Stheraven if (length(ARGV[i]) > j) { 89227825Stheraven opt_l = substr(ARGV[i], j + 1); 90227825Stheraven break; 91227825Stheraven } 92227825Stheraven else { 93227825Stheraven if (++i < ARGC) 94227825Stheraven opt_l = ARGV[i]; 95227825Stheraven else 96227825Stheraven usage(); 97227825Stheraven } 98227825Stheraven } else 99227825Stheraven usage(); 100227825Stheraven } 101227825Stheraven } else { 102227825Stheraven split(ARGV[i], curr, ":"); 103227825Stheraven filenames[num_files] = curr[1]; 104227825Stheraven if (length(curr[2]) > 0) 105227825Stheraven shortnames[num_files] = curr[2]; 106227825Stheraven else 107227825Stheraven shortnames[num_files] = curr[1]; 108227825Stheraven if (length(curr[3]) > 0) 109227825Stheraven versions[num_files] = int(curr[3]); 110227825Stheraven else 111227825Stheraven versions[num_files] = 0; 112227825Stheraven num_files++; 113227825Stheraven } 114227825Stheraven} 115227825Stheraven 116227825Stheravenif (!num_files || !opt_m) 117227825Stheraven usage(); 118227825Stheraven 119227825Stheravencfilename = opt_c; 120227825Stheravenctmpfilename = cfilename ".tmp"; 121227825Stheravenmodname = opt_m; 122227825Stheravengsub(/[-\.]/, "_", modname); 123227825Stheraven 124227825Stheravenprintc("/*\ 125227825Stheraven * Automatically generated by:\ 126227825Stheraven * $FreeBSD: head/sys/tools/fw_stub.awk 220227 2011-03-31 21:33:33Z rstone $\ 127227825Stheraven */"); 128227825Stheravenprintc("#include <sys/param.h>"); 129241903Sdimprintc("#include <sys/errno.h>"); 130227825Stheravenprintc("#include <sys/kernel.h>"); 131227825Stheravenprintc("#include <sys/module.h>"); 132227825Stheravenprintc("#include <sys/linker.h>"); 133227825Stheravenprintc("#include <sys/firmware.h>"); 134227825Stheravenprintc("#include <sys/systm.h>\n"); 135227825Stheraven 136227825Stheravenif (opt_l) { 137227825Stheraven printc("static long " opt_l "_license_ack = 0;"); 138227825Stheraven} 139227825Stheraven 140227825Stheravenfor (file_i = 0; file_i < num_files; file_i++) { 141227825Stheraven symb = filenames[file_i]; 142227825Stheraven # '-', '.' and '/' are converted to '_' by ld/objcopy 143227825Stheraven gsub(/-|\.|\//, "_", symb); 144227825Stheraven printc("extern char _binary_" symb "_start[], _binary_" symb "_end[];"); 145227825Stheraven} 146227825Stheraven 147227825Stheravenprintc("\nstatic int\n"\ 148227825Stheravenmodname "_fw_modevent(module_t mod, int type, void *unused)\ 149227825Stheraven{\ 150227825Stheraven const struct firmware *fp, *parent;\ 151227825Stheraven int error;\ 152227825Stheraven switch (type) {\ 153227825Stheraven case MOD_LOAD:\n"); 154227825Stheraven 155227825Stheravenif (opt_l) { 156227825Stheraven printc("\ 157227825Stheraven TUNABLE_LONG_FETCH(\"legal." opt_l ".license_ack\", &" opt_l "_license_ack);\ 158227825Stheraven if (!" opt_l "_license_ack) {\ 159227825Stheraven printf(\"" opt_m ": You need to read the LICENSE file in /usr/share/doc/legal/" opt_l "/.\\n\");\ 160227825Stheraven printf(\"" opt_m ": If you agree with the license, set legal." opt_l ".license_ack=1 in /boot/loader.conf.\\n\");\ 161227825Stheraven return(EPERM);\ 162227825Stheraven }\n"); 163227825Stheraven} 164227825Stheraven 165227825Stheravenfor (file_i = 0; file_i < num_files; file_i++) { 166227825Stheraven short = shortnames[file_i]; 167227825Stheraven symb = filenames[file_i]; 168227825Stheraven version = versions[file_i]; 169227825Stheraven # '-', '.' and '/' are converted to '_' by ld/objcopy 170227825Stheraven gsub(/-|\.|\//, "_", symb); 171227825Stheraven 172227825Stheraven reg = "\t\tfp = "; 173227825Stheraven reg = reg "firmware_register(\"" short "\", _binary_" symb "_start , "; 174227825Stheraven reg = reg "(size_t)(_binary_" symb "_end - _binary_" symb "_start), "; 175227825Stheraven reg = reg version ", "; 176227825Stheraven 177227825Stheraven if (file_i == 0) 178227825Stheraven reg = reg "NULL);"; 179227825Stheraven else 180227825Stheraven reg = reg "parent);"; 181227825Stheraven 182227825Stheraven printc(reg); 183227825Stheraven 184227825Stheraven printc("\t\tif (fp == NULL)"); 185227825Stheraven printc("\t\t\tgoto fail_" file_i ";"); 186227825Stheraven if (file_i == 0) 187227825Stheraven printc("\t\tparent = fp;"); 188227825Stheraven} 189227825Stheraven 190227825Stheravenprintc("\t\treturn (0);"); 191227825Stheraven 192227825Stheravenfor (file_i = num_files - 1; file_i > 0; file_i--) { 193227825Stheraven printc("fail_" file_i ":") 194227825Stheraven printc("\t\t(void)firmware_unregister(\"" shortnames[file_i - 1] "\");"); 195227825Stheraven} 196227825Stheraven 197227825Stheravenprintc("\tfail_0:"); 198227825Stheravenprintc("\t\treturn (ENXIO);"); 199227825Stheraven 200227825Stheravenprintc("\tcase MOD_UNLOAD:"); 201227825Stheraven 202227825Stheravenfor (file_i = 1; file_i < num_files; file_i++) { 203227825Stheraven printc("\t\terror = firmware_unregister(\"" shortnames[file_i] "\");"); 204227825Stheraven printc("\t\tif (error)"); 205227825Stheraven printc("\t\t\treturn (error);"); 206227825Stheraven} 207227825Stheraven 208227825Stheravenprintc("\t\terror = firmware_unregister(\"" shortnames[0] "\");"); 209227825Stheraven 210227825Stheravenprintc("\t\treturn (error);\ 211227825Stheraven }\ 212227825Stheraven return (EINVAL);\ 213227825Stheraven}\ 214227825Stheraven\ 215227825Stheravenstatic moduledata_t " modname "_fw_mod = {\ 216227825Stheraven \"" modname "_fw\",\ 217227825Stheraven " modname "_fw_modevent,\ 218227825Stheraven 0\ 219227825Stheraven};\ 220227825StheravenDECLARE_MODULE(" modname "_fw, " modname "_fw_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);\ 221227825StheravenMODULE_VERSION(" modname "_fw, 1);\ 222227825StheravenMODULE_DEPEND(" modname "_fw, firmware, 1, 1, 1);\ 223227825Stheraven"); 224227825Stheraven 225227825Stheravenif (opt_c) 226227825Stheraven if ((rc = system("mv -f " ctmpfilename " " cfilename))) { 227227825Stheraven print "'mv -f " ctmpfilename " " cfilename "' failed: " rc \ 228227825Stheraven > "/dev/stderr"; 229227825Stheraven exit 1; 230227825Stheraven } 231227825Stheraven 232227825Stheravenexit 0; 233227825Stheraven 234227825Stheraven} 235227825Stheraven