xref: /dflybsd-src/sys/tools/fw_stub.awk (revision f2219fd3f675d0f96d4fd693c7c3472b7d725ac2)
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