ndiscvt.c revision 124060
1101100Ssos/*
2101100Ssos * Copyright (c) 2003
3101100Ssos *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
4101100Ssos *
5101100Ssos * Redistribution and use in source and binary forms, with or without
6101100Ssos * modification, are permitted provided that the following conditions
7101100Ssos * are met:
8101100Ssos * 1. Redistributions of source code must retain the above copyright
9101100Ssos *    notice, this list of conditions and the following disclaimer.
10101100Ssos * 2. Redistributions in binary form must reproduce the above copyright
11101100Ssos *    notice, this list of conditions and the following disclaimer in the
12101100Ssos *    documentation and/or other materials provided with the distribution.
13101100Ssos * 3. All advertising materials mentioning features or use of this software
14101100Ssos *    must display the following acknowledgement:
15101100Ssos *	This product includes software developed by Bill Paul.
16101100Ssos * 4. Neither the name of the author nor the names of any co-contributors
17101100Ssos *    may be used to endorse or promote products derived from this software
18101100Ssos *    without specific prior written permission.
19101100Ssos *
20101100Ssos * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21101100Ssos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22101100Ssos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23101100Ssos * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24101100Ssos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25101100Ssos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26101100Ssos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27101100Ssos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28101100Ssos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29101100Ssos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30101100Ssos * THE POSSIBILITY OF SUCH DAMAGE.
31101100Ssos */
32101100Ssos
33101100Ssos#include <sys/cdefs.h>
34101100Ssos__FBSDID("$FreeBSD: head/usr.sbin/ndiscvt/ndiscvt.c 124060 2004-01-02 04:31:06Z wpaul $");
35101100Ssos
36101100Ssos#include <sys/types.h>
37101100Ssos#include <sys/queue.h>
38101100Ssos#include <sys/socket.h>
39101100Ssos#include <net/if.h>
40101100Ssos#include <stdlib.h>
41101100Ssos#include <unistd.h>
42101100Ssos#include <stdio.h>
43101100Ssos#include <errno.h>
44101100Ssos#include <string.h>
45101100Ssos#include <err.h>
46101100Ssos
47101100Ssos#include <compat/ndis/pe_var.h>
48101100Ssos
49101100Ssos#include "inf.h"
50101100Ssos
51101100Ssosstatic int insert_padding(void **, int *);
52101100Ssosextern const char *__progname;
53101100Ssos
54101100Ssos/*
55101100Ssos * Sections in object code files can be sparse. That is, the
56101100Ssos * section may occupy more space in memory that it does when
57101100Ssos * stored in a disk file. In Windows PE files, each section header
58101100Ssos * has a 'virtual size' and 'raw data size' field. The latter
59101100Ssos * specifies the amount of section data actually stored in the
60101100Ssos * disk file, and the former describes how much space the section
61101100Ssos * should actually occupy in memory. If the vsize is larger than
62101100Ssos * the rsize, we need to allocate some extra storage and fill
63101100Ssos * it with zeros. (Think BSS.)
64101100Ssos *
65101100Ssos * The typical method of loading an executable file involves
66101100Ssos * reading each segment into memory using the vaddr/vsize from
67101100Ssos * each section header. We try to make a small optimization however
68101100Ssos * and only pad/move segments when it's absolutely necessary, i.e.
69101100Ssos * if the vsize is larger than the rsize. This conserves a little
70101100Ssos * bit of memory, at the cost of having to fixup some of the values
71101100Ssos * in the section headers.
72101100Ssos */
73101100Ssos
74101100Ssos#define ROUND_UP(x, y)	\
75101100Ssos	(((x) + (y)) - ((x) % (y)))
76101100Ssos
77101100Ssos#define SET_HDRS(x)	\
78101100Ssos	dos_hdr = (image_dos_header *)x;				\
79108533Sschweikh	nt_hdr = (image_nt_header *)(x + dos_hdr->idh_lfanew);		\
80101100Ssos	sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +	\
81101100Ssos	    sizeof(image_nt_header));
82101100Ssos
83101100Ssosstatic
84101100Ssosint insert_padding(imgbase, imglen)
85101100Ssos	void			**imgbase;
86101100Ssos	int			*imglen;
87101100Ssos{
88101100Ssos        image_section_header	*sect_hdr;
89101100Ssos        image_dos_header	*dos_hdr;
90101100Ssos        image_nt_header		*nt_hdr;
91101100Ssos	image_optional_header	opt_hdr;
92101100Ssos        int			i = 0, sections, curlen = 0;
93101100Ssos	int			offaccum = 0, diff, oldraddr, oldrlen;
94101100Ssos	uint8_t			*newimg, *tmp;
95101100Ssos
96101100Ssos	newimg = malloc(*imglen);
97101100Ssos
98101100Ssos	if (newimg == NULL)
99101100Ssos		return(ENOMEM);
100101100Ssos
101101100Ssos	bcopy(*imgbase, newimg, *imglen);
102101100Ssos	curlen = *imglen;
103101100Ssos
104101100Ssos	if (pe_get_optional_header((vm_offset_t)newimg, &opt_hdr))
105101100Ssos		return(0);
106101100Ssos
107101100Ssos        sections = pe_numsections((vm_offset_t)newimg);
108101100Ssos
109101100Ssos	SET_HDRS(newimg);
110101100Ssos
111101100Ssos	for (i = 0; i < sections; i++) {
112101100Ssos		/*
113101100Ssos		 * If we have accumulated any padding offset,
114101100Ssos		 * add it to the raw data address of this segment.
115101100Ssos		 */
116101100Ssos		oldraddr = sect_hdr->ish_rawdataaddr;
117101100Ssos		oldrlen = sect_hdr->ish_rawdatasize;
118101100Ssos		if (offaccum)
119101100Ssos			sect_hdr->ish_rawdataaddr += offaccum;
120101100Ssos		if (sect_hdr->ish_misc.ish_vsize >
121101100Ssos		    sect_hdr->ish_rawdatasize) {
122101100Ssos			diff = ROUND_UP(sect_hdr->ish_misc.ish_vsize -
123101100Ssos			    sect_hdr->ish_rawdatasize,
124101100Ssos			    opt_hdr.ioh_filealign);
125101100Ssos			offaccum += ROUND_UP(diff -
126101100Ssos			    (sect_hdr->ish_misc.ish_vsize -
127101100Ssos			    sect_hdr->ish_rawdatasize),
128101100Ssos			    opt_hdr.ioh_filealign);
129101100Ssos			sect_hdr->ish_rawdatasize =
130101100Ssos			    ROUND_UP(sect_hdr->ish_rawdatasize,
131101100Ssos			    opt_hdr.ioh_filealign);
132101100Ssos			tmp = realloc(newimg, *imglen + offaccum);
133101100Ssos			if (tmp == NULL) {
134101100Ssos				free(newimg);
135101100Ssos				return(ENOMEM);
136101100Ssos			}
137101100Ssos			newimg = tmp;
138101100Ssos			SET_HDRS(newimg);
139101100Ssos			sect_hdr += i;
140101100Ssos		}
141101100Ssos		bzero(newimg + sect_hdr->ish_rawdataaddr,
142101100Ssos		    ROUND_UP(sect_hdr->ish_misc.ish_vsize,
143101100Ssos		    opt_hdr.ioh_filealign));
144101100Ssos		bcopy((uint8_t *)(*imgbase) + oldraddr,
145101100Ssos		    newimg + sect_hdr->ish_rawdataaddr, oldrlen);
146101100Ssos		sect_hdr++;
147101100Ssos	}
148101100Ssos
149101100Ssos	free(*imgbase);
150101100Ssos
151101100Ssos	*imgbase = newimg;
152101100Ssos	*imglen += offaccum;
153101100Ssos
154101100Ssos	return(0);
155101100Ssos}
156101100Ssos
157102058Ssosstatic void
158102058Ssosusage(void)
159102058Ssos{
160102058Ssos	fprintf(stderr, "Usage: %s [-i <inffile>] -s <sysfile> "
161102058Ssos	    "[-d devname] [-o outfile]\n", __progname);
162102058Ssos	exit(1);
163102058Ssos}
164102058Ssos
165108533Sschweikhint
166102058Ssosmain(int argc, char *argv[])
167108533Sschweikh{
168102058Ssos	FILE		*fp, *outfp;
169102058Ssos	void		*img;
170102058Ssos	int		n, fsize, cnt;
171102058Ssos	unsigned char	*ptr;
172101100Ssos	int		i;
173101100Ssos	char		*inffile = NULL, *sysfile = NULL, *outfile = NULL;
174101100Ssos	char		*dname = NULL;
175102058Ssos	int		ch;
176102058Ssos
177102058Ssos	while((ch = getopt(argc, argv, "i:s:o:n:")) != -1) {
178108533Sschweikh		switch(ch) {
179102058Ssos		case 'i':
180102058Ssos			inffile = optarg;
181102058Ssos			break;
182101100Ssos		case 's':
183101100Ssos			sysfile = optarg;
184101100Ssos			break;
185101100Ssos		case 'o':
186101100Ssos			outfile = optarg;
187101100Ssos			break;
188101100Ssos		case 'n':
189101100Ssos			dname = optarg;
190102058Ssos			break;
191101100Ssos		default:
192101100Ssos			usage();
193101100Ssos			break;
194101100Ssos		}
195101100Ssos	}
196101100Ssos
197101100Ssos	if (sysfile == NULL)
198101100Ssos		usage();
199101100Ssos
200101100Ssos	/* Open the .SYS file and load it into memory */
201101100Ssos	fp = fopen(sysfile, "r");
202101100Ssos	if (fp == NULL)
203101100Ssos		err(1, "opening .SYS file '%s' failed", sysfile);
204101100Ssos	fseek (fp, 0L, SEEK_END);
205101100Ssos	fsize = ftell (fp);
206101100Ssos	rewind (fp);
207101100Ssos	img = calloc(fsize, 1);
208101100Ssos	n = fread (img, fsize, 1, fp);
209101100Ssos
210101100Ssos	fclose(fp);
211101100Ssos
212101100Ssos	if (insert_padding(&img, &fsize)) {
213102058Ssos		fprintf(stderr, "section relocation failed\n");
214101100Ssos		exit(1);
215101100Ssos	}
216101100Ssos
217101100Ssos	if (outfile == NULL || strcmp(outfile, "-") == 0)
218101100Ssos		outfp = stdout;
219101100Ssos	else {
220101100Ssos		outfp = fopen(outfile, "w");
221101100Ssos		if (outfp == NULL)
222101100Ssos			err(1, "opening output file '%s' failed", outfile);
223102058Ssos	}
224101100Ssos
225101100Ssos	fprintf(outfp, "\n/*\n");
226101100Ssos	fprintf(outfp, " * Generated from %s and %s (%d bytes)\n",
227101100Ssos	    inffile == NULL ? "<notused>" : inffile, sysfile, fsize);
228102058Ssos	fprintf(outfp, " */\n\n");
229102058Ssos
230101100Ssos	if (dname != NULL) {
231101100Ssos		if (strlen(dname) > IFNAMSIZ)
232101100Ssos			err(1, "selected device name '%s' is "
233101100Ssos			    "too long (max chars: %d)", dname, IFNAMSIZ);
234101100Ssos		fprintf (outfp, "#define NDIS_DEVNAME \"%s\"\n", dname);
235101100Ssos		fprintf (outfp, "#define NDIS_MODNAME %s\n", dname);
236101100Ssos	}
237101100Ssos
238101100Ssos	if (inffile == NULL) {
239101100Ssos		fprintf (outfp, "ndis_cfg ndis_regvals[] = {\n");
240101100Ssos        	fprintf (outfp, "\t{ NULL, NULL, { 0 }, 0 }\n");
241101100Ssos
242101100Ssos		fprintf (outfp, "};\n\n");
243101100Ssos	} else {
244101100Ssos		fp = fopen(inffile, "r");
245101100Ssos		if (fp == NULL)
246101100Ssos			err(1, "opening .INF file '%s' failed", inffile);
247101100Ssos
248101100Ssos
249101100Ssos		inf_parse(fp, outfp);
250101100Ssos		fclose(fp);
251101100Ssos	}
252101100Ssos
253101100Ssos	fprintf(outfp, "\n\nextern unsigned char drv_data[];\n\n");
254101100Ssos
255101100Ssos	fprintf(outfp, "__asm__(\".data\");\n");
256101100Ssos	fprintf(outfp, "__asm__(\".type   drv_data, @object\");\n");
257101100Ssos	fprintf(outfp, "__asm__(\".size   drv_data, %d\");\n", fsize);
258108533Sschweikh	fprintf(outfp, "__asm__(\"drv_data:\");\n");
259101100Ssos
260101100Ssos	ptr = img;
261101100Ssos	cnt = 0;
262101100Ssos	while(cnt < fsize) {
263101100Ssos		fprintf (outfp, "__asm__(\".byte ");
264101100Ssos		for (i = 0; i < 10; i++) {
265101100Ssos			cnt++;
266101100Ssos			if (cnt == fsize) {
267101100Ssos				fprintf(outfp, "0x%.2X\");\n", ptr[i]);
268101100Ssos				goto done;
269101100Ssos			} else {
270101100Ssos				if (i == 9)
271101100Ssos					fprintf(outfp, "0x%.2X\");\n", ptr[i]);
272101100Ssos				else
273101100Ssos					fprintf(outfp, "0x%.2X, ", ptr[i]);
274101100Ssos			}
275101100Ssos		}
276101100Ssos		ptr += 10;
277101100Ssos	}
278101100Ssos
279101100Ssosdone:
280101100Ssos
281101100Ssos	if (fp != NULL)
282101100Ssos		fclose(fp);
283101100Ssos	fclose(outfp);
284102058Ssos	free(img);
285101100Ssos	exit(0);
286101100Ssos}
287101100Ssos