Merge from vendor branch OPENPAM:
[dragonfly.git] / usr.sbin / ndiscvt / ndiscvt.c
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  * $DragonFly: src/usr.sbin/ndiscvt/ndiscvt.c,v 1.1 2004/07/30 00:24:24 dillon Exp $
33  */
34
35 #include <sys/types.h>
36 #include <sys/queue.h>
37 #include <sys/socket.h>
38 #include <net/if.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <stdio.h>
42 #include <errno.h>
43 #include <string.h>
44 #include <err.h>
45
46 #include <emulation/ndis/regcall.h>
47 #include <emulation/ndis/pe_var.h>
48
49 #include "inf.h"
50
51 static int insert_padding(void **, int *);
52 extern 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
83 static
84 int 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
157 static void
158 usage(void)
159 {
160         fprintf(stderr, "Usage: %s [-i <inffile>] -s <sysfile> "
161             "[-n devname] [-o outfile]\n", __progname);
162         exit(1);
163 }
164
165 int
166 main(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
282 done:
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 }