ndiscvt.c revision 124089
1123475Swpaul/* 2123475Swpaul * Copyright (c) 2003 3123475Swpaul * Bill Paul <wpaul@windriver.com>. All rights reserved. 4123475Swpaul * 5123475Swpaul * Redistribution and use in source and binary forms, with or without 6123475Swpaul * modification, are permitted provided that the following conditions 7123475Swpaul * are met: 8123475Swpaul * 1. Redistributions of source code must retain the above copyright 9123475Swpaul * notice, this list of conditions and the following disclaimer. 10123475Swpaul * 2. Redistributions in binary form must reproduce the above copyright 11123475Swpaul * notice, this list of conditions and the following disclaimer in the 12123475Swpaul * documentation and/or other materials provided with the distribution. 13123475Swpaul * 3. All advertising materials mentioning features or use of this software 14123475Swpaul * must display the following acknowledgement: 15123475Swpaul * This product includes software developed by Bill Paul. 16123475Swpaul * 4. Neither the name of the author nor the names of any co-contributors 17123475Swpaul * may be used to endorse or promote products derived from this software 18123475Swpaul * without specific prior written permission. 19123475Swpaul * 20123475Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21123475Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22123475Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23123475Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24123475Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25123475Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26123475Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27123475Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28123475Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29123475Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30123475Swpaul * THE POSSIBILITY OF SUCH DAMAGE. 31123475Swpaul */ 32123475Swpaul 33123475Swpaul#include <sys/cdefs.h> 34123475Swpaul__FBSDID("$FreeBSD: head/usr.sbin/ndiscvt/ndiscvt.c 124089 2004-01-02 23:35:57Z green $"); 35123475Swpaul 36123475Swpaul#include <sys/types.h> 37123475Swpaul#include <sys/queue.h> 38124060Swpaul#include <sys/socket.h> 39124060Swpaul#include <net/if.h> 40123475Swpaul#include <stdlib.h> 41123475Swpaul#include <unistd.h> 42123475Swpaul#include <stdio.h> 43123475Swpaul#include <errno.h> 44123475Swpaul#include <string.h> 45123475Swpaul#include <err.h> 46123475Swpaul 47123475Swpaul#include <compat/ndis/pe_var.h> 48123475Swpaul 49123475Swpaul#include "inf.h" 50123475Swpaul 51123475Swpaulstatic int insert_padding(void **, int *); 52123475Swpaulextern const char *__progname; 53123475Swpaul 54123475Swpaul/* 55123475Swpaul * Sections in object code files can be sparse. That is, the 56123475Swpaul * section may occupy more space in memory that it does when 57123475Swpaul * stored in a disk file. In Windows PE files, each section header 58123475Swpaul * has a 'virtual size' and 'raw data size' field. The latter 59123475Swpaul * specifies the amount of section data actually stored in the 60123475Swpaul * disk file, and the former describes how much space the section 61123475Swpaul * should actually occupy in memory. If the vsize is larger than 62123475Swpaul * the rsize, we need to allocate some extra storage and fill 63123475Swpaul * it with zeros. (Think BSS.) 64123475Swpaul * 65123475Swpaul * The typical method of loading an executable file involves 66123475Swpaul * reading each segment into memory using the vaddr/vsize from 67123475Swpaul * each section header. We try to make a small optimization however 68123475Swpaul * and only pad/move segments when it's absolutely necessary, i.e. 69123475Swpaul * if the vsize is larger than the rsize. This conserves a little 70123475Swpaul * bit of memory, at the cost of having to fixup some of the values 71123475Swpaul * in the section headers. 72123475Swpaul */ 73123475Swpaul 74123475Swpaul#define ROUND_UP(x, y) \ 75123475Swpaul (((x) + (y)) - ((x) % (y))) 76123475Swpaul 77123475Swpaul#define SET_HDRS(x) \ 78123475Swpaul dos_hdr = (image_dos_header *)x; \ 79123475Swpaul nt_hdr = (image_nt_header *)(x + dos_hdr->idh_lfanew); \ 80123475Swpaul sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr + \ 81123475Swpaul sizeof(image_nt_header)); 82123475Swpaul 83123475Swpaulstatic 84123475Swpaulint insert_padding(imgbase, imglen) 85123475Swpaul void **imgbase; 86123475Swpaul int *imglen; 87123475Swpaul{ 88123475Swpaul image_section_header *sect_hdr; 89123475Swpaul image_dos_header *dos_hdr; 90123475Swpaul image_nt_header *nt_hdr; 91123475Swpaul image_optional_header opt_hdr; 92123475Swpaul int i = 0, sections, curlen = 0; 93123475Swpaul int offaccum = 0, diff, oldraddr, oldrlen; 94123475Swpaul uint8_t *newimg, *tmp; 95123475Swpaul 96123475Swpaul newimg = malloc(*imglen); 97123475Swpaul 98123475Swpaul if (newimg == NULL) 99123475Swpaul return(ENOMEM); 100123475Swpaul 101123475Swpaul bcopy(*imgbase, newimg, *imglen); 102123475Swpaul curlen = *imglen; 103123475Swpaul 104123475Swpaul if (pe_get_optional_header((vm_offset_t)newimg, &opt_hdr)) 105123475Swpaul return(0); 106123475Swpaul 107123475Swpaul sections = pe_numsections((vm_offset_t)newimg); 108123475Swpaul 109123475Swpaul SET_HDRS(newimg); 110123475Swpaul 111123475Swpaul for (i = 0; i < sections; i++) { 112123475Swpaul /* 113123475Swpaul * If we have accumulated any padding offset, 114123475Swpaul * add it to the raw data address of this segment. 115123475Swpaul */ 116123475Swpaul oldraddr = sect_hdr->ish_rawdataaddr; 117123475Swpaul oldrlen = sect_hdr->ish_rawdatasize; 118123475Swpaul if (offaccum) 119123475Swpaul sect_hdr->ish_rawdataaddr += offaccum; 120123475Swpaul if (sect_hdr->ish_misc.ish_vsize > 121123475Swpaul sect_hdr->ish_rawdatasize) { 122123475Swpaul diff = ROUND_UP(sect_hdr->ish_misc.ish_vsize - 123123475Swpaul sect_hdr->ish_rawdatasize, 124123475Swpaul opt_hdr.ioh_filealign); 125123475Swpaul offaccum += ROUND_UP(diff - 126123475Swpaul (sect_hdr->ish_misc.ish_vsize - 127123475Swpaul sect_hdr->ish_rawdatasize), 128123475Swpaul opt_hdr.ioh_filealign); 129123475Swpaul sect_hdr->ish_rawdatasize = 130123475Swpaul ROUND_UP(sect_hdr->ish_rawdatasize, 131123475Swpaul opt_hdr.ioh_filealign); 132123475Swpaul tmp = realloc(newimg, *imglen + offaccum); 133123475Swpaul if (tmp == NULL) { 134123475Swpaul free(newimg); 135123475Swpaul return(ENOMEM); 136123475Swpaul } 137123475Swpaul newimg = tmp; 138123475Swpaul SET_HDRS(newimg); 139123475Swpaul sect_hdr += i; 140123475Swpaul } 141123475Swpaul bzero(newimg + sect_hdr->ish_rawdataaddr, 142123475Swpaul ROUND_UP(sect_hdr->ish_misc.ish_vsize, 143123475Swpaul opt_hdr.ioh_filealign)); 144123475Swpaul bcopy((uint8_t *)(*imgbase) + oldraddr, 145123475Swpaul newimg + sect_hdr->ish_rawdataaddr, oldrlen); 146123475Swpaul sect_hdr++; 147123475Swpaul } 148123475Swpaul 149123475Swpaul free(*imgbase); 150123475Swpaul 151123475Swpaul *imgbase = newimg; 152123475Swpaul *imglen += offaccum; 153123475Swpaul 154123475Swpaul return(0); 155123475Swpaul} 156123475Swpaul 157123475Swpaulstatic void 158123475Swpaulusage(void) 159123475Swpaul{ 160123475Swpaul fprintf(stderr, "Usage: %s [-i <inffile>] -s <sysfile> " 161124089Sgreen "[-n devname] [-o outfile]\n", __progname); 162123475Swpaul exit(1); 163123475Swpaul} 164123475Swpaul 165123475Swpaulint 166123475Swpaulmain(int argc, char *argv[]) 167123475Swpaul{ 168123475Swpaul FILE *fp, *outfp; 169123475Swpaul void *img; 170123475Swpaul int n, fsize, cnt; 171123475Swpaul unsigned char *ptr; 172123475Swpaul int i; 173123475Swpaul char *inffile = NULL, *sysfile = NULL, *outfile = NULL; 174124060Swpaul char *dname = NULL; 175123475Swpaul int ch; 176123475Swpaul 177124060Swpaul while((ch = getopt(argc, argv, "i:s:o:n:")) != -1) { 178123475Swpaul switch(ch) { 179123475Swpaul case 'i': 180123475Swpaul inffile = optarg; 181123475Swpaul break; 182123475Swpaul case 's': 183123475Swpaul sysfile = optarg; 184123475Swpaul break; 185123475Swpaul case 'o': 186123475Swpaul outfile = optarg; 187123475Swpaul break; 188124060Swpaul case 'n': 189124060Swpaul dname = optarg; 190124060Swpaul break; 191123475Swpaul default: 192123475Swpaul usage(); 193123475Swpaul break; 194123475Swpaul } 195123475Swpaul } 196123475Swpaul 197123475Swpaul if (sysfile == NULL) 198123475Swpaul usage(); 199123475Swpaul 200123475Swpaul /* Open the .SYS file and load it into memory */ 201123475Swpaul fp = fopen(sysfile, "r"); 202123475Swpaul if (fp == NULL) 203123475Swpaul err(1, "opening .SYS file '%s' failed", sysfile); 204123475Swpaul fseek (fp, 0L, SEEK_END); 205123475Swpaul fsize = ftell (fp); 206123475Swpaul rewind (fp); 207123475Swpaul img = calloc(fsize, 1); 208123475Swpaul n = fread (img, fsize, 1, fp); 209123475Swpaul 210123475Swpaul fclose(fp); 211123475Swpaul 212123475Swpaul if (insert_padding(&img, &fsize)) { 213123475Swpaul fprintf(stderr, "section relocation failed\n"); 214123475Swpaul exit(1); 215123475Swpaul } 216123475Swpaul 217123475Swpaul if (outfile == NULL || strcmp(outfile, "-") == 0) 218123475Swpaul outfp = stdout; 219123475Swpaul else { 220123475Swpaul outfp = fopen(outfile, "w"); 221123475Swpaul if (outfp == NULL) 222123475Swpaul err(1, "opening output file '%s' failed", outfile); 223123475Swpaul } 224123475Swpaul 225123475Swpaul fprintf(outfp, "\n/*\n"); 226123475Swpaul fprintf(outfp, " * Generated from %s and %s (%d bytes)\n", 227124060Swpaul inffile == NULL ? "<notused>" : inffile, sysfile, fsize); 228123475Swpaul fprintf(outfp, " */\n\n"); 229123475Swpaul 230124060Swpaul if (dname != NULL) { 231124060Swpaul if (strlen(dname) > IFNAMSIZ) 232124060Swpaul err(1, "selected device name '%s' is " 233124060Swpaul "too long (max chars: %d)", dname, IFNAMSIZ); 234124060Swpaul fprintf (outfp, "#define NDIS_DEVNAME \"%s\"\n", dname); 235124085Swpaul fprintf (outfp, "#define NDIS_MODNAME %s\n\n", dname); 236124060Swpaul } 237124060Swpaul 238124060Swpaul if (inffile == NULL) { 239123475Swpaul fprintf (outfp, "ndis_cfg ndis_regvals[] = {\n"); 240124060Swpaul fprintf (outfp, "\t{ NULL, NULL, { 0 }, 0 }\n"); 241123475Swpaul 242123475Swpaul fprintf (outfp, "};\n\n"); 243123475Swpaul } else { 244123475Swpaul fp = fopen(inffile, "r"); 245123475Swpaul if (fp == NULL) 246123475Swpaul err(1, "opening .INF file '%s' failed", inffile); 247123475Swpaul 248123475Swpaul 249123475Swpaul inf_parse(fp, outfp); 250123475Swpaul fclose(fp); 251123475Swpaul } 252123475Swpaul 253123653Swpaul fprintf(outfp, "\n\nextern unsigned char drv_data[];\n\n"); 254123475Swpaul 255123653Swpaul fprintf(outfp, "__asm__(\".data\");\n"); 256123653Swpaul fprintf(outfp, "__asm__(\".type drv_data, @object\");\n"); 257123653Swpaul fprintf(outfp, "__asm__(\".size drv_data, %d\");\n", fsize); 258123653Swpaul fprintf(outfp, "__asm__(\"drv_data:\");\n"); 259123653Swpaul 260123475Swpaul ptr = img; 261123475Swpaul cnt = 0; 262123475Swpaul while(cnt < fsize) { 263123653Swpaul fprintf (outfp, "__asm__(\".byte "); 264123653Swpaul for (i = 0; i < 10; i++) { 265123475Swpaul cnt++; 266123475Swpaul if (cnt == fsize) { 267123653Swpaul fprintf(outfp, "0x%.2X\");\n", ptr[i]); 268123475Swpaul goto done; 269123653Swpaul } else { 270123653Swpaul if (i == 9) 271123653Swpaul fprintf(outfp, "0x%.2X\");\n", ptr[i]); 272123653Swpaul else 273123653Swpaul fprintf(outfp, "0x%.2X, ", ptr[i]); 274123653Swpaul } 275123475Swpaul } 276123653Swpaul ptr += 10; 277123475Swpaul } 278123475Swpaul 279123475Swpauldone: 280123475Swpaul 281123475Swpaul if (fp != NULL) 282123475Swpaul fclose(fp); 283123475Swpaul fclose(outfp); 284123475Swpaul free(img); 285123475Swpaul exit(0); 286123475Swpaul} 287