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
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>
35 __FBSDID("$FreeBSD: src/usr.sbin/ndiscvt/ndiscvt.c,v 1.9.2.2 2005/02/23 16:31:47 wpaul Exp $");
38 __RCSID("$NetBSD: ndiscvt.c,v 1.8 2006/05/26 11:45:31 jnemeth Exp $");
42 #include <sys/types.h>
44 #include <sys/stdint.h>
46 #include <sys/queue.h>
47 #include <sys/socket.h>
59 #include <compat/ndis/pe_var.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
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, \
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));
105 int insert_padding(imgbase
, 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
);
122 bcopy(*imgbase
, newimg
, *imglen
);
125 if (pe_get_optional_header((vm_offset_t
)newimg
, &opt_hdr
))
128 sections
= pe_numsections((vm_offset_t
)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
);
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
);
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
);
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
);
178 bincvt(char *sysfile
, char *outfile
, void *img
, int fsize
)
181 char tname
[] = "/tmp/ndiscvt.XXXXXX";
188 err(1, "creating temp file %s failed", tname
);
190 binfp
= fdopen(fd
, "a+");
193 err(1, "opening %s failed", tname
);
196 if (fwrite(img
, fsize
, 1, binfp
) != 1) {
198 err(1, "failed to output binary image");
203 outfile
= strdup(basename(outfile
));
204 if (strchr(outfile
, '.'))
205 *strchr(outfile
, '.') = '\0';
207 snprintf(sysbuf
, sizeof(sysbuf
),
210 "objcopy -I binary -O elf32-i386-freebsd -B i386 %s %s.o\n",
212 "objcopy -I binary -O elf32-i386 -B i386 %s %s.o\n",
213 #endif /* __FreeBSD__ */
216 "objcopy -I binary -O elf64-x86-64 -B i386 %s %s.o\n",
219 printf("%s", sysbuf
);
225 if (*ptr
== '/' || *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
);
243 firmcvt(char *firmfile
)
245 char *basefile
, *outfile
, *ptr
;
248 outfile
= strdup(basename(firmfile
));
249 basefile
= strdup(outfile
);
251 snprintf(sysbuf
, sizeof(sysbuf
),
254 "objcopy -I binary -O elf32-i386-freebsd -B i386 %s %s.o\n",
256 "objcopy -I binary -O elf32-i386 -B i386 %s %s.o\n",
257 #endif /* __FreeBSD__ */
260 "objcopy -I binary -O elf64-x86-64 -B i386 %s %s.o\n",
263 printf("%s", sysbuf
);
268 if (*ptr
== '/' || *ptr
== '.')
274 if (*ptr
== '/' || *ptr
== '.')
277 *ptr
= tolower((int)*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
);
288 printf("%s", sysbuf
);
291 snprintf(sysbuf
, sizeof(sysbuf
),
292 "ld -Bshareable -d -warn-common -o %s.ko %s.o\n",
294 printf("%s", sysbuf
);
303 main(int argc
, char *argv
[])
310 char *inffile
= NULL
, *sysfile
= NULL
;
311 char *outfile
= NULL
, *firmfile
= NULL
;
315 while((ch
= getopt(argc
, argv
, "i:s:o:n:f:O")) != -1) {
341 if (firmfile
!= NULL
)
347 /* Open the .SYS file and load it into memory */
348 fp
= fopen(sysfile
, "r");
350 err(1, "opening .SYS file '%s' failed", sysfile
);
351 fseek (fp
, 0L, SEEK_END
);
354 err(1, "getting size of .SYS file '%s' failed", sysfile
);
357 n
= fread (img
, fsize
, 1, fp
);
359 err(1, "reading .SYS file '%s' failed", sysfile
);
364 if (insert_padding(&img
, &fsize
)) {
365 fprintf(stderr
, "section relocation failed\n");
369 if (outfile
== NULL
|| strcmp(outfile
, "-") == 0)
372 outfp
= fopen(outfile
, "w");
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");
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");
398 fp
= fopen(inffile
, "r");
400 err(1, "opening .INF file '%s' failed", inffile
);
403 inf_parse(fp
, outfp
);
408 fprintf(outfp
, "\n#ifdef NDIS_IMAGE\n");
411 sysfile
= strdup(basename(sysfile
));
419 "\nextern unsigned char %s_drv_data_start[];\n",
421 fprintf(outfp
, "static unsigned char *drv_data = "
422 "%s_drv_data_start;\n\n", sysfile
);
423 bincvt(sysfile
, outfile
, img
, fsize
);
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");
439 fprintf (outfp
, "__asm__(\".byte ");
440 for (i
= 0; i
< 10; i
++) {
443 fprintf(outfp
, "0x%.2X\");\n", ptr
[i
]);
447 fprintf(outfp
, "0x%.2X\");\n", ptr
[i
]);
449 fprintf(outfp
, "0x%.2X, ", ptr
[i
]);
457 fprintf(outfp
, "#endif /* NDIS_IMAGE */\n");