ndiscvt.c revision 124060
1101100Ssos/* 2101100Ssos * Copyright (c) 2003 3101100Ssos * Bill Paul <wpaul@windriver.com>. All rights reserved. 4101100Ssos * 5101100Ssos * Redistribution and use in source and binary forms, with or without 6101100Ssos * modification, are permitted provided that the following conditions 7101100Ssos * are met: 8101100Ssos * 1. Redistributions of source code must retain the above copyright 9101100Ssos * notice, this list of conditions and the following disclaimer. 10101100Ssos * 2. Redistributions in binary form must reproduce the above copyright 11101100Ssos * notice, this list of conditions and the following disclaimer in the 12101100Ssos * documentation and/or other materials provided with the distribution. 13101100Ssos * 3. All advertising materials mentioning features or use of this software 14101100Ssos * must display the following acknowledgement: 15101100Ssos * This product includes software developed by Bill Paul. 16101100Ssos * 4. Neither the name of the author nor the names of any co-contributors 17101100Ssos * may be used to endorse or promote products derived from this software 18101100Ssos * without specific prior written permission. 19101100Ssos * 20101100Ssos * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21101100Ssos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22101100Ssos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23101100Ssos * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24101100Ssos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25101100Ssos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26101100Ssos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27101100Ssos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28101100Ssos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29101100Ssos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30101100Ssos * THE POSSIBILITY OF SUCH DAMAGE. 31101100Ssos */ 32101100Ssos 33101100Ssos#include <sys/cdefs.h> 34101100Ssos__FBSDID("$FreeBSD: head/usr.sbin/ndiscvt/ndiscvt.c 124060 2004-01-02 04:31:06Z wpaul $"); 35101100Ssos 36101100Ssos#include <sys/types.h> 37101100Ssos#include <sys/queue.h> 38101100Ssos#include <sys/socket.h> 39101100Ssos#include <net/if.h> 40101100Ssos#include <stdlib.h> 41101100Ssos#include <unistd.h> 42101100Ssos#include <stdio.h> 43101100Ssos#include <errno.h> 44101100Ssos#include <string.h> 45101100Ssos#include <err.h> 46101100Ssos 47101100Ssos#include <compat/ndis/pe_var.h> 48101100Ssos 49101100Ssos#include "inf.h" 50101100Ssos 51101100Ssosstatic int insert_padding(void **, int *); 52101100Ssosextern const char *__progname; 53101100Ssos 54101100Ssos/* 55101100Ssos * Sections in object code files can be sparse. That is, the 56101100Ssos * section may occupy more space in memory that it does when 57101100Ssos * stored in a disk file. In Windows PE files, each section header 58101100Ssos * has a 'virtual size' and 'raw data size' field. The latter 59101100Ssos * specifies the amount of section data actually stored in the 60101100Ssos * disk file, and the former describes how much space the section 61101100Ssos * should actually occupy in memory. If the vsize is larger than 62101100Ssos * the rsize, we need to allocate some extra storage and fill 63101100Ssos * it with zeros. (Think BSS.) 64101100Ssos * 65101100Ssos * The typical method of loading an executable file involves 66101100Ssos * reading each segment into memory using the vaddr/vsize from 67101100Ssos * each section header. We try to make a small optimization however 68101100Ssos * and only pad/move segments when it's absolutely necessary, i.e. 69101100Ssos * if the vsize is larger than the rsize. This conserves a little 70101100Ssos * bit of memory, at the cost of having to fixup some of the values 71101100Ssos * in the section headers. 72101100Ssos */ 73101100Ssos 74101100Ssos#define ROUND_UP(x, y) \ 75101100Ssos (((x) + (y)) - ((x) % (y))) 76101100Ssos 77101100Ssos#define SET_HDRS(x) \ 78101100Ssos dos_hdr = (image_dos_header *)x; \ 79108533Sschweikh nt_hdr = (image_nt_header *)(x + dos_hdr->idh_lfanew); \ 80101100Ssos sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr + \ 81101100Ssos sizeof(image_nt_header)); 82101100Ssos 83101100Ssosstatic 84101100Ssosint insert_padding(imgbase, imglen) 85101100Ssos void **imgbase; 86101100Ssos int *imglen; 87101100Ssos{ 88101100Ssos image_section_header *sect_hdr; 89101100Ssos image_dos_header *dos_hdr; 90101100Ssos image_nt_header *nt_hdr; 91101100Ssos image_optional_header opt_hdr; 92101100Ssos int i = 0, sections, curlen = 0; 93101100Ssos int offaccum = 0, diff, oldraddr, oldrlen; 94101100Ssos uint8_t *newimg, *tmp; 95101100Ssos 96101100Ssos newimg = malloc(*imglen); 97101100Ssos 98101100Ssos if (newimg == NULL) 99101100Ssos return(ENOMEM); 100101100Ssos 101101100Ssos bcopy(*imgbase, newimg, *imglen); 102101100Ssos curlen = *imglen; 103101100Ssos 104101100Ssos if (pe_get_optional_header((vm_offset_t)newimg, &opt_hdr)) 105101100Ssos return(0); 106101100Ssos 107101100Ssos sections = pe_numsections((vm_offset_t)newimg); 108101100Ssos 109101100Ssos SET_HDRS(newimg); 110101100Ssos 111101100Ssos for (i = 0; i < sections; i++) { 112101100Ssos /* 113101100Ssos * If we have accumulated any padding offset, 114101100Ssos * add it to the raw data address of this segment. 115101100Ssos */ 116101100Ssos oldraddr = sect_hdr->ish_rawdataaddr; 117101100Ssos oldrlen = sect_hdr->ish_rawdatasize; 118101100Ssos if (offaccum) 119101100Ssos sect_hdr->ish_rawdataaddr += offaccum; 120101100Ssos if (sect_hdr->ish_misc.ish_vsize > 121101100Ssos sect_hdr->ish_rawdatasize) { 122101100Ssos diff = ROUND_UP(sect_hdr->ish_misc.ish_vsize - 123101100Ssos sect_hdr->ish_rawdatasize, 124101100Ssos opt_hdr.ioh_filealign); 125101100Ssos offaccum += ROUND_UP(diff - 126101100Ssos (sect_hdr->ish_misc.ish_vsize - 127101100Ssos sect_hdr->ish_rawdatasize), 128101100Ssos opt_hdr.ioh_filealign); 129101100Ssos sect_hdr->ish_rawdatasize = 130101100Ssos ROUND_UP(sect_hdr->ish_rawdatasize, 131101100Ssos opt_hdr.ioh_filealign); 132101100Ssos tmp = realloc(newimg, *imglen + offaccum); 133101100Ssos if (tmp == NULL) { 134101100Ssos free(newimg); 135101100Ssos return(ENOMEM); 136101100Ssos } 137101100Ssos newimg = tmp; 138101100Ssos SET_HDRS(newimg); 139101100Ssos sect_hdr += i; 140101100Ssos } 141101100Ssos bzero(newimg + sect_hdr->ish_rawdataaddr, 142101100Ssos ROUND_UP(sect_hdr->ish_misc.ish_vsize, 143101100Ssos opt_hdr.ioh_filealign)); 144101100Ssos bcopy((uint8_t *)(*imgbase) + oldraddr, 145101100Ssos newimg + sect_hdr->ish_rawdataaddr, oldrlen); 146101100Ssos sect_hdr++; 147101100Ssos } 148101100Ssos 149101100Ssos free(*imgbase); 150101100Ssos 151101100Ssos *imgbase = newimg; 152101100Ssos *imglen += offaccum; 153101100Ssos 154101100Ssos return(0); 155101100Ssos} 156101100Ssos 157102058Ssosstatic void 158102058Ssosusage(void) 159102058Ssos{ 160102058Ssos fprintf(stderr, "Usage: %s [-i <inffile>] -s <sysfile> " 161102058Ssos "[-d devname] [-o outfile]\n", __progname); 162102058Ssos exit(1); 163102058Ssos} 164102058Ssos 165108533Sschweikhint 166102058Ssosmain(int argc, char *argv[]) 167108533Sschweikh{ 168102058Ssos FILE *fp, *outfp; 169102058Ssos void *img; 170102058Ssos int n, fsize, cnt; 171102058Ssos unsigned char *ptr; 172101100Ssos int i; 173101100Ssos char *inffile = NULL, *sysfile = NULL, *outfile = NULL; 174101100Ssos char *dname = NULL; 175102058Ssos int ch; 176102058Ssos 177102058Ssos while((ch = getopt(argc, argv, "i:s:o:n:")) != -1) { 178108533Sschweikh switch(ch) { 179102058Ssos case 'i': 180102058Ssos inffile = optarg; 181102058Ssos break; 182101100Ssos case 's': 183101100Ssos sysfile = optarg; 184101100Ssos break; 185101100Ssos case 'o': 186101100Ssos outfile = optarg; 187101100Ssos break; 188101100Ssos case 'n': 189101100Ssos dname = optarg; 190102058Ssos break; 191101100Ssos default: 192101100Ssos usage(); 193101100Ssos break; 194101100Ssos } 195101100Ssos } 196101100Ssos 197101100Ssos if (sysfile == NULL) 198101100Ssos usage(); 199101100Ssos 200101100Ssos /* Open the .SYS file and load it into memory */ 201101100Ssos fp = fopen(sysfile, "r"); 202101100Ssos if (fp == NULL) 203101100Ssos err(1, "opening .SYS file '%s' failed", sysfile); 204101100Ssos fseek (fp, 0L, SEEK_END); 205101100Ssos fsize = ftell (fp); 206101100Ssos rewind (fp); 207101100Ssos img = calloc(fsize, 1); 208101100Ssos n = fread (img, fsize, 1, fp); 209101100Ssos 210101100Ssos fclose(fp); 211101100Ssos 212101100Ssos if (insert_padding(&img, &fsize)) { 213102058Ssos fprintf(stderr, "section relocation failed\n"); 214101100Ssos exit(1); 215101100Ssos } 216101100Ssos 217101100Ssos if (outfile == NULL || strcmp(outfile, "-") == 0) 218101100Ssos outfp = stdout; 219101100Ssos else { 220101100Ssos outfp = fopen(outfile, "w"); 221101100Ssos if (outfp == NULL) 222101100Ssos err(1, "opening output file '%s' failed", outfile); 223102058Ssos } 224101100Ssos 225101100Ssos fprintf(outfp, "\n/*\n"); 226101100Ssos fprintf(outfp, " * Generated from %s and %s (%d bytes)\n", 227101100Ssos inffile == NULL ? "<notused>" : inffile, sysfile, fsize); 228102058Ssos fprintf(outfp, " */\n\n"); 229102058Ssos 230101100Ssos if (dname != NULL) { 231101100Ssos if (strlen(dname) > IFNAMSIZ) 232101100Ssos err(1, "selected device name '%s' is " 233101100Ssos "too long (max chars: %d)", dname, IFNAMSIZ); 234101100Ssos fprintf (outfp, "#define NDIS_DEVNAME \"%s\"\n", dname); 235101100Ssos fprintf (outfp, "#define NDIS_MODNAME %s\n", dname); 236101100Ssos } 237101100Ssos 238101100Ssos if (inffile == NULL) { 239101100Ssos fprintf (outfp, "ndis_cfg ndis_regvals[] = {\n"); 240101100Ssos fprintf (outfp, "\t{ NULL, NULL, { 0 }, 0 }\n"); 241101100Ssos 242101100Ssos fprintf (outfp, "};\n\n"); 243101100Ssos } else { 244101100Ssos fp = fopen(inffile, "r"); 245101100Ssos if (fp == NULL) 246101100Ssos err(1, "opening .INF file '%s' failed", inffile); 247101100Ssos 248101100Ssos 249101100Ssos inf_parse(fp, outfp); 250101100Ssos fclose(fp); 251101100Ssos } 252101100Ssos 253101100Ssos fprintf(outfp, "\n\nextern unsigned char drv_data[];\n\n"); 254101100Ssos 255101100Ssos fprintf(outfp, "__asm__(\".data\");\n"); 256101100Ssos fprintf(outfp, "__asm__(\".type drv_data, @object\");\n"); 257101100Ssos fprintf(outfp, "__asm__(\".size drv_data, %d\");\n", fsize); 258108533Sschweikh fprintf(outfp, "__asm__(\"drv_data:\");\n"); 259101100Ssos 260101100Ssos ptr = img; 261101100Ssos cnt = 0; 262101100Ssos while(cnt < fsize) { 263101100Ssos fprintf (outfp, "__asm__(\".byte "); 264101100Ssos for (i = 0; i < 10; i++) { 265101100Ssos cnt++; 266101100Ssos if (cnt == fsize) { 267101100Ssos fprintf(outfp, "0x%.2X\");\n", ptr[i]); 268101100Ssos goto done; 269101100Ssos } else { 270101100Ssos if (i == 9) 271101100Ssos fprintf(outfp, "0x%.2X\");\n", ptr[i]); 272101100Ssos else 273101100Ssos fprintf(outfp, "0x%.2X, ", ptr[i]); 274101100Ssos } 275101100Ssos } 276101100Ssos ptr += 10; 277101100Ssos } 278101100Ssos 279101100Ssosdone: 280101100Ssos 281101100Ssos if (fp != NULL) 282101100Ssos fclose(fp); 283101100Ssos fclose(outfp); 284102058Ssos free(img); 285101100Ssos exit(0); 286101100Ssos} 287101100Ssos