Don't use .Xo/.Xc. Fix date format.
[netbsd-mini2440.git] / usr.sbin / ndiscvt / ndiscvt.c
blob4011fb62b66fce1e9373780e239601547d64cd31
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.
33 #include <sys/cdefs.h>
34 #ifdef __FreeBSD__
35 __FBSDID("$FreeBSD: src/usr.sbin/ndiscvt/ndiscvt.c,v 1.9.2.2 2005/02/23 16:31:47 wpaul Exp $");
36 #endif
37 #ifdef __NetBSD__
38 __RCSID("$NetBSD: ndiscvt.c,v 1.8 2006/05/26 11:45:31 jnemeth Exp $");
39 #endif
42 #include <sys/types.h>
43 #ifdef __NetBSD__
44 #include <sys/stdint.h>
45 #endif
46 #include <sys/queue.h>
47 #include <sys/socket.h>
48 #include <sys/lock.h>
49 #include <net/if.h>
50 #include <stdlib.h>
51 #include <unistd.h>
52 #include <stdio.h>
53 #include <errno.h>
54 #include <string.h>
55 #include <libgen.h>
56 #include <err.h>
57 #include <ctype.h>
59 #include <compat/ndis/pe_var.h>
61 #include "inf.h"
63 static int insert_padding(void **, int *);
64 extern const char *__progname;
67 * Sections within Windows PE files are defined using virtual
68 * and physical address offsets and virtual and physical sizes.
69 * The physical values define how the section data is stored in
70 * the executable file while the virtual values describe how the
71 * sections will look once loaded into memory. It happens that
72 * the linker in the Microsoft(r) DDK will tend to generate
73 * binaries where the virtual and physical values are identical,
74 * which means in most cases we can just transfer the file
75 * directly to memory without any fixups. This is not always
76 * the case though, so we have to be prepared to handle files
77 * where the in-memory section layout differs from the disk file
78 * section layout.
80 * There are two kinds of variations that can occur: the relative
81 * virtual address of the section might be different from the
82 * physical file offset, and the virtual section size might be
83 * different from the physical size (for example, the physical
84 * size of the .data section might be 1024 bytes, but the virtual
85 * size might be 1384 bytes, indicating that the data section should
86 * actually use up 1384 bytes in RAM and be padded with zeros). What we
87 * do is read the original file into memory and then make an in-memory
88 * copy with all of the sections relocated, re-sized and zero padded
89 * according to the virtual values specified in the section headers.
90 * We then emit the fixed up image file for use by the if_ndis driver.
91 * This way, we don't have to do the fixups inside the kernel.
94 #define ROUND_DOWN(n, align) (((uintptr_t)n) & ~((align) - 1l))
95 #define ROUND_UP(n, align) ROUND_DOWN(((uintptr_t)n) + (align) - 1l, \
96 (align))
98 #define SET_HDRS(x) \
99 dos_hdr = (image_dos_header *)x; \
100 nt_hdr = (image_nt_header *)(x + dos_hdr->idh_lfanew); \
101 sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr + \
102 sizeof(image_nt_header));
104 static
105 int insert_padding(imgbase, imglen)
106 void **imgbase;
107 int *imglen;
109 image_section_header *sect_hdr;
110 image_dos_header *dos_hdr;
111 image_nt_header *nt_hdr;
112 image_optional_header opt_hdr;
113 int i = 0, sections, curlen = 0;
114 int offaccum = 0, oldraddr, oldrlen;
115 uint8_t *newimg, *tmp;
117 newimg = malloc(*imglen);
119 if (newimg == NULL)
120 return(ENOMEM);
122 bcopy(*imgbase, newimg, *imglen);
123 curlen = *imglen;
125 if (pe_get_optional_header((vm_offset_t)newimg, &opt_hdr))
126 return(0);
128 sections = pe_numsections((vm_offset_t)newimg);
130 SET_HDRS(newimg);
132 for (i = 0; i < sections; i++) {
133 oldraddr = sect_hdr->ish_rawdataaddr;
134 oldrlen = sect_hdr->ish_rawdatasize;
135 sect_hdr->ish_rawdataaddr = sect_hdr->ish_vaddr;
136 offaccum += ROUND_UP(sect_hdr->ish_vaddr - oldraddr,
137 opt_hdr.ioh_filealign);
138 offaccum +=
139 ROUND_UP(sect_hdr->ish_misc.ish_vsize,
140 opt_hdr.ioh_filealign) -
141 ROUND_UP(sect_hdr->ish_rawdatasize,
142 opt_hdr.ioh_filealign);
143 tmp = realloc(newimg, *imglen + offaccum);
144 if (tmp == NULL) {
145 free(newimg);
146 return(ENOMEM);
148 newimg = tmp;
149 SET_HDRS(newimg);
150 sect_hdr += i;
151 bzero(newimg + sect_hdr->ish_rawdataaddr,
152 ROUND_UP(sect_hdr->ish_misc.ish_vsize,
153 opt_hdr.ioh_filealign));
154 bcopy((uint8_t *)(*imgbase) + oldraddr,
155 newimg + sect_hdr->ish_rawdataaddr, oldrlen);
156 sect_hdr++;
159 free(*imgbase);
161 *imgbase = newimg;
162 *imglen += offaccum;
164 return(0);
167 static void
168 usage(void)
170 fprintf(stderr, "Usage: %s [-O] [-i <inffile>] -s <sysfile> "
171 "[-n devname] [-o outfile]\n", __progname);
172 fprintf(stderr, " %s -f <firmfile>\n", __progname);
174 exit(1);
177 static void
178 bincvt(char *sysfile, char *outfile, void *img, int fsize)
180 char *ptr;
181 char tname[] = "/tmp/ndiscvt.XXXXXX";
182 char sysbuf[1024];
183 FILE *binfp;
184 int fd;
186 fd = mkstemp(tname);
187 if (fd == -1)
188 err(1, "creating temp file %s failed", tname);
190 binfp = fdopen(fd, "a+");
191 if (binfp == NULL) {
192 unlink(tname);
193 err(1, "opening %s failed", tname);
196 if (fwrite(img, fsize, 1, binfp) != 1) {
197 unlink(tname);
198 err(1, "failed to output binary image");
201 fclose(binfp);
203 outfile = strdup(basename(outfile));
204 if (strchr(outfile, '.'))
205 *strchr(outfile, '.') = '\0';
207 snprintf(sysbuf, sizeof(sysbuf),
208 #ifdef __i386__
209 #ifdef __FreeBSD__
210 "objcopy -I binary -O elf32-i386-freebsd -B i386 %s %s.o\n",
211 #else
212 "objcopy -I binary -O elf32-i386 -B i386 %s %s.o\n",
213 #endif /* __FreeBSD__ */
214 #endif
215 #ifdef __amd64__
216 "objcopy -I binary -O elf64-x86-64 -B i386 %s %s.o\n",
217 #endif
218 tname, outfile);
219 printf("%s", sysbuf);
220 system(sysbuf);
221 unlink(tname);
223 ptr = tname;
224 while (*ptr) {
225 if (*ptr == '/' || *ptr == '.')
226 *ptr = '_';
227 ptr++;
230 snprintf(sysbuf, sizeof(sysbuf),
231 "objcopy --redefine-sym _binary_%s_start=%s_drv_data_start "
232 "--strip-symbol _binary_%s_size "
233 "--redefine-sym _binary_%s_end=%s_drv_data_end %s.o %s.o\n",
234 tname, sysfile, tname, tname, sysfile, outfile, outfile);
235 printf("%s", sysbuf);
236 system(sysbuf);
238 free(outfile);
239 return;
242 static void
243 firmcvt(char *firmfile)
245 char *basefile, *outfile, *ptr;
246 char sysbuf[1024];
248 outfile = strdup(basename(firmfile));
249 basefile = strdup(outfile);
251 snprintf(sysbuf, sizeof(sysbuf),
252 #ifdef __i386__
253 #ifdef __FreeBSD__
254 "objcopy -I binary -O elf32-i386-freebsd -B i386 %s %s.o\n",
255 #else
256 "objcopy -I binary -O elf32-i386 -B i386 %s %s.o\n",
257 #endif /* __FreeBSD__ */
258 #endif
259 #ifdef __amd64__
260 "objcopy -I binary -O elf64-x86-64 -B i386 %s %s.o\n",
261 #endif
262 firmfile, outfile);
263 printf("%s", sysbuf);
264 system(sysbuf);
266 ptr = firmfile;
267 while (*ptr) {
268 if (*ptr == '/' || *ptr == '.')
269 *ptr = '_';
270 ptr++;
272 ptr = basefile;
273 while (*ptr) {
274 if (*ptr == '/' || *ptr == '.')
275 *ptr = '_';
276 else
277 *ptr = tolower((int)*ptr);
278 ptr++;
281 snprintf(sysbuf, sizeof(sysbuf),
282 "objcopy --redefine-sym _binary_%s_start=%s_start "
283 "--strip-symbol _binary_%s_size "
284 "--redefine-sym _binary_%s_end=%s_end %s.o %s.o\n",
285 firmfile, basefile, firmfile, firmfile,
286 basefile, outfile, outfile);
287 ptr = sysbuf;
288 printf("%s", sysbuf);
289 system(sysbuf);
291 snprintf(sysbuf, sizeof(sysbuf),
292 "ld -Bshareable -d -warn-common -o %s.ko %s.o\n",
293 outfile, outfile);
294 printf("%s", sysbuf);
295 system(sysbuf);
297 free(basefile);
299 exit(0);
303 main(int argc, char *argv[])
305 FILE *fp, *outfp;
306 int i, bin = 0;
307 void *img;
308 int n, fsize, cnt;
309 char *ptr;
310 char *inffile = NULL, *sysfile = NULL;
311 char *outfile = NULL, *firmfile = NULL;
312 char *dname = NULL;
313 int ch;
315 while((ch = getopt(argc, argv, "i:s:o:n:f:O")) != -1) {
316 switch(ch) {
317 case 'f':
318 firmfile = optarg;
319 break;
320 case 'i':
321 inffile = optarg;
322 break;
323 case 's':
324 sysfile = optarg;
325 break;
326 case 'o':
327 outfile = optarg;
328 break;
329 case 'n':
330 dname = optarg;
331 break;
332 case 'O':
333 bin = 1;
334 break;
335 default:
336 usage();
337 break;
341 if (firmfile != NULL)
342 firmcvt(firmfile);
344 if (sysfile == NULL)
345 usage();
347 /* Open the .SYS file and load it into memory */
348 fp = fopen(sysfile, "r");
349 if (fp == NULL)
350 err(1, "opening .SYS file '%s' failed", sysfile);
351 fseek (fp, 0L, SEEK_END);
352 fsize = ftell (fp);
353 if (fsize == -1)
354 err(1, "getting size of .SYS file '%s' failed", sysfile);
355 rewind (fp);
356 img = malloc(fsize);
357 n = fread (img, fsize, 1, fp);
358 if (n < 1)
359 err(1, "reading .SYS file '%s' failed", sysfile);
361 fclose(fp);
362 fp = NULL;
364 if (insert_padding(&img, &fsize)) {
365 fprintf(stderr, "section relocation failed\n");
366 exit(1);
369 if (outfile == NULL || strcmp(outfile, "-") == 0)
370 outfp = stdout;
371 else {
372 outfp = fopen(outfile, "w");
373 if (outfp == NULL)
374 err(1, "opening output file '%s' failed", outfile);
377 fprintf(outfp, "\n/*\n");
378 fprintf(outfp, " * Generated from %s and %s (%d bytes)\n",
379 inffile == NULL ? "<notused>" : inffile, sysfile, fsize);
380 fprintf(outfp, " */\n\n");
382 if (dname != NULL) {
383 if (strlen(dname) > IFNAMSIZ)
384 err(1, "selected device name '%s' is "
385 "too long (max chars: %d)", dname, IFNAMSIZ);
386 fprintf (outfp, "#define NDIS_DEVNAME \"%s\"\n", dname);
387 fprintf (outfp, "#define NDIS_MODNAME %s\n\n", dname);
390 if (inffile == NULL) {
391 fprintf (outfp, "#ifdef NDIS_REGVALS\n");
392 fprintf (outfp, "ndis_cfg ndis_regvals[] = {\n");
393 fprintf (outfp, "\t{ NULL, NULL, { 0 }, 0 }\n");
394 fprintf (outfp, "#endif /* NDIS_REGVALS */\n");
396 fprintf (outfp, "};\n\n");
397 } else {
398 fp = fopen(inffile, "r");
399 if (fp == NULL)
400 err(1, "opening .INF file '%s' failed", inffile);
403 inf_parse(fp, outfp);
404 fclose(fp);
405 fp = NULL;
408 fprintf(outfp, "\n#ifdef NDIS_IMAGE\n");
410 if (bin) {
411 sysfile = strdup(basename(sysfile));
412 ptr = sysfile;
413 while (*ptr) {
414 if (*ptr == '.')
415 *ptr = '_';
416 ptr++;
418 fprintf(outfp,
419 "\nextern unsigned char %s_drv_data_start[];\n",
420 sysfile);
421 fprintf(outfp, "static unsigned char *drv_data = "
422 "%s_drv_data_start;\n\n", sysfile);
423 bincvt(sysfile, outfile, img, fsize);
424 goto done;
428 fprintf(outfp, "\nextern unsigned char drv_data[];\n\n");
430 fprintf(outfp, "__asm__(\".data\");\n");
431 fprintf(outfp, "__asm__(\".globl drv_data\");\n");
432 fprintf(outfp, "__asm__(\".type drv_data, @object\");\n");
433 fprintf(outfp, "__asm__(\".size drv_data, %d\");\n", fsize);
434 fprintf(outfp, "__asm__(\"drv_data:\");\n");
436 ptr = img;
437 cnt = 0;
438 while(cnt < fsize) {
439 fprintf (outfp, "__asm__(\".byte ");
440 for (i = 0; i < 10; i++) {
441 cnt++;
442 if (cnt == fsize) {
443 fprintf(outfp, "0x%.2X\");\n", ptr[i]);
444 goto done;
445 } else {
446 if (i == 9)
447 fprintf(outfp, "0x%.2X\");\n", ptr[i]);
448 else
449 fprintf(outfp, "0x%.2X, ", ptr[i]);
452 ptr += 10;
455 done:
457 fprintf(outfp, "#endif /* NDIS_IMAGE */\n");
459 if (fp != NULL)
460 fclose(fp);
461 fclose(outfp);
462 free(img);
463 exit(0);