ndiscvt.c revision 126706
1/* 2 * Copyright (c) 2003 3 * Bill Paul <wpaul@windriver.com>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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. 19 * 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. 31 */ 32 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD: head/usr.sbin/ndiscvt/ndiscvt.c 126706 2004-03-07 02:49:06Z wpaul $"); 35 36#include <sys/types.h> 37#include <sys/queue.h> 38#include <sys/socket.h> 39#include <net/if.h> 40#include <stdlib.h> 41#include <unistd.h> 42#include <stdio.h> 43#include <errno.h> 44#include <string.h> 45#include <err.h> 46 47#include <compat/ndis/pe_var.h> 48 49#include "inf.h" 50 51static int insert_padding(void **, int *); 52extern const char *__progname; 53 54/* 55 * Sections in object code files can be sparse. That is, the 56 * section may occupy more space in memory that it does when 57 * stored in a disk file. In Windows PE files, each section header 58 * has a 'virtual size' and 'raw data size' field. The latter 59 * specifies the amount of section data actually stored in the 60 * disk file, and the former describes how much space the section 61 * should actually occupy in memory. If the vsize is larger than 62 * the rsize, we need to allocate some extra storage and fill 63 * it with zeros. (Think BSS.) 64 * 65 * The typical method of loading an executable file involves 66 * reading each segment into memory using the vaddr/vsize from 67 * each section header. We try to make a small optimization however 68 * and only pad/move segments when it's absolutely necessary, i.e. 69 * if the vsize is larger than the rsize. This conserves a little 70 * bit of memory, at the cost of having to fixup some of the values 71 * in the section headers. 72 */ 73 74#define ROUND_UP(x, y) \ 75 (((x) + (y)) - ((x) % (y))) 76 77#define SET_HDRS(x) \ 78 dos_hdr = (image_dos_header *)x; \ 79 nt_hdr = (image_nt_header *)(x + dos_hdr->idh_lfanew); \ 80 sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr + \ 81 sizeof(image_nt_header)); 82 83static 84int insert_padding(imgbase, imglen) 85 void **imgbase; 86 int *imglen; 87{ 88 image_section_header *sect_hdr; 89 image_dos_header *dos_hdr; 90 image_nt_header *nt_hdr; 91 image_optional_header opt_hdr; 92 int i = 0, sections, curlen = 0; 93 int offaccum = 0, diff, oldraddr, oldrlen; 94 uint8_t *newimg, *tmp; 95 96 newimg = malloc(*imglen); 97 98 if (newimg == NULL) 99 return(ENOMEM); 100 101 bcopy(*imgbase, newimg, *imglen); 102 curlen = *imglen; 103 104 if (pe_get_optional_header((vm_offset_t)newimg, &opt_hdr)) 105 return(0); 106 107 sections = pe_numsections((vm_offset_t)newimg); 108 109 SET_HDRS(newimg); 110 111 for (i = 0; i < sections; i++) { 112 /* 113 * If we have accumulated any padding offset, 114 * add it to the raw data address of this segment. 115 */ 116 oldraddr = sect_hdr->ish_rawdataaddr; 117 oldrlen = sect_hdr->ish_rawdatasize; 118 if (offaccum) 119 sect_hdr->ish_rawdataaddr += offaccum; 120 if (sect_hdr->ish_misc.ish_vsize > 121 sect_hdr->ish_rawdatasize) { 122 diff = ROUND_UP(sect_hdr->ish_misc.ish_vsize - 123 sect_hdr->ish_rawdatasize, 124 opt_hdr.ioh_filealign); 125 offaccum += ROUND_UP(diff - 126 (sect_hdr->ish_misc.ish_vsize - 127 sect_hdr->ish_rawdatasize), 128 opt_hdr.ioh_filealign); 129 sect_hdr->ish_rawdatasize = 130 ROUND_UP(sect_hdr->ish_rawdatasize, 131 opt_hdr.ioh_filealign); 132 tmp = realloc(newimg, *imglen + offaccum); 133 if (tmp == NULL) { 134 free(newimg); 135 return(ENOMEM); 136 } 137 newimg = tmp; 138 SET_HDRS(newimg); 139 sect_hdr += i; 140 } 141 bzero(newimg + sect_hdr->ish_rawdataaddr, 142 ROUND_UP(sect_hdr->ish_misc.ish_vsize, 143 opt_hdr.ioh_filealign)); 144 bcopy((uint8_t *)(*imgbase) + oldraddr, 145 newimg + sect_hdr->ish_rawdataaddr, oldrlen); 146 sect_hdr++; 147 } 148 149 free(*imgbase); 150 151 *imgbase = newimg; 152 *imglen += offaccum; 153 154 return(0); 155} 156 157static void 158usage(void) 159{ 160 fprintf(stderr, "Usage: %s [-i <inffile>] -s <sysfile> " 161 "[-n devname] [-o outfile]\n", __progname); 162 exit(1); 163} 164 165int 166main(int argc, char *argv[]) 167{ 168 FILE *fp, *outfp; 169 void *img; 170 int n, fsize, cnt; 171 unsigned char *ptr; 172 int i; 173 char *inffile = NULL, *sysfile = NULL, *outfile = NULL; 174 char *dname = NULL; 175 int ch; 176 177 while((ch = getopt(argc, argv, "i:s:o:n:")) != -1) { 178 switch(ch) { 179 case 'i': 180 inffile = optarg; 181 break; 182 case 's': 183 sysfile = optarg; 184 break; 185 case 'o': 186 outfile = optarg; 187 break; 188 case 'n': 189 dname = optarg; 190 break; 191 default: 192 usage(); 193 break; 194 } 195 } 196 197 if (sysfile == NULL) 198 usage(); 199 200 /* Open the .SYS file and load it into memory */ 201 fp = fopen(sysfile, "r"); 202 if (fp == NULL) 203 err(1, "opening .SYS file '%s' failed", sysfile); 204 fseek (fp, 0L, SEEK_END); 205 fsize = ftell (fp); 206 rewind (fp); 207 img = calloc(fsize, 1); 208 n = fread (img, fsize, 1, fp); 209 210 fclose(fp); 211 212 if (insert_padding(&img, &fsize)) { 213 fprintf(stderr, "section relocation failed\n"); 214 exit(1); 215 } 216 217 if (outfile == NULL || strcmp(outfile, "-") == 0) 218 outfp = stdout; 219 else { 220 outfp = fopen(outfile, "w"); 221 if (outfp == NULL) 222 err(1, "opening output file '%s' failed", outfile); 223 } 224 225 fprintf(outfp, "\n/*\n"); 226 fprintf(outfp, " * Generated from %s and %s (%d bytes)\n", 227 inffile == NULL ? "<notused>" : inffile, sysfile, fsize); 228 fprintf(outfp, " */\n\n"); 229 230 if (dname != NULL) { 231 if (strlen(dname) > IFNAMSIZ) 232 err(1, "selected device name '%s' is " 233 "too long (max chars: %d)", dname, IFNAMSIZ); 234 fprintf (outfp, "#define NDIS_DEVNAME \"%s\"\n", dname); 235 fprintf (outfp, "#define NDIS_MODNAME %s\n\n", dname); 236 } 237 238 if (inffile == NULL) { 239 fprintf (outfp, "#ifdef NDIS_REGVALS\n"); 240 fprintf (outfp, "ndis_cfg ndis_regvals[] = {\n"); 241 fprintf (outfp, "\t{ NULL, NULL, { 0 }, 0 }\n"); 242 fprintf (outfp, "#endif /* NDIS_REGVALS */\n"); 243 244 fprintf (outfp, "};\n\n"); 245 } else { 246 fp = fopen(inffile, "r"); 247 if (fp == NULL) 248 err(1, "opening .INF file '%s' failed", inffile); 249 250 251 inf_parse(fp, outfp); 252 fclose(fp); 253 } 254 255 fprintf(outfp, "\n#ifdef NDIS_IMAGE\n"); 256 fprintf(outfp, "\nextern unsigned char drv_data[];\n\n"); 257 258 fprintf(outfp, "__asm__(\".data\");\n"); 259 fprintf(outfp, "__asm__(\".type drv_data, @object\");\n"); 260 fprintf(outfp, "__asm__(\".size drv_data, %d\");\n", fsize); 261 fprintf(outfp, "__asm__(\"drv_data:\");\n"); 262 263 ptr = img; 264 cnt = 0; 265 while(cnt < fsize) { 266 fprintf (outfp, "__asm__(\".byte "); 267 for (i = 0; i < 10; i++) { 268 cnt++; 269 if (cnt == fsize) { 270 fprintf(outfp, "0x%.2X\");\n", ptr[i]); 271 goto done; 272 } else { 273 if (i == 9) 274 fprintf(outfp, "0x%.2X\");\n", ptr[i]); 275 else 276 fprintf(outfp, "0x%.2X, ", ptr[i]); 277 } 278 } 279 ptr += 10; 280 } 281 282done: 283 284 fprintf(outfp, "#endif /* NDIS_IMAGE */\n"); 285 if (fp != NULL) 286 fclose(fp); 287 fclose(outfp); 288 free(img); 289 exit(0); 290} 291