MFC:
[dragonfly.git] / usr.sbin / ndiscvt / ndiscvt.c
blob3c0953634d50fd9b02343420565ebff0d3219299
1 /*
2 * Copyright (c) 2003
3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
32 * $DragonFly: src/usr.sbin/ndiscvt/ndiscvt.c,v 1.2 2005/12/05 02:40:27 swildner Exp $
35 #include <sys/types.h>
36 #include <sys/queue.h>
37 #include <sys/socket.h>
38 #include <net/if.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <stdio.h>
42 #include <errno.h>
43 #include <string.h>
44 #include <err.h>
46 #include <emulation/ndis/regcall.h>
47 #include <emulation/ndis/pe_var.h>
49 #include "inf.h"
51 static int insert_padding(void **, int *);
52 extern const char *__progname;
55 * Sections in object code files can be sparse. That is, the
56 * section may occupy more space in memory that it does when
57 * stored in a disk file. In Windows PE files, each section header
58 * has a 'virtual size' and 'raw data size' field. The latter
59 * specifies the amount of section data actually stored in the
60 * disk file, and the former describes how much space the section
61 * should actually occupy in memory. If the vsize is larger than
62 * the rsize, we need to allocate some extra storage and fill
63 * it with zeros. (Think BSS.)
65 * The typical method of loading an executable file involves
66 * reading each segment into memory using the vaddr/vsize from
67 * each section header. We try to make a small optimization however
68 * and only pad/move segments when it's absolutely necessary, i.e.
69 * if the vsize is larger than the rsize. This conserves a little
70 * bit of memory, at the cost of having to fixup some of the values
71 * in the section headers.
74 #define ROUND_UP(x, y) \
75 (((x) + (y)) - ((x) % (y)))
77 #define SET_HDRS(x) \
78 dos_hdr = (image_dos_header *)x; \
79 nt_hdr = (image_nt_header *)(x + dos_hdr->idh_lfanew); \
80 sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr + \
81 sizeof(image_nt_header));
83 static int
84 insert_padding(void **imgbase, int *imglen)
86 image_section_header *sect_hdr;
87 image_dos_header *dos_hdr;
88 image_nt_header *nt_hdr;
89 image_optional_header opt_hdr;
90 int i = 0, sections, curlen = 0;
91 int offaccum = 0, diff, oldraddr, oldrlen;
92 uint8_t *newimg, *tmp;
94 newimg = malloc(*imglen);
96 if (newimg == NULL)
97 return(ENOMEM);
99 bcopy(*imgbase, newimg, *imglen);
100 curlen = *imglen;
102 if (pe_get_optional_header((vm_offset_t)newimg, &opt_hdr))
103 return(0);
105 sections = pe_numsections((vm_offset_t)newimg);
107 SET_HDRS(newimg);
109 for (i = 0; i < sections; i++) {
111 * If we have accumulated any padding offset,
112 * add it to the raw data address of this segment.
114 oldraddr = sect_hdr->ish_rawdataaddr;
115 oldrlen = sect_hdr->ish_rawdatasize;
116 if (offaccum)
117 sect_hdr->ish_rawdataaddr += offaccum;
118 if (sect_hdr->ish_misc.ish_vsize >
119 sect_hdr->ish_rawdatasize) {
120 diff = ROUND_UP(sect_hdr->ish_misc.ish_vsize -
121 sect_hdr->ish_rawdatasize,
122 opt_hdr.ioh_filealign);
123 offaccum += ROUND_UP(diff -
124 (sect_hdr->ish_misc.ish_vsize -
125 sect_hdr->ish_rawdatasize),
126 opt_hdr.ioh_filealign);
127 sect_hdr->ish_rawdatasize =
128 ROUND_UP(sect_hdr->ish_rawdatasize,
129 opt_hdr.ioh_filealign);
130 tmp = realloc(newimg, *imglen + offaccum);
131 if (tmp == NULL) {
132 free(newimg);
133 return(ENOMEM);
135 newimg = tmp;
136 SET_HDRS(newimg);
137 sect_hdr += i;
139 bzero(newimg + sect_hdr->ish_rawdataaddr,
140 ROUND_UP(sect_hdr->ish_misc.ish_vsize,
141 opt_hdr.ioh_filealign));
142 bcopy((uint8_t *)(*imgbase) + oldraddr,
143 newimg + sect_hdr->ish_rawdataaddr, oldrlen);
144 sect_hdr++;
147 free(*imgbase);
149 *imgbase = newimg;
150 *imglen += offaccum;
152 return(0);
155 static void
156 usage(void)
158 fprintf(stderr, "Usage: %s [-i <inffile>] -s <sysfile> "
159 "[-n devname] [-o outfile]\n", __progname);
160 exit(1);
164 main(int argc, char *argv[])
166 FILE *fp, *outfp;
167 void *img;
168 int n, fsize, cnt;
169 unsigned char *ptr;
170 int i;
171 char *inffile = NULL, *sysfile = NULL, *outfile = NULL;
172 char *dname = NULL;
173 int ch;
175 while((ch = getopt(argc, argv, "i:s:o:n:")) != -1) {
176 switch(ch) {
177 case 'i':
178 inffile = optarg;
179 break;
180 case 's':
181 sysfile = optarg;
182 break;
183 case 'o':
184 outfile = optarg;
185 break;
186 case 'n':
187 dname = optarg;
188 break;
189 default:
190 usage();
191 break;
195 if (sysfile == NULL)
196 usage();
198 /* Open the .SYS file and load it into memory */
199 fp = fopen(sysfile, "r");
200 if (fp == NULL)
201 err(1, "opening .SYS file '%s' failed", sysfile);
202 fseek (fp, 0L, SEEK_END);
203 fsize = ftell (fp);
204 rewind (fp);
205 img = calloc(fsize, 1);
206 n = fread (img, fsize, 1, fp);
208 fclose(fp);
210 if (insert_padding(&img, &fsize)) {
211 fprintf(stderr, "section relocation failed\n");
212 exit(1);
215 if (outfile == NULL || strcmp(outfile, "-") == 0)
216 outfp = stdout;
217 else {
218 outfp = fopen(outfile, "w");
219 if (outfp == NULL)
220 err(1, "opening output file '%s' failed", outfile);
223 fprintf(outfp, "\n/*\n");
224 fprintf(outfp, " * Generated from %s and %s (%d bytes)\n",
225 inffile == NULL ? "<notused>" : inffile, sysfile, fsize);
226 fprintf(outfp, " */\n\n");
228 if (dname != NULL) {
229 if (strlen(dname) > IFNAMSIZ)
230 err(1, "selected device name '%s' is "
231 "too long (max chars: %d)", dname, IFNAMSIZ);
232 fprintf (outfp, "#define NDIS_DEVNAME \"%s\"\n", dname);
233 fprintf (outfp, "#define NDIS_MODNAME %s\n\n", dname);
236 if (inffile == NULL) {
237 fprintf (outfp, "#ifdef NDIS_REGVALS\n");
238 fprintf (outfp, "ndis_cfg ndis_regvals[] = {\n");
239 fprintf (outfp, "\t{ NULL, NULL, { 0 }, 0 }\n");
240 fprintf (outfp, "#endif /* NDIS_REGVALS */\n");
242 fprintf (outfp, "};\n\n");
243 } else {
244 fp = fopen(inffile, "r");
245 if (fp == NULL)
246 err(1, "opening .INF file '%s' failed", inffile);
249 inf_parse(fp, outfp);
250 fclose(fp);
253 fprintf(outfp, "\n#ifdef NDIS_IMAGE\n");
254 fprintf(outfp, "\nextern unsigned char drv_data[];\n\n");
256 fprintf(outfp, "__asm__(\".data\");\n");
257 fprintf(outfp, "__asm__(\".type drv_data, @object\");\n");
258 fprintf(outfp, "__asm__(\".size drv_data, %d\");\n", fsize);
259 fprintf(outfp, "__asm__(\"drv_data:\");\n");
261 ptr = img;
262 cnt = 0;
263 while(cnt < fsize) {
264 fprintf (outfp, "__asm__(\".byte ");
265 for (i = 0; i < 10; i++) {
266 cnt++;
267 if (cnt == fsize) {
268 fprintf(outfp, "0x%.2X\");\n", ptr[i]);
269 goto done;
270 } else {
271 if (i == 9)
272 fprintf(outfp, "0x%.2X\");\n", ptr[i]);
273 else
274 fprintf(outfp, "0x%.2X, ", ptr[i]);
277 ptr += 10;
280 done:
282 fprintf(outfp, "#endif /* NDIS_IMAGE */\n");
283 if (fp != NULL)
284 fclose(fp);
285 fclose(outfp);
286 free(img);
287 exit(0);