fw_stub.awk revision 166756
1154974Smlaier#!/usr/bin/awk -f
2154974Smlaier
3154974Smlaier#-
4154974Smlaier# Copyright (c) 2006 Max Laier.
5154974Smlaier# All rights reserved.
6154974Smlaier#
7154974Smlaier# Redistribution and use in source and binary forms, with or without
8154974Smlaier# modification, are permitted provided that the following conditions
9154974Smlaier# are met:
10154974Smlaier# 1. Redistributions of source code must retain the above copyright
11154974Smlaier#    notice, this list of conditions and the following disclaimer.
12154974Smlaier# 2. Redistributions in binary form must reproduce the above copyright
13154974Smlaier#    notice, this list of conditions and the following disclaimer in the
14154974Smlaier#    documentation and/or other materials provided with the distribution.
15154974Smlaier#
16154974Smlaier# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS'' AND
17154974Smlaier# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18154974Smlaier# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19154974Smlaier# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20154974Smlaier# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21154974Smlaier# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22154974Smlaier# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23154974Smlaier# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24154974Smlaier# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25154974Smlaier# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26154974Smlaier# SUCH DAMAGE.
27154974Smlaier#
28154974Smlaier# $FreeBSD: head/sys/tools/fw_stub.awk 166756 2007-02-15 17:21:31Z luigi $
29154974Smlaier
30154974Smlaier#
31154974Smlaier# Script to generate module .c file from a list of firmware images
32154974Smlaier#
33154974Smlaier
34154974Smlaierfunction usage ()
35154974Smlaier{
36154974Smlaier	print "usage: fw_stub <firmware:name>* [-m modname] [-c outfile]";
37154974Smlaier	exit 1;
38154974Smlaier}
39154974Smlaier
40154974Smlaier#   These are just for convenience ...
41154974Smlaierfunction printc(s)
42154974Smlaier{
43154974Smlaier	if (opt_c)
44154974Smlaier		print s > ctmpfilename;
45154974Smlaier	else
46154974Smlaier		print s > "/dev/stdout";
47154974Smlaier}
48154974Smlaier
49154974SmlaierBEGIN {
50154974Smlaier
51154974Smlaier#
52154974Smlaier#   Process the command line.
53154974Smlaier#
54154974Smlaier
55154974Smlaiernum_files = 0;
56154974Smlaier
57154974Smlaierfor (i = 1; i < ARGC; i++) {
58154974Smlaier	if (ARGV[i] ~ /^-/) {
59154974Smlaier		#
60154974Smlaier		#   awk doesn't have getopt(), so we have to do it ourselves.
61154974Smlaier		#   This is a bit clumsy, but it works.
62154974Smlaier		#
63154974Smlaier		for (j = 2; j <= length(ARGV[i]); j++) {
64154974Smlaier			o = substr(ARGV[i], j, 1);
65154974Smlaier			if (o == "c") {
66154974Smlaier				if (length(ARGV[i]) > j) {
67154974Smlaier					opt_c = substr(ARGV[i], j + 1);
68154974Smlaier					break;
69154974Smlaier				}
70154974Smlaier				else {
71154974Smlaier					if (++i < ARGC)
72154974Smlaier						opt_c = ARGV[i];
73154974Smlaier					else
74154974Smlaier						usage();
75154974Smlaier				}
76154974Smlaier			} else if (o == "m") {
77154974Smlaier				if (length(ARGV[i]) > j) {
78154974Smlaier					opt_m = substr(ARGV[i], j + 1);
79154974Smlaier					break;
80154974Smlaier				}
81154974Smlaier				else {
82154974Smlaier					if (++i < ARGC)
83154974Smlaier						opt_m = ARGV[i];
84154974Smlaier					else
85154974Smlaier						usage();
86154974Smlaier				}
87154974Smlaier			} else
88154974Smlaier				usage();
89154974Smlaier		}
90154974Smlaier	} else {
91154974Smlaier		split(ARGV[i], curr, ":");
92154974Smlaier		filenames[num_files] = curr[1];
93154974Smlaier		if (length(curr[2]) > 0)
94154974Smlaier			shortnames[num_files] = curr[2];
95154974Smlaier		else
96154974Smlaier			shortnames[num_files] = curr[2];
97154974Smlaier		if (length(curr[3]) > 0)
98154974Smlaier			versions[num_files] = int(curr[3]);
99154974Smlaier		else
100154974Smlaier			versions[num_files] = 0;
101154974Smlaier		num_files++;
102154974Smlaier	}
103154974Smlaier}
104154974Smlaier
105154974Smlaierif (!num_files || !opt_m)
106154974Smlaier	usage();
107154974Smlaier
108154974Smlaiercfilename = opt_c;
109154974Smlaierctmpfilename = cfilename ".tmp";
110154974Smlaier
111154974Smlaierprintc("#include <sys/param.h>\
112154974Smlaier#include <sys/errno.h>\
113154974Smlaier#include <sys/kernel.h>\
114154974Smlaier#include <sys/module.h>\
115154974Smlaier#include <sys/linker.h>\
116154974Smlaier#include <sys/firmware.h>\n");
117154974Smlaier
118154974Smlaierfor (file_i = 0; file_i < num_files; file_i++) {
119154974Smlaier	symb = filenames[file_i];
120154974Smlaier	# '-', '.' and '/' are converted to '_' by ld/objcopy
121154974Smlaier	gsub(/-|\.|\//, "_", symb);
122154974Smlaier	printc("extern char _binary_" symb "_start[], _binary_" symb "_end[];");
123154974Smlaier}
124154974Smlaier
125154974Smlaierprintc("\nstatic int\n"\
126154974Smlaieropt_m "_fw_modevent(module_t mod, int type, void *unused)\
127154974Smlaier{\
128166756Sluigi	const struct firmware *fp, *parent;\
129159670Sjhb	int error;\
130154974Smlaier	switch (type) {\
131154974Smlaier	case MOD_LOAD:");
132154974Smlaier
133154974Smlaierfor (file_i = 0; file_i < num_files; file_i++) {
134154974Smlaier	short = shortnames[file_i];
135154974Smlaier	symb = filenames[file_i];
136154974Smlaier	version = versions[file_i];
137154974Smlaier	# '-', '.' and '/' are converted to '_' by ld/objcopy
138154974Smlaier	gsub(/-|\.|\//, "_", symb);
139154974Smlaier
140159670Sjhb	reg = "\t\tfp = ";
141154974Smlaier	reg = reg "firmware_register(\"" short "\", _binary_" symb "_start , ";
142154974Smlaier	reg = reg "(size_t)(_binary_" symb "_end - _binary_" symb "_start), ";
143154974Smlaier	reg = reg version ", ";
144154974Smlaier
145154974Smlaier	if (file_i == 0)
146154974Smlaier		reg = reg "NULL);";
147154974Smlaier	else
148159670Sjhb		reg = reg "parent);";
149154974Smlaier
150154974Smlaier	printc(reg);
151159670Sjhb
152159670Sjhb	printc("\t\tif (fp == NULL)");
153159670Sjhb	printc("\t\t\tgoto fail_" file_i ";");
154159670Sjhb	if (file_i == 0)
155159670Sjhb		printc("\t\tparent = fp;");
156154974Smlaier}
157154974Smlaier
158159670Sjhbprintc("\t\treturn (0);");
159154974Smlaier
160159670Sjhbfor (file_i = num_files - 1; file_i > 0; file_i--) {
161159670Sjhb	printc("\tfail_" file_i ":")
162159670Sjhb	printc("\t\t(void)firmware_unregister(\"" shortnames[file_i - 1] "\");");
163159670Sjhb}
164159670Sjhb
165159670Sjhbprintc("\tfail_0:");
166159670Sjhbprintc("\t\treturn (ENXIO);");
167159670Sjhb
168159670Sjhbprintc("\tcase MOD_UNLOAD:");
169159670Sjhb
170154974Smlaierfor (file_i = 1; file_i < num_files; file_i++) {
171159670Sjhb	printc("\t\terror = firmware_unregister(\"" shortnames[file_i] "\");");
172159670Sjhb	printc("\t\tif (error)");
173159670Sjhb	printc("\t\t\treturn (error);");
174154974Smlaier}
175154974Smlaier
176159670Sjhbprintc("\t\terror = firmware_unregister(\"" shortnames[0] "\");");
177154974Smlaier
178159670Sjhbprintc("\t\treturn (error);\
179154974Smlaier	}\
180154974Smlaier	return (EINVAL);\
181154974Smlaier}\
182154974Smlaier\
183154974Smlaierstatic moduledata_t " opt_m "_fw_mod = {\
184154974Smlaier        \"" opt_m "_fw\",\
185154974Smlaier        " opt_m "_fw_modevent,\
186154974Smlaier        0\
187154974Smlaier};\
188154974SmlaierDECLARE_MODULE(" opt_m "_fw, " opt_m "_fw_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);\
189154974SmlaierMODULE_VERSION(" opt_m "_fw, 1);\
190155055SmlaierMODULE_DEPEND(" opt_m "_fw, firmware, 1, 1, 1);\
191154974Smlaier");
192154974Smlaier
193154974Smlaierif (opt_c)
194154974Smlaier	if ((rc = system("mv -f " ctmpfilename " " cfilename))) {
195154974Smlaier		print "'mv -f " ctmpfilename " " cfilename "' failed: " rc \
196154974Smlaier		    > "/dev/stderr";
197154974Smlaier		exit 1;
198154974Smlaier	}
199154974Smlaier
200154974Smlaierexit 0;
201154974Smlaier
202154974Smlaier}
203