diff options
Diffstat (limited to 'usr.sbin/ndiscvt/ndiscvt.c')
-rw-r--r-- | usr.sbin/ndiscvt/ndiscvt.c | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/usr.sbin/ndiscvt/ndiscvt.c b/usr.sbin/ndiscvt/ndiscvt.c new file mode 100644 index 0000000..e307595 --- /dev/null +++ b/usr.sbin/ndiscvt/ndiscvt.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2003 + * Bill Paul <wpaul@windriver.com>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/queue.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <err.h> + +#include <compat/ndis/pe_var.h> + +#include "inf.h" + +static int insert_padding(void **, int *); +extern const char *__progname; + +/* + * Sections in object code files can be sparse. That is, the + * section may occupy more space in memory that it does when + * stored in a disk file. In Windows PE files, each section header + * has a 'virtual size' and 'raw data size' field. The latter + * specifies the amount of section data actually stored in the + * disk file, and the former describes how much space the section + * should actually occupy in memory. If the vsize is larger than + * the rsize, we need to allocate some extra storage and fill + * it with zeros. (Think BSS.) + * + * The typical method of loading an executable file involves + * reading each segment into memory using the vaddr/vsize from + * each section header. We try to make a small optimization however + * and only pad/move segments when it's absolutely necessary, i.e. + * if the vsize is larger than the rsize. This conserves a little + * bit of memory, at the cost of having to fixup some of the values + * in the section headers. + */ + +#define ROUND_UP(x, y) \ + (((x) + (y)) - ((x) % (y))) + +#define SET_HDRS(x) \ + dos_hdr = (image_dos_header *)x; \ + nt_hdr = (image_nt_header *)(x + dos_hdr->idh_lfanew); \ + sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr + \ + sizeof(image_nt_header)); + +static +int insert_padding(imgbase, imglen) + void **imgbase; + int *imglen; +{ + image_section_header *sect_hdr; + image_dos_header *dos_hdr; + image_nt_header *nt_hdr; + image_optional_header opt_hdr; + int i = 0, sections, curlen = 0; + int offaccum = 0, diff, oldraddr, oldrlen; + uint8_t *newimg, *tmp; + + newimg = malloc(*imglen); + + if (newimg == NULL) + return(ENOMEM); + + bcopy(*imgbase, newimg, *imglen); + curlen = *imglen; + + if (pe_get_optional_header((vm_offset_t)newimg, &opt_hdr)) + return(0); + + sections = pe_numsections((vm_offset_t)newimg); + + SET_HDRS(newimg); + + for (i = 0; i < sections; i++) { + /* + * If we have accumulated any padding offset, + * add it to the raw data address of this segment. + */ + oldraddr = sect_hdr->ish_rawdataaddr; + oldrlen = sect_hdr->ish_rawdatasize; + if (offaccum) + sect_hdr->ish_rawdataaddr += offaccum; + if (sect_hdr->ish_misc.ish_vsize > + sect_hdr->ish_rawdatasize) { + diff = ROUND_UP(sect_hdr->ish_misc.ish_vsize - + sect_hdr->ish_rawdatasize, + opt_hdr.ioh_filealign); + offaccum += ROUND_UP(diff - + (sect_hdr->ish_misc.ish_vsize - + sect_hdr->ish_rawdatasize), + opt_hdr.ioh_filealign); + sect_hdr->ish_rawdatasize = + ROUND_UP(sect_hdr->ish_rawdatasize, + opt_hdr.ioh_filealign); + tmp = realloc(newimg, *imglen + offaccum); + if (tmp == NULL) { + free(newimg); + return(ENOMEM); + } + newimg = tmp; + SET_HDRS(newimg); + sect_hdr += i; + } + bzero(newimg + sect_hdr->ish_rawdataaddr, + ROUND_UP(sect_hdr->ish_misc.ish_vsize, + opt_hdr.ioh_filealign)); + bcopy((uint8_t *)(*imgbase) + oldraddr, + newimg + sect_hdr->ish_rawdataaddr, oldrlen); + sect_hdr++; + } + + free(*imgbase); + + *imgbase = newimg; + *imglen += offaccum; + + return(0); +} + +static void +usage(void) +{ + fprintf(stderr, "Usage: %s [-i <inffile>] -s <sysfile> " + "[-o outfile]\n", __progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + FILE *fp, *outfp; + void *img; + int n, fsize, cnt; + unsigned char *ptr; + int i; + char *inffile = NULL, *sysfile = NULL, *outfile = NULL; + int ch; + + while((ch = getopt(argc, argv, "i:s:o")) != -1) { + switch(ch) { + case 'i': + inffile = optarg; + break; + case 's': + sysfile = optarg; + break; + case 'o': + outfile = optarg; + break; + default: + usage(); + break; + } + } + + if (sysfile == NULL) + usage(); + + /* Open the .SYS file and load it into memory */ + fp = fopen(sysfile, "r"); + if (fp == NULL) + err(1, "opening .SYS file '%s' failed", sysfile); + fseek (fp, 0L, SEEK_END); + fsize = ftell (fp); + rewind (fp); + img = calloc(fsize, 1); + n = fread (img, fsize, 1, fp); + + fclose(fp); + + if (insert_padding(&img, &fsize)) { + fprintf(stderr, "section relocation failed\n"); + exit(1); + } + + if (outfile == NULL || strcmp(outfile, "-") == 0) + outfp = stdout; + else { + outfp = fopen(outfile, "w"); + if (outfp == NULL) + err(1, "opening output file '%s' failed", outfile); + } + + fprintf(outfp, "\n/*\n"); + fprintf(outfp, " * Generated from %s and %s (%d bytes)\n", + inffile, sysfile, fsize); + fprintf(outfp, " */\n\n"); + + if (fp == NULL) { + fprintf (outfp, "ndis_cfg ndis_regvals[] = {\n"); + fprintf (outfp, "\t{ NULL, NULL, ndis_parm_int, { 0 } }\n"); + + fprintf (outfp, "};\n\n"); + } else { + fp = fopen(inffile, "r"); + if (fp == NULL) + err(1, "opening .INF file '%s' failed", inffile); + + + inf_parse(fp, outfp); + fclose(fp); + } + + fprintf(outfp, "\n\nunsigned char drv_data[] = { \n"); + + ptr = img; + cnt = 0; + while(cnt < fsize) { + for (i = 0; i < 12; i++) { + cnt++; + if (cnt == fsize) { + fprintf(outfp, "0x%.2X\n", ptr[i]); + goto done; + } else + fprintf(outfp, "0x%.2X, ", ptr[i]); + } + fprintf(outfp, "\n"); + ptr += 12; + } + +done: + fprintf(outfp, "};\n"); + + if (fp != NULL) + fclose(fp); + fclose(outfp); + free(img); + exit(0); +} |