aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/ndiscvt/ndiscvt.c
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>2003-12-11 22:38:14 +0000
committerBill Paul <wpaul@FreeBSD.org>2003-12-11 22:38:14 +0000
commitd934c8b0dee15ae80a86115f468a1d52e07dd228 (patch)
tree7c2d5abaacdb24db0fe7ad5dd49024bfe7023096 /usr.sbin/ndiscvt/ndiscvt.c
parentc854fc10923e591ed41cc3f76d240aebdbb3f396 (diff)
downloadsrc-d934c8b0dee15ae80a86115f468a1d52e07dd228.tar.gz
src-d934c8b0dee15ae80a86115f468a1d52e07dd228.zip
Commit the ndiscvt(8) utility too. (Missed it in the last import.)
Notes
Notes: svn path=/head/; revision=123475
Diffstat (limited to 'usr.sbin/ndiscvt/ndiscvt.c')
-rw-r--r--usr.sbin/ndiscvt/ndiscvt.c264
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 000000000000..e3075951775b
--- /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);
+}