fw_stub.awk revision 154974
133965Sjdp#!/usr/bin/awk -f
2218822Sdim
3104834Sobrien#-
433965Sjdp# Copyright (c) 2006 Max Laier.
533965Sjdp# All rights reserved.
633965Sjdp#
733965Sjdp# Redistribution and use in source and binary forms, with or without
833965Sjdp# modification, are permitted provided that the following conditions
933965Sjdp# are met:
1033965Sjdp# 1. Redistributions of source code must retain the above copyright
1133965Sjdp#    notice, this list of conditions and the following disclaimer.
1233965Sjdp# 2. Redistributions in binary form must reproduce the above copyright
1333965Sjdp#    notice, this list of conditions and the following disclaimer in the
1433965Sjdp#    documentation and/or other materials provided with the distribution.
1533965Sjdp#
1633965Sjdp# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS'' AND
1733965Sjdp# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1833965Sjdp# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19218822Sdim# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2033965Sjdp# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2133965Sjdp# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2233965Sjdp# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2333965Sjdp# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2433965Sjdp# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2533965Sjdp# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2633965Sjdp# SUCH DAMAGE.
2733965Sjdp#
2833965Sjdp# $FreeBSD: head/sys/tools/fw_stub.awk 154974 2006-01-29 02:52:42Z mlaier $
29218822Sdim
30104834Sobrien#
31104834Sobrien# Script to generate module .c file from a list of firmware images
3233965Sjdp#
3333965Sjdp
3433965Sjdpfunction usage ()
35218822Sdim{
3633965Sjdp	print "usage: fw_stub <firmware:name>* [-m modname] [-c outfile]";
37218822Sdim	exit 1;
38218822Sdim}
3933965Sjdp
4033965Sjdp#   These are just for convenience ...
4133965Sjdpfunction printc(s)
4233965Sjdp{
43218822Sdim	if (opt_c)
44218822Sdim		print s > ctmpfilename;
45218822Sdim	else
46218822Sdim		print s > "/dev/stdout";
47218822Sdim}
4833965Sjdp
4933965SjdpBEGIN {
5033965Sjdp
5133965Sjdp#
5233965Sjdp#   Process the command line.
5333965Sjdp#
5433965Sjdp
5533965Sjdpnum_files = 0;
5633965Sjdp
5733965Sjdpfor (i = 1; i < ARGC; i++) {
5833965Sjdp	if (ARGV[i] ~ /^-/) {
5933965Sjdp		#
6089857Sobrien		#   awk doesn't have getopt(), so we have to do it ourselves.
61130561Sobrien		#   This is a bit clumsy, but it works.
62130561Sobrien		#
63130561Sobrien		for (j = 2; j <= length(ARGV[i]); j++) {
64130561Sobrien			o = substr(ARGV[i], j, 1);
65130561Sobrien			if (o == "c") {
66130561Sobrien				if (length(ARGV[i]) > j) {
6733965Sjdp					opt_c = substr(ARGV[i], j + 1);
6833965Sjdp					break;
6933965Sjdp				}
70130561Sobrien				else {
71130561Sobrien					if (++i < ARGC)
72130561Sobrien						opt_c = ARGV[i];
73130561Sobrien					else
74130561Sobrien						usage();
75130561Sobrien				}
76130561Sobrien			} else if (o == "m") {
77130561Sobrien				if (length(ARGV[i]) > j) {
78130561Sobrien					opt_m = substr(ARGV[i], j + 1);
79130561Sobrien					break;
80130561Sobrien				}
81130561Sobrien				else {
8289857Sobrien					if (++i < ARGC)
8333965Sjdp						opt_m = ARGV[i];
84130561Sobrien					else
8533965Sjdp						usage();
8633965Sjdp				}
8733965Sjdp			} else
8833965Sjdp				usage();
8933965Sjdp		}
9033965Sjdp	} else {
9133965Sjdp		split(ARGV[i], curr, ":");
92130561Sobrien		filenames[num_files] = curr[1];
9333965Sjdp		if (length(curr[2]) > 0)
9433965Sjdp			shortnames[num_files] = curr[2];
9533965Sjdp		else
9633965Sjdp			shortnames[num_files] = curr[2];
9733965Sjdp		if (length(curr[3]) > 0)
9833965Sjdp			versions[num_files] = int(curr[3]);
99130561Sobrien		else
10033965Sjdp			versions[num_files] = 0;
10133965Sjdp		num_files++;
10233965Sjdp	}
10333965Sjdp}
10433965Sjdp
10533965Sjdpif (!num_files || !opt_m)
10633965Sjdp	usage();
10733965Sjdp
10833965Sjdpcfilename = opt_c;
10933965Sjdpctmpfilename = cfilename ".tmp";
11033965Sjdp
11133965Sjdpprintc("#include <sys/param.h>\
11233965Sjdp#include <sys/errno.h>\
11333965Sjdp#include <sys/kernel.h>\
11433965Sjdp#include <sys/module.h>\
11533965Sjdp#include <sys/linker.h>\
11633965Sjdp#include <sys/firmware.h>\n");
11733965Sjdp
11833965Sjdpfor (file_i = 0; file_i < num_files; file_i++) {
11933965Sjdp	symb = filenames[file_i];
12033965Sjdp	# '-', '.' and '/' are converted to '_' by ld/objcopy
12133965Sjdp	gsub(/-|\.|\//, "_", symb);
12233965Sjdp	printc("extern char _binary_" symb "_start[], _binary_" symb "_end[];");
123130561Sobrien}
12433965Sjdp
12533965Sjdpprintc("\nstatic int\n"\
12633965Sjdpopt_m "_fw_modevent(module_t mod, int type, void *unused)\
12733965Sjdp{\
12833965Sjdp	struct firmware *fp;\
129130561Sobrien	switch (type) {\
13033965Sjdp	case MOD_LOAD:");
13133965Sjdp
13233965Sjdpfor (file_i = 0; file_i < num_files; file_i++) {
13333965Sjdp	short = shortnames[file_i];
13433965Sjdp	symb = filenames[file_i];
13533965Sjdp	version = versions[file_i];
13633965Sjdp	# '-', '.' and '/' are converted to '_' by ld/objcopy
13733965Sjdp	gsub(/-|\.|\//, "_", symb);
13833965Sjdp
13933965Sjdp	if (file_i == 0)
14033965Sjdp		reg = "\t\tfp = ";
14133965Sjdp	else
14233965Sjdp		reg = "\t\t(void)";
14333965Sjdp
14433965Sjdp	reg = reg "firmware_register(\"" short "\", _binary_" symb "_start , ";
14533965Sjdp	reg = reg "(size_t)(_binary_" symb "_end - _binary_" symb "_start), ";
14633965Sjdp	reg = reg version ", ";
14733965Sjdp
14833965Sjdp	if (file_i == 0)
149104834Sobrien		reg = reg "NULL);";
15033965Sjdp	else
15133965Sjdp		reg = reg "fp);";
15233965Sjdp
15333965Sjdp	printc(reg);
15433965Sjdp}
15533965Sjdp
15633965Sjdpprintc("\t\treturn (0);\
15733965Sjdp	case MOD_UNLOAD:");
15833965Sjdp
15933965Sjdpfor (file_i = 1; file_i < num_files; file_i++) {
16038889Sjdp	printc("\t\tfirmware_unregister(\"" shortnames[file_i] "\");");
161218822Sdim}
16233965Sjdp
16333965Sjdpprintc("\t\tfirmware_unregister(\"" shortnames[0] "\");");
16433965Sjdp
16533965Sjdpprintc("\t\treturn (0);\
16633965Sjdp	}\
16733965Sjdp	return (EINVAL);\
16833965Sjdp}\
16933965Sjdp\
17033965Sjdpstatic moduledata_t " opt_m "_fw_mod = {\
17133965Sjdp        \"" opt_m "_fw\",\
17233965Sjdp        " opt_m "_fw_modevent,\
17333965Sjdp        0\
17433965Sjdp};\
17533965SjdpDECLARE_MODULE(" opt_m "_fw, " opt_m "_fw_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);\
17633965SjdpMODULE_VERSION(" opt_m "_fw, 1);\
17733965SjdpMODULE_DEPEND(iwi_boot_fw, firmware, 1, 1, 1);\
178130561Sobrien");
17933965Sjdp
18033965Sjdpif (opt_c)
18133965Sjdp	if ((rc = system("mv -f " ctmpfilename " " cfilename))) {
18233965Sjdp		print "'mv -f " ctmpfilename " " cfilename "' failed: " rc \
18338889Sjdp		    > "/dev/stderr";
18438889Sjdp		exit 1;
18533965Sjdp	}
18633965Sjdp
18733965Sjdpexit 0;
18833965Sjdp
18933965Sjdp}
19033965Sjdp