132e913d7SJoe Talbott#!/usr/bin/awk -f 232e913d7SJoe Talbott 332e913d7SJoe Talbott#- 432e913d7SJoe Talbott# Copyright (c) 2006 Max Laier. 532e913d7SJoe Talbott# All rights reserved. 632e913d7SJoe Talbott# 732e913d7SJoe Talbott# Redistribution and use in source and binary forms, with or without 832e913d7SJoe Talbott# modification, are permitted provided that the following conditions 932e913d7SJoe Talbott# are met: 1032e913d7SJoe Talbott# 1. Redistributions of source code must retain the above copyright 1132e913d7SJoe Talbott# notice, this list of conditions and the following disclaimer. 1232e913d7SJoe Talbott# 2. Redistributions in binary form must reproduce the above copyright 1332e913d7SJoe Talbott# notice, this list of conditions and the following disclaimer in the 1432e913d7SJoe Talbott# documentation and/or other materials provided with the distribution. 1532e913d7SJoe Talbott# 1632e913d7SJoe Talbott# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS'' AND 1732e913d7SJoe Talbott# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1832e913d7SJoe Talbott# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1932e913d7SJoe Talbott# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2032e913d7SJoe Talbott# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2132e913d7SJoe Talbott# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2232e913d7SJoe Talbott# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2332e913d7SJoe Talbott# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2432e913d7SJoe Talbott# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2532e913d7SJoe Talbott# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2632e913d7SJoe Talbott# SUCH DAMAGE. 2732e913d7SJoe Talbott# 2832e913d7SJoe Talbott# $FreeBSD: src/sys/tools/fw_stub.awk,v 1.6.10.2 2009/11/02 09:47:15 fjoe Exp $ 2932e913d7SJoe Talbott 3032e913d7SJoe Talbott# 3132e913d7SJoe Talbott# Script to generate module .c file from a list of firmware images 3232e913d7SJoe Talbott# 3332e913d7SJoe Talbott 3432e913d7SJoe Talbottfunction usage () 3532e913d7SJoe Talbott{ 36a8d7b48aSJan Sucan print "usage: fw_stub <firmware:name[:version[:parent]]>* [-l name] [-c outfile] -m modname"; 3732e913d7SJoe Talbott exit 1; 3832e913d7SJoe Talbott} 3932e913d7SJoe Talbott 4032e913d7SJoe Talbott# These are just for convenience ... 4132e913d7SJoe Talbottfunction printc(s) 4232e913d7SJoe Talbott{ 4332e913d7SJoe Talbott if (opt_c) 4432e913d7SJoe Talbott print s > ctmpfilename; 4532e913d7SJoe Talbott else 4632e913d7SJoe Talbott print s > "/dev/stdout"; 4732e913d7SJoe Talbott} 4832e913d7SJoe Talbott 4932e913d7SJoe TalbottBEGIN { 5032e913d7SJoe Talbott 5132e913d7SJoe Talbott# 5232e913d7SJoe Talbott# Process the command line. 5332e913d7SJoe Talbott# 5432e913d7SJoe Talbott 5532e913d7SJoe Talbottnum_files = 0; 5632e913d7SJoe Talbott 5732e913d7SJoe Talbottfor (i = 1; i < ARGC; i++) { 5832e913d7SJoe Talbott if (ARGV[i] ~ /^-/) { 5932e913d7SJoe Talbott # 6032e913d7SJoe Talbott # awk doesn't have getopt(), so we have to do it ourselves. 6132e913d7SJoe Talbott # This is a bit clumsy, but it works. 6232e913d7SJoe Talbott # 6332e913d7SJoe Talbott for (j = 2; j <= length(ARGV[i]); j++) { 6432e913d7SJoe Talbott o = substr(ARGV[i], j, 1); 6532e913d7SJoe Talbott if (o == "c") { 6632e913d7SJoe Talbott if (length(ARGV[i]) > j) { 6732e913d7SJoe Talbott opt_c = substr(ARGV[i], j + 1); 6832e913d7SJoe Talbott break; 6932e913d7SJoe Talbott } 7032e913d7SJoe Talbott else { 7178a3688bSJan Sucan if (++i < ARGC) { 7232e913d7SJoe Talbott opt_c = ARGV[i]; 7378a3688bSJan Sucan break; 7478a3688bSJan Sucan } else { 7532e913d7SJoe Talbott usage(); 7632e913d7SJoe Talbott } 7778a3688bSJan Sucan } 7832e913d7SJoe Talbott } else if (o == "m") { 7932e913d7SJoe Talbott if (length(ARGV[i]) > j) { 8032e913d7SJoe Talbott opt_m = substr(ARGV[i], j + 1); 8132e913d7SJoe Talbott break; 8232e913d7SJoe Talbott } 8332e913d7SJoe Talbott else { 8478a3688bSJan Sucan if (++i < ARGC) { 8532e913d7SJoe Talbott opt_m = ARGV[i]; 8678a3688bSJan Sucan break; 8778a3688bSJan Sucan } else { 8832e913d7SJoe Talbott usage(); 8932e913d7SJoe Talbott } 9078a3688bSJan Sucan } 9132e913d7SJoe Talbott } else if (o == "l") { 9232e913d7SJoe Talbott if (length(ARGV[i]) > j) { 9332e913d7SJoe Talbott opt_l = substr(ARGV[i], j + 1); 9432e913d7SJoe Talbott break; 9532e913d7SJoe Talbott } 9632e913d7SJoe Talbott else { 9778a3688bSJan Sucan if (++i < ARGC) { 9832e913d7SJoe Talbott opt_l = ARGV[i]; 9978a3688bSJan Sucan break; 10078a3688bSJan Sucan } else { 10132e913d7SJoe Talbott usage(); 10232e913d7SJoe Talbott } 10378a3688bSJan Sucan } 10432e913d7SJoe Talbott } else 10532e913d7SJoe Talbott usage(); 10632e913d7SJoe Talbott } 10732e913d7SJoe Talbott } else { 10832e913d7SJoe Talbott split(ARGV[i], curr, ":"); 10932e913d7SJoe Talbott filenames[num_files] = curr[1]; 11032e913d7SJoe Talbott if (length(curr[2]) > 0) 11132e913d7SJoe Talbott shortnames[num_files] = curr[2]; 11232e913d7SJoe Talbott else 11332e913d7SJoe Talbott shortnames[num_files] = curr[1]; 11432e913d7SJoe Talbott if (length(curr[3]) > 0) 11532e913d7SJoe Talbott versions[num_files] = int(curr[3]); 11632e913d7SJoe Talbott else 11732e913d7SJoe Talbott versions[num_files] = 0; 11832e913d7SJoe Talbott num_files++; 11932e913d7SJoe Talbott } 12032e913d7SJoe Talbott} 12132e913d7SJoe Talbott 12232e913d7SJoe Talbottif (!num_files || !opt_m) 12332e913d7SJoe Talbott usage(); 12432e913d7SJoe Talbott 12532e913d7SJoe Talbottcfilename = opt_c; 12632e913d7SJoe Talbottctmpfilename = cfilename ".tmp"; 12732e913d7SJoe Talbottmodname = opt_m; 12832e913d7SJoe Talbottgsub(/[-\.]/, "_", modname); 12932e913d7SJoe Talbott 130*f2219fd3SMatthew Dillonprintc("#include <sys/param.h>\n"\ 131*f2219fd3SMatthew Dillon "#include <sys/errno.h>\n"\ 132*f2219fd3SMatthew Dillon "#include <sys/kernel.h>\n"\ 133*f2219fd3SMatthew Dillon "#include <sys/module.h>\n"\ 134*f2219fd3SMatthew Dillon "#include <sys/linker.h>\n"\ 135*f2219fd3SMatthew Dillon "#include <sys/firmware.h>\n"\ 136*f2219fd3SMatthew Dillon "#include <sys/systm.h>\n"); 13732e913d7SJoe Talbott 13832e913d7SJoe Talbottif (opt_l) { 13932e913d7SJoe Talbott printc("static long " opt_l "_license_ack = 0;"); 14032e913d7SJoe Talbott} 14132e913d7SJoe Talbott 14232e913d7SJoe Talbottfor (file_i = 0; file_i < num_files; file_i++) { 14332e913d7SJoe Talbott symb = filenames[file_i]; 14432e913d7SJoe Talbott # '-', '.' and '/' are converted to '_' by ld/objcopy 14532e913d7SJoe Talbott gsub(/-|\.|\//, "_", symb); 14632e913d7SJoe Talbott printc("extern char _binary_" symb "_start[], _binary_" symb "_end[];"); 14732e913d7SJoe Talbott} 14832e913d7SJoe Talbott 149*f2219fd3SMatthew Dillonprintc(""); 150*f2219fd3SMatthew Dillonprintc("static int\n"\ 151*f2219fd3SMatthew Dillon modname "_fw_modevent(module_t mod, int type, void *unused)\n"\ 152*f2219fd3SMatthew Dillon "{\n"\ 153*f2219fd3SMatthew Dillon " const struct firmware *fp;"); 154092f4823SSepherosa Ziehau 155092f4823SSepherosa Ziehauif (num_files > 1) 156092f4823SSepherosa Ziehau printc("\tconst struct firmware *parent;"); 157092f4823SSepherosa Ziehau 158*f2219fd3SMatthew Dillonprintc(" int error;\n"\ 159*f2219fd3SMatthew Dillon "\n"\ 160*f2219fd3SMatthew Dillon " switch (type) {\n"\ 161*f2219fd3SMatthew Dillon " case MOD_LOAD:\n"); 16232e913d7SJoe Talbott 16332e913d7SJoe Talbottif (opt_l) { 164*f2219fd3SMatthew Dillon printc(""); 165*f2219fd3SMatthew Dillon printc("\tTUNABLE_LONG_FETCH(\"legal." opt_l ".license_ack\", &" opt_l "_license_ack);\n"\ 166*f2219fd3SMatthew Dillon "\tif (!" opt_l "_license_ack) {\n"\ 167*f2219fd3SMatthew Dillon "\t kprintf(\"" opt_m ": You need to read the LICENSE file in /usr/share/doc/legal/" opt_l "/.\\n\");\n"\ 168*f2219fd3SMatthew Dillon "\t kprintf(\"" opt_m ": If you agree with the license, set legal." opt_l ".license_ack=1 in /boot/loader.conf.\\n\");\n"\ 169*f2219fd3SMatthew Dillon "\t return(EPERM);\n"\ 170*f2219fd3SMatthew Dillon "\t}\n"); 17132e913d7SJoe Talbott} 17232e913d7SJoe Talbott 17332e913d7SJoe Talbottfor (file_i = 0; file_i < num_files; file_i++) { 17432e913d7SJoe Talbott short = shortnames[file_i]; 17532e913d7SJoe Talbott symb = filenames[file_i]; 17632e913d7SJoe Talbott version = versions[file_i]; 17732e913d7SJoe Talbott # '-', '.' and '/' are converted to '_' by ld/objcopy 17832e913d7SJoe Talbott gsub(/-|\.|\//, "_", symb); 17932e913d7SJoe Talbott 18032e913d7SJoe Talbott reg = "\t\tfp = "; 18132e913d7SJoe Talbott reg = reg "firmware_register(\"" short "\", _binary_" symb "_start , "; 18232e913d7SJoe Talbott reg = reg "(size_t)(_binary_" symb "_end - _binary_" symb "_start), "; 18332e913d7SJoe Talbott reg = reg version ", "; 18432e913d7SJoe Talbott 18532e913d7SJoe Talbott if (file_i == 0) 18632e913d7SJoe Talbott reg = reg "NULL);"; 18732e913d7SJoe Talbott else 18832e913d7SJoe Talbott reg = reg "parent);"; 18932e913d7SJoe Talbott 19032e913d7SJoe Talbott printc(reg); 19132e913d7SJoe Talbott 19232e913d7SJoe Talbott printc("\t\tif (fp == NULL)"); 19332e913d7SJoe Talbott printc("\t\t\tgoto fail_" file_i ";"); 194092f4823SSepherosa Ziehau if (file_i == 0 && num_files > 1) 19532e913d7SJoe Talbott printc("\t\tparent = fp;"); 19632e913d7SJoe Talbott} 19732e913d7SJoe Talbott 19832e913d7SJoe Talbottprintc("\t\treturn (0);"); 19932e913d7SJoe Talbott 20032e913d7SJoe Talbottfor (file_i = num_files - 1; file_i > 0; file_i--) { 20132e913d7SJoe Talbott printc("fail_" file_i ":") 20232e913d7SJoe Talbott printc("\t\t(void)firmware_unregister(\"" shortnames[file_i - 1] "\");"); 20332e913d7SJoe Talbott} 20432e913d7SJoe Talbott 20532e913d7SJoe Talbottprintc("\tfail_0:"); 20632e913d7SJoe Talbottprintc("\t\treturn (ENXIO);"); 20732e913d7SJoe Talbott 20832e913d7SJoe Talbottprintc("\tcase MOD_UNLOAD:"); 20932e913d7SJoe Talbott 21032e913d7SJoe Talbottfor (file_i = 1; file_i < num_files; file_i++) { 21132e913d7SJoe Talbott printc("\t\terror = firmware_unregister(\"" shortnames[file_i] "\");"); 21232e913d7SJoe Talbott printc("\t\tif (error)"); 21332e913d7SJoe Talbott printc("\t\t\treturn (error);"); 21432e913d7SJoe Talbott} 21532e913d7SJoe Talbott 21632e913d7SJoe Talbottprintc("\t\terror = firmware_unregister(\"" shortnames[0] "\");"); 21732e913d7SJoe Talbott 218*f2219fd3SMatthew Dillonprintc("\t\treturn (error);\n"\ 219*f2219fd3SMatthew Dillon " }\n"\ 220*f2219fd3SMatthew Dillon " return (EINVAL);\n"\ 221*f2219fd3SMatthew Dillon "}\n"\ 222*f2219fd3SMatthew Dillon "\n"\ 223*f2219fd3SMatthew Dillon "static moduledata_t " modname "_fw_mod = {\n"\ 224*f2219fd3SMatthew Dillon " \"" modname "_fw\",\n"\ 225*f2219fd3SMatthew Dillon " " modname "_fw_modevent,\n"\ 226*f2219fd3SMatthew Dillon " 0\n"\ 227*f2219fd3SMatthew Dillon "};\n"\ 228*f2219fd3SMatthew Dillon "DECLARE_MODULE(" modname "_fw, " modname "_fw_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);\n"\ 229*f2219fd3SMatthew Dillon "MODULE_VERSION(" modname "_fw, 1);\n"\ 230*f2219fd3SMatthew Dillon "MODULE_DEPEND(" modname "_fw, firmware, 1, 1, 1);\n"); 23132e913d7SJoe Talbott 23232e913d7SJoe Talbottif (opt_c) 23332e913d7SJoe Talbott if ((rc = system("mv -f " ctmpfilename " " cfilename))) { 23432e913d7SJoe Talbott print "'mv -f " ctmpfilename " " cfilename "' failed: " rc \ 23532e913d7SJoe Talbott > "/dev/stderr"; 23632e913d7SJoe Talbott exit 1; 23732e913d7SJoe Talbott } 23832e913d7SJoe Talbott 23932e913d7SJoe Talbottexit 0; 24032e913d7SJoe Talbott 24132e913d7SJoe Talbott} 242