ndiscvt.c revision 124060
1123475Swpaul/*
2123475Swpaul * Copyright (c) 2003
3123475Swpaul *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
4123475Swpaul *
5123475Swpaul * Redistribution and use in source and binary forms, with or without
6123475Swpaul * modification, are permitted provided that the following conditions
7123475Swpaul * are met:
8123475Swpaul * 1. Redistributions of source code must retain the above copyright
9123475Swpaul *    notice, this list of conditions and the following disclaimer.
10123475Swpaul * 2. Redistributions in binary form must reproduce the above copyright
11123475Swpaul *    notice, this list of conditions and the following disclaimer in the
12123475Swpaul *    documentation and/or other materials provided with the distribution.
13123475Swpaul * 3. All advertising materials mentioning features or use of this software
14123475Swpaul *    must display the following acknowledgement:
15123475Swpaul *	This product includes software developed by Bill Paul.
16123475Swpaul * 4. Neither the name of the author nor the names of any co-contributors
17123475Swpaul *    may be used to endorse or promote products derived from this software
18123475Swpaul *    without specific prior written permission.
19123475Swpaul *
20123475Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21123475Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22123475Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23123475Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24123475Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25123475Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26123475Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27123475Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28123475Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29123475Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30123475Swpaul * THE POSSIBILITY OF SUCH DAMAGE.
31123475Swpaul */
32123475Swpaul
33123475Swpaul#include <sys/cdefs.h>
34123475Swpaul__FBSDID("$FreeBSD: head/usr.sbin/ndiscvt/ndiscvt.c 124060 2004-01-02 04:31:06Z wpaul $");
35123475Swpaul
36123475Swpaul#include <sys/types.h>
37123475Swpaul#include <sys/queue.h>
38124060Swpaul#include <sys/socket.h>
39124060Swpaul#include <net/if.h>
40123475Swpaul#include <stdlib.h>
41123475Swpaul#include <unistd.h>
42123475Swpaul#include <stdio.h>
43123475Swpaul#include <errno.h>
44123475Swpaul#include <string.h>
45123475Swpaul#include <err.h>
46123475Swpaul
47123475Swpaul#include <compat/ndis/pe_var.h>
48123475Swpaul
49123475Swpaul#include "inf.h"
50123475Swpaul
51123475Swpaulstatic int insert_padding(void **, int *);
52123475Swpaulextern const char *__progname;
53123475Swpaul
54123475Swpaul/*
55123475Swpaul * Sections in object code files can be sparse. That is, the
56123475Swpaul * section may occupy more space in memory that it does when
57123475Swpaul * stored in a disk file. In Windows PE files, each section header
58123475Swpaul * has a 'virtual size' and 'raw data size' field. The latter
59123475Swpaul * specifies the amount of section data actually stored in the
60123475Swpaul * disk file, and the former describes how much space the section
61123475Swpaul * should actually occupy in memory. If the vsize is larger than
62123475Swpaul * the rsize, we need to allocate some extra storage and fill
63123475Swpaul * it with zeros. (Think BSS.)
64123475Swpaul *
65123475Swpaul * The typical method of loading an executable file involves
66123475Swpaul * reading each segment into memory using the vaddr/vsize from
67123475Swpaul * each section header. We try to make a small optimization however
68123475Swpaul * and only pad/move segments when it's absolutely necessary, i.e.
69123475Swpaul * if the vsize is larger than the rsize. This conserves a little
70123475Swpaul * bit of memory, at the cost of having to fixup some of the values
71123475Swpaul * in the section headers.
72123475Swpaul */
73123475Swpaul
74123475Swpaul#define ROUND_UP(x, y)	\
75123475Swpaul	(((x) + (y)) - ((x) % (y)))
76123475Swpaul
77123475Swpaul#define SET_HDRS(x)	\
78123475Swpaul	dos_hdr = (image_dos_header *)x;				\
79123475Swpaul	nt_hdr = (image_nt_header *)(x + dos_hdr->idh_lfanew);		\
80123475Swpaul	sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +	\
81123475Swpaul	    sizeof(image_nt_header));
82123475Swpaul
83123475Swpaulstatic
84123475Swpaulint insert_padding(imgbase, imglen)
85123475Swpaul	void			**imgbase;
86123475Swpaul	int			*imglen;
87123475Swpaul{
88123475Swpaul        image_section_header	*sect_hdr;
89123475Swpaul        image_dos_header	*dos_hdr;
90123475Swpaul        image_nt_header		*nt_hdr;
91123475Swpaul	image_optional_header	opt_hdr;
92123475Swpaul        int			i = 0, sections, curlen = 0;
93123475Swpaul	int			offaccum = 0, diff, oldraddr, oldrlen;
94123475Swpaul	uint8_t			*newimg, *tmp;
95123475Swpaul
96123475Swpaul	newimg = malloc(*imglen);
97123475Swpaul
98123475Swpaul	if (newimg == NULL)
99123475Swpaul		return(ENOMEM);
100123475Swpaul
101123475Swpaul	bcopy(*imgbase, newimg, *imglen);
102123475Swpaul	curlen = *imglen;
103123475Swpaul
104123475Swpaul	if (pe_get_optional_header((vm_offset_t)newimg, &opt_hdr))
105123475Swpaul		return(0);
106123475Swpaul
107123475Swpaul        sections = pe_numsections((vm_offset_t)newimg);
108123475Swpaul
109123475Swpaul	SET_HDRS(newimg);
110123475Swpaul
111123475Swpaul	for (i = 0; i < sections; i++) {
112123475Swpaul		/*
113123475Swpaul		 * If we have accumulated any padding offset,
114123475Swpaul		 * add it to the raw data address of this segment.
115123475Swpaul		 */
116123475Swpaul		oldraddr = sect_hdr->ish_rawdataaddr;
117123475Swpaul		oldrlen = sect_hdr->ish_rawdatasize;
118123475Swpaul		if (offaccum)
119123475Swpaul			sect_hdr->ish_rawdataaddr += offaccum;
120123475Swpaul		if (sect_hdr->ish_misc.ish_vsize >
121123475Swpaul		    sect_hdr->ish_rawdatasize) {
122123475Swpaul			diff = ROUND_UP(sect_hdr->ish_misc.ish_vsize -
123123475Swpaul			    sect_hdr->ish_rawdatasize,
124123475Swpaul			    opt_hdr.ioh_filealign);
125123475Swpaul			offaccum += ROUND_UP(diff -
126123475Swpaul			    (sect_hdr->ish_misc.ish_vsize -
127123475Swpaul			    sect_hdr->ish_rawdatasize),
128123475Swpaul			    opt_hdr.ioh_filealign);
129123475Swpaul			sect_hdr->ish_rawdatasize =
130123475Swpaul			    ROUND_UP(sect_hdr->ish_rawdatasize,
131123475Swpaul			    opt_hdr.ioh_filealign);
132123475Swpaul			tmp = realloc(newimg, *imglen + offaccum);
133123475Swpaul			if (tmp == NULL) {
134123475Swpaul				free(newimg);
135123475Swpaul				return(ENOMEM);
136123475Swpaul			}
137123475Swpaul			newimg = tmp;
138123475Swpaul			SET_HDRS(newimg);
139123475Swpaul			sect_hdr += i;
140123475Swpaul		}
141123475Swpaul		bzero(newimg + sect_hdr->ish_rawdataaddr,
142123475Swpaul		    ROUND_UP(sect_hdr->ish_misc.ish_vsize,
143123475Swpaul		    opt_hdr.ioh_filealign));
144123475Swpaul		bcopy((uint8_t *)(*imgbase) + oldraddr,
145123475Swpaul		    newimg + sect_hdr->ish_rawdataaddr, oldrlen);
146123475Swpaul		sect_hdr++;
147123475Swpaul	}
148123475Swpaul
149123475Swpaul	free(*imgbase);
150123475Swpaul
151123475Swpaul	*imgbase = newimg;
152123475Swpaul	*imglen += offaccum;
153123475Swpaul
154123475Swpaul	return(0);
155123475Swpaul}
156123475Swpaul
157123475Swpaulstatic void
158123475Swpaulusage(void)
159123475Swpaul{
160123475Swpaul	fprintf(stderr, "Usage: %s [-i <inffile>] -s <sysfile> "
161124060Swpaul	    "[-d devname] [-o outfile]\n", __progname);
162123475Swpaul	exit(1);
163123475Swpaul}
164123475Swpaul
165123475Swpaulint
166123475Swpaulmain(int argc, char *argv[])
167123475Swpaul{
168123475Swpaul	FILE		*fp, *outfp;
169123475Swpaul	void		*img;
170123475Swpaul	int		n, fsize, cnt;
171123475Swpaul	unsigned char	*ptr;
172123475Swpaul	int		i;
173123475Swpaul	char		*inffile = NULL, *sysfile = NULL, *outfile = NULL;
174124060Swpaul	char		*dname = NULL;
175123475Swpaul	int		ch;
176123475Swpaul
177124060Swpaul	while((ch = getopt(argc, argv, "i:s:o:n:")) != -1) {
178123475Swpaul		switch(ch) {
179123475Swpaul		case 'i':
180123475Swpaul			inffile = optarg;
181123475Swpaul			break;
182123475Swpaul		case 's':
183123475Swpaul			sysfile = optarg;
184123475Swpaul			break;
185123475Swpaul		case 'o':
186123475Swpaul			outfile = optarg;
187123475Swpaul			break;
188124060Swpaul		case 'n':
189124060Swpaul			dname = optarg;
190124060Swpaul			break;
191123475Swpaul		default:
192123475Swpaul			usage();
193123475Swpaul			break;
194123475Swpaul		}
195123475Swpaul	}
196123475Swpaul
197123475Swpaul	if (sysfile == NULL)
198123475Swpaul		usage();
199123475Swpaul
200123475Swpaul	/* Open the .SYS file and load it into memory */
201123475Swpaul	fp = fopen(sysfile, "r");
202123475Swpaul	if (fp == NULL)
203123475Swpaul		err(1, "opening .SYS file '%s' failed", sysfile);
204123475Swpaul	fseek (fp, 0L, SEEK_END);
205123475Swpaul	fsize = ftell (fp);
206123475Swpaul	rewind (fp);
207123475Swpaul	img = calloc(fsize, 1);
208123475Swpaul	n = fread (img, fsize, 1, fp);
209123475Swpaul
210123475Swpaul	fclose(fp);
211123475Swpaul
212123475Swpaul	if (insert_padding(&img, &fsize)) {
213123475Swpaul		fprintf(stderr, "section relocation failed\n");
214123475Swpaul		exit(1);
215123475Swpaul	}
216123475Swpaul
217123475Swpaul	if (outfile == NULL || strcmp(outfile, "-") == 0)
218123475Swpaul		outfp = stdout;
219123475Swpaul	else {
220123475Swpaul		outfp = fopen(outfile, "w");
221123475Swpaul		if (outfp == NULL)
222123475Swpaul			err(1, "opening output file '%s' failed", outfile);
223123475Swpaul	}
224123475Swpaul
225123475Swpaul	fprintf(outfp, "\n/*\n");
226123475Swpaul	fprintf(outfp, " * Generated from %s and %s (%d bytes)\n",
227124060Swpaul	    inffile == NULL ? "<notused>" : inffile, sysfile, fsize);
228123475Swpaul	fprintf(outfp, " */\n\n");
229123475Swpaul
230124060Swpaul	if (dname != NULL) {
231124060Swpaul		if (strlen(dname) > IFNAMSIZ)
232124060Swpaul			err(1, "selected device name '%s' is "
233124060Swpaul			    "too long (max chars: %d)", dname, IFNAMSIZ);
234124060Swpaul		fprintf (outfp, "#define NDIS_DEVNAME \"%s\"\n", dname);
235124060Swpaul		fprintf (outfp, "#define NDIS_MODNAME %s\n", dname);
236124060Swpaul	}
237124060Swpaul
238124060Swpaul	if (inffile == NULL) {
239123475Swpaul		fprintf (outfp, "ndis_cfg ndis_regvals[] = {\n");
240124060Swpaul        	fprintf (outfp, "\t{ NULL, NULL, { 0 }, 0 }\n");
241123475Swpaul
242123475Swpaul		fprintf (outfp, "};\n\n");
243123475Swpaul	} else {
244123475Swpaul		fp = fopen(inffile, "r");
245123475Swpaul		if (fp == NULL)
246123475Swpaul			err(1, "opening .INF file '%s' failed", inffile);
247123475Swpaul
248123475Swpaul
249123475Swpaul		inf_parse(fp, outfp);
250123475Swpaul		fclose(fp);
251123475Swpaul	}
252123475Swpaul
253123653Swpaul	fprintf(outfp, "\n\nextern unsigned char drv_data[];\n\n");
254123475Swpaul
255123653Swpaul	fprintf(outfp, "__asm__(\".data\");\n");
256123653Swpaul	fprintf(outfp, "__asm__(\".type   drv_data, @object\");\n");
257123653Swpaul	fprintf(outfp, "__asm__(\".size   drv_data, %d\");\n", fsize);
258123653Swpaul	fprintf(outfp, "__asm__(\"drv_data:\");\n");
259123653Swpaul
260123475Swpaul	ptr = img;
261123475Swpaul	cnt = 0;
262123475Swpaul	while(cnt < fsize) {
263123653Swpaul		fprintf (outfp, "__asm__(\".byte ");
264123653Swpaul		for (i = 0; i < 10; i++) {
265123475Swpaul			cnt++;
266123475Swpaul			if (cnt == fsize) {
267123653Swpaul				fprintf(outfp, "0x%.2X\");\n", ptr[i]);
268123475Swpaul				goto done;
269123653Swpaul			} else {
270123653Swpaul				if (i == 9)
271123653Swpaul					fprintf(outfp, "0x%.2X\");\n", ptr[i]);
272123653Swpaul				else
273123653Swpaul					fprintf(outfp, "0x%.2X, ", ptr[i]);
274123653Swpaul			}
275123475Swpaul		}
276123653Swpaul		ptr += 10;
277123475Swpaul	}
278123475Swpaul
279123475Swpauldone:
280123475Swpaul
281123475Swpaul	if (fp != NULL)
282123475Swpaul		fclose(fp);
283123475Swpaul	fclose(outfp);
284123475Swpaul	free(img);
285123475Swpaul	exit(0);
286123475Swpaul}
287