fw_stub.awk revision 159670
118099Spst#!/usr/bin/awk -f
218099Spst
318099Spst#-
418099Spst# Copyright (c) 2006 Max Laier.
518099Spst# All rights reserved.
618099Spst#
718099Spst# Redistribution and use in source and binary forms, with or without
818099Spst# modification, are permitted provided that the following conditions
918099Spst# are met:
1018099Spst# 1. Redistributions of source code must retain the above copyright
1118099Spst#    notice, this list of conditions and the following disclaimer.
1218099Spst# 2. Redistributions in binary form must reproduce the above copyright
1318099Spst#    notice, this list of conditions and the following disclaimer in the
1418099Spst#    documentation and/or other materials provided with the distribution.
1518099Spst#
1618099Spst# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS'' AND
1718099Spst# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1818099Spst# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1918099Spst# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2055839Sasmodai# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2118099Spst# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2255839Sasmodai# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2318099Spst# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2418099Spst# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2555839Sasmodai# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2618099Spst# SUCH DAMAGE.
2718099Spst#
2818099Spst# $FreeBSD: head/sys/tools/fw_stub.awk 159670 2006-06-16 21:06:03Z jhb $
2918099Spst
3018099Spst#
3118099Spst# Script to generate module .c file from a list of firmware images
3255839Sasmodai#
3318099Spst
3455839Sasmodaifunction usage ()
3518099Spst{
3618099Spst	print "usage: fw_stub <firmware:name>* [-m modname] [-c outfile]";
3718099Spst	exit 1;
3818099Spst}
3918099Spst
4018099Spst#   These are just for convenience ...
4118099Spstfunction printc(s)
4218099Spst{
4355839Sasmodai	if (opt_c)
4455839Sasmodai		print s > ctmpfilename;
4518099Spst	else
4618099Spst		print s > "/dev/stdout";
4718099Spst}
4818099Spst
4918099SpstBEGIN {
5018099Spst
5118099Spst#
5255839Sasmodai#   Process the command line.
5355839Sasmodai#
5418099Spst
5518099Spstnum_files = 0;
5655839Sasmodai
5718099Spstfor (i = 1; i < ARGC; i++) {
5818099Spst	if (ARGV[i] ~ /^-/) {
5955839Sasmodai		#
6055839Sasmodai		#   awk doesn't have getopt(), so we have to do it ourselves.
6118099Spst		#   This is a bit clumsy, but it works.
6255839Sasmodai		#
6318099Spst		for (j = 2; j <= length(ARGV[i]); j++) {
6418099Spst			o = substr(ARGV[i], j, 1);
6518099Spst			if (o == "c") {
6618099Spst				if (length(ARGV[i]) > j) {
6718099Spst					opt_c = substr(ARGV[i], j + 1);
6818099Spst					break;
6918099Spst				}
7018099Spst				else {
7118099Spst					if (++i < ARGC)
7255839Sasmodai						opt_c = ARGV[i];
7318099Spst					else
7418099Spst						usage();
7518099Spst				}
7618099Spst			} else if (o == "m") {
7755839Sasmodai				if (length(ARGV[i]) > j) {
7855839Sasmodai					opt_m = substr(ARGV[i], j + 1);
7955839Sasmodai					break;
8018099Spst				}
8155839Sasmodai				else {
8218099Spst					if (++i < ARGC)
8318099Spst						opt_m = ARGV[i];
8418099Spst					else
8518099Spst						usage();
8618099Spst				}
8718099Spst			} else
8818099Spst				usage();
8918099Spst		}
9018099Spst	} else {
9118099Spst		split(ARGV[i], curr, ":");
9218099Spst		filenames[num_files] = curr[1];
9355839Sasmodai		if (length(curr[2]) > 0)
9455839Sasmodai			shortnames[num_files] = curr[2];
9518099Spst		else
9618099Spst			shortnames[num_files] = curr[2];
9718099Spst		if (length(curr[3]) > 0)
9818099Spst			versions[num_files] = int(curr[3]);
9918099Spst		else
10018099Spst			versions[num_files] = 0;
10118099Spst		num_files++;
10218099Spst	}
10318099Spst}
10455839Sasmodai
10555839Sasmodaiif (!num_files || !opt_m)
10618099Spst	usage();
10718099Spst
10818099Spstcfilename = opt_c;
10918099Spstctmpfilename = cfilename ".tmp";
11055839Sasmodai
11155839Sasmodaiprintc("#include <sys/param.h>\
11255839Sasmodai#include <sys/errno.h>\
11318099Spst#include <sys/kernel.h>\
11418099Spst#include <sys/module.h>\
11518099Spst#include <sys/linker.h>\
11618099Spst#include <sys/firmware.h>\n");
11755839Sasmodai
11855839Sasmodaifor (file_i = 0; file_i < num_files; file_i++) {
11918099Spst	symb = filenames[file_i];
12018099Spst	# '-', '.' and '/' are converted to '_' by ld/objcopy
12155839Sasmodai	gsub(/-|\.|\//, "_", symb);
12255839Sasmodai	printc("extern char _binary_" symb "_start[], _binary_" symb "_end[];");
12318099Spst}
12418099Spst
12518099Spstprintc("\nstatic int\n"\
12618099Spstopt_m "_fw_modevent(module_t mod, int type, void *unused)\
12718099Spst{\
12855839Sasmodai	struct firmware *fp, *parent;\
12955839Sasmodai	int error;\
13055839Sasmodai	switch (type) {\
13118099Spst	case MOD_LOAD:");
13255839Sasmodai
13355839Sasmodaifor (file_i = 0; file_i < num_files; file_i++) {
13418099Spst	short = shortnames[file_i];
13518099Spst	symb = filenames[file_i];
13618099Spst	version = versions[file_i];
13718099Spst	# '-', '.' and '/' are converted to '_' by ld/objcopy
13818099Spst	gsub(/-|\.|\//, "_", symb);
13955839Sasmodai
14055839Sasmodai	reg = "\t\tfp = ";
14118099Spst	reg = reg "firmware_register(\"" short "\", _binary_" symb "_start , ";
14218099Spst	reg = reg "(size_t)(_binary_" symb "_end - _binary_" symb "_start), ";
14355839Sasmodai	reg = reg version ", ";
14455839Sasmodai
14518099Spst	if (file_i == 0)
14618099Spst		reg = reg "NULL);";
14718099Spst	else
14818099Spst		reg = reg "parent);";
14918099Spst
15055839Sasmodai	printc(reg);
15155839Sasmodai
15218099Spst	printc("\t\tif (fp == NULL)");
15318099Spst	printc("\t\t\tgoto fail_" file_i ";");
15455839Sasmodai	if (file_i == 0)
15555839Sasmodai		printc("\t\tparent = fp;");
15655839Sasmodai}
15755839Sasmodai
15855839Sasmodaiprintc("\t\treturn (0);");
15955839Sasmodai
16055839Sasmodaifor (file_i = num_files - 1; file_i > 0; file_i--) {
16155839Sasmodai	printc("\tfail_" file_i ":")
16255839Sasmodai	printc("\t\t(void)firmware_unregister(\"" shortnames[file_i - 1] "\");");
16355839Sasmodai}
16455839Sasmodai
16555839Sasmodaiprintc("\tfail_0:");
16655839Sasmodaiprintc("\t\treturn (ENXIO);");
16755839Sasmodai
16855839Sasmodaiprintc("\tcase MOD_UNLOAD:");
16955839Sasmodai
17055839Sasmodaifor (file_i = 1; file_i < num_files; file_i++) {
17155839Sasmodai	printc("\t\terror = firmware_unregister(\"" shortnames[file_i] "\");");
17255839Sasmodai	printc("\t\tif (error)");
17355839Sasmodai	printc("\t\t\treturn (error);");
17455839Sasmodai}
17555839Sasmodai
17655839Sasmodaiprintc("\t\terror = firmware_unregister(\"" shortnames[0] "\");");
17755839Sasmodai
17855839Sasmodaiprintc("\t\treturn (error);\
17955839Sasmodai	}\
18055839Sasmodai	return (EINVAL);\
18155839Sasmodai}\
18255839Sasmodai\
18355839Sasmodaistatic moduledata_t " opt_m "_fw_mod = {\
18455839Sasmodai        \"" opt_m "_fw\",\
18555839Sasmodai        " opt_m "_fw_modevent,\
18655839Sasmodai        0\
18755839Sasmodai};\
18855839SasmodaiDECLARE_MODULE(" opt_m "_fw, " opt_m "_fw_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);\
18955839SasmodaiMODULE_VERSION(" opt_m "_fw, 1);\
19055839SasmodaiMODULE_DEPEND(" opt_m "_fw, firmware, 1, 1, 1);\
19118099Spst");
19218099Spst
19318099Spstif (opt_c)
19418099Spst	if ((rc = system("mv -f " ctmpfilename " " cfilename))) {
19518099Spst		print "'mv -f " ctmpfilename " " cfilename "' failed: " rc \
19655839Sasmodai		    > "/dev/stderr";
19755839Sasmodai		exit 1;
19818099Spst	}
19918099Spst
20055839Sasmodaiexit 0;
20155839Sasmodai
20218099Spst}
20318099Spst