fw_stub.awk revision 154974
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 154974 2006-01-29 02:52:42Z mlaier $
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{\
128154974Smlaier	struct firmware *fp;\
129154974Smlaier	switch (type) {\
130154974Smlaier	case MOD_LOAD:");
131154974Smlaier
132154974Smlaierfor (file_i = 0; file_i < num_files; file_i++) {
133154974Smlaier	short = shortnames[file_i];
134154974Smlaier	symb = filenames[file_i];
135154974Smlaier	version = versions[file_i];
136154974Smlaier	# '-', '.' and '/' are converted to '_' by ld/objcopy
137154974Smlaier	gsub(/-|\.|\//, "_", symb);
138154974Smlaier
139154974Smlaier	if (file_i == 0)
140154974Smlaier		reg = "\t\tfp = ";
141154974Smlaier	else
142154974Smlaier		reg = "\t\t(void)";
143154974Smlaier
144154974Smlaier	reg = reg "firmware_register(\"" short "\", _binary_" symb "_start , ";
145154974Smlaier	reg = reg "(size_t)(_binary_" symb "_end - _binary_" symb "_start), ";
146154974Smlaier	reg = reg version ", ";
147154974Smlaier
148154974Smlaier	if (file_i == 0)
149154974Smlaier		reg = reg "NULL);";
150154974Smlaier	else
151154974Smlaier		reg = reg "fp);";
152154974Smlaier
153154974Smlaier	printc(reg);
154154974Smlaier}
155154974Smlaier
156154974Smlaierprintc("\t\treturn (0);\
157154974Smlaier	case MOD_UNLOAD:");
158154974Smlaier
159154974Smlaierfor (file_i = 1; file_i < num_files; file_i++) {
160154974Smlaier	printc("\t\tfirmware_unregister(\"" shortnames[file_i] "\");");
161154974Smlaier}
162154974Smlaier
163154974Smlaierprintc("\t\tfirmware_unregister(\"" shortnames[0] "\");");
164154974Smlaier
165154974Smlaierprintc("\t\treturn (0);\
166154974Smlaier	}\
167154974Smlaier	return (EINVAL);\
168154974Smlaier}\
169154974Smlaier\
170154974Smlaierstatic moduledata_t " opt_m "_fw_mod = {\
171154974Smlaier        \"" opt_m "_fw\",\
172154974Smlaier        " opt_m "_fw_modevent,\
173154974Smlaier        0\
174154974Smlaier};\
175154974SmlaierDECLARE_MODULE(" opt_m "_fw, " opt_m "_fw_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);\
176154974SmlaierMODULE_VERSION(" opt_m "_fw, 1);\
177154974SmlaierMODULE_DEPEND(iwi_boot_fw, firmware, 1, 1, 1);\
178154974Smlaier");
179154974Smlaier
180154974Smlaierif (opt_c)
181154974Smlaier	if ((rc = system("mv -f " ctmpfilename " " cfilename))) {
182154974Smlaier		print "'mv -f " ctmpfilename " " cfilename "' failed: " rc \
183154974Smlaier		    > "/dev/stderr";
184154974Smlaier		exit 1;
185154974Smlaier	}
186154974Smlaier
187154974Smlaierexit 0;
188154974Smlaier
189154974Smlaier}
190