3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
39 #include <sys/types.h>
41 #include <sys/queue.h>
48 const char *words[W_MAX]; /* More than we'll need. */
51 static struct section_head sh;
52 static struct reg_head rh;
53 static struct assign_head ah;
55 static char *sstrdup (const char *);
57 *find_assign (const char *, const char *);
59 *find_section (const char *);
60 static void dump_deviceids_pci (void);
61 static void dump_deviceids_pcmcia (void);
62 static void dump_pci_id (const char *);
63 static void dump_pcmcia_id (const char *);
64 static void dump_regvals (void);
65 static void dump_paramreg (const struct section *,
66 const struct reg *, int);
71 inf_parse (FILE *fp, FILE *outfp)
82 dump_deviceids_pcmcia();
83 fprintf(outfp, "#ifdef NDIS_REGVALS\n");
85 fprintf(outfp, "#endif /* NDIS_REGVALS */\n");
91 section_add (const char *s)
95 sec = malloc(sizeof(struct section));
96 bzero(sec, sizeof(struct section));
98 TAILQ_INSERT_TAIL(&sh, sec, link);
103 static struct assign *
104 find_assign (const char *s, const char *k)
106 struct assign *assign;
109 /* Deal with string section lookups. */
111 if (k != NULL && k[0] == '%') {
112 bzero(newkey, sizeof(newkey));
113 strncpy(newkey, k + 1, strlen(k) - 2);
117 TAILQ_FOREACH(assign, &ah, link) {
118 if (strcasecmp(assign->section->name, s) == 0) {
122 if (strcasecmp(assign->key, k) == 0)
130 stringcvt(const char *s)
134 manf = find_assign("strings", s);
137 return(manf->vals[0]);
141 find_section (const char *s)
143 struct section *section;
145 TAILQ_FOREACH(section, &sh, link) {
146 if (strcasecmp(section->name, s) == 0)
153 dump_pcmcia_id(const char *s)
155 char *manstr, *devstr;
158 p0 = __DECONST(char *, s);
160 p = strchr(p0, '\\');
172 /* Convert any underscores to spaces. */
174 while (*p0 != '\0') {
188 /* Convert any underscores to spaces. */
190 while (*p0 != '\0') {
196 fprintf(ofp, "\t\\\n\t{ \"%s\", \"%s\", ", manstr, devstr);
201 dump_pci_id(const char *s)
204 char vidstr[7], didstr[7], subsysstr[14];
206 p = strcasestr(s, "VEN_");
210 strcpy(vidstr, "0x");
211 strncat(vidstr, p, 4);
212 p = strcasestr(s, "DEV_");
216 strcpy(didstr, "0x");
217 strncat(didstr, p, 4);
220 p = strcasestr(s, "SUBSYS_");
222 strcpy(subsysstr, "0x00000000");
225 strcpy(subsysstr, "0x");
226 strncat(subsysstr, p, 8);
229 fprintf(ofp, "\t\\\n\t{ %s, %s, %s, ", vidstr, didstr, subsysstr);
236 struct assign *manf, *dev;
238 struct assign *assign;
242 /* Find manufacturer name */
243 manf = find_assign("Manufacturer", NULL);
245 /* Find manufacturer section */
246 if (manf->vals[1] != NULL &&
247 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
248 strcasecmp(manf->vals[1], "NTx86") == 0 ||
249 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
250 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
251 /* Handle Windows XP INF files. */
252 snprintf(xpsec, sizeof(xpsec), "%s.%s",
253 manf->vals[0], manf->vals[1]);
254 sec = find_section(xpsec);
256 sec = find_section(manf->vals[0]);
258 /* See if there are any PCI device definitions. */
260 TAILQ_FOREACH(assign, &ah, link) {
261 if (assign->section == sec) {
262 dev = find_assign("strings", assign->key);
263 if (strcasestr(assign->vals[1], "PCI") != NULL) {
275 /* Emit start of PCI device table */
276 fprintf (ofp, "#define NDIS_PCI_DEV_TABLE");
281 * Now run through all the device names listed
282 * in the manufacturer section and dump out the
283 * device descriptions and vendor/device IDs.
286 TAILQ_FOREACH(assign, &ah, link) {
287 if (assign->section == sec) {
288 dev = find_assign("strings", assign->key);
289 /* Emit device IDs. */
290 if (strcasestr(assign->vals[1], "PCI") != NULL)
291 dump_pci_id(assign->vals[1]);
294 /* Emit device description */
295 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
300 /* Someone tried to fool us. Shame on them. */
303 sec = find_section(manf->vals[0]);
307 /* Emit end of table */
309 fprintf(ofp, "\n\n");
314 dump_deviceids_pcmcia()
316 struct assign *manf, *dev;
318 struct assign *assign;
322 /* Find manufacturer name */
323 manf = find_assign("Manufacturer", NULL);
325 /* Find manufacturer section */
326 if (manf->vals[1] != NULL &&
327 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
328 strcasecmp(manf->vals[1], "NTx86") == 0 ||
329 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
330 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
331 /* Handle Windows XP INF files. */
332 snprintf(xpsec, sizeof(xpsec), "%s.%s",
333 manf->vals[0], manf->vals[1]);
334 sec = find_section(xpsec);
336 sec = find_section(manf->vals[0]);
338 /* See if there are any PCMCIA device definitions. */
340 TAILQ_FOREACH(assign, &ah, link) {
341 if (assign->section == sec) {
342 dev = find_assign("strings", assign->key);
343 if (strcasestr(assign->vals[1], "PCMCIA") != NULL) {
355 /* Emit start of PCMCIA device table */
356 fprintf (ofp, "#define NDIS_PCMCIA_DEV_TABLE");
361 * Now run through all the device names listed
362 * in the manufacturer section and dump out the
363 * device descriptions and vendor/device IDs.
366 TAILQ_FOREACH(assign, &ah, link) {
367 if (assign->section == sec) {
368 dev = find_assign("strings", assign->key);
369 /* Emit device IDs. */
370 if (strcasestr(assign->vals[1], "PCMCIA") != NULL)
371 dump_pcmcia_id(assign->vals[1]);
374 /* Emit device description */
375 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
380 /* Someone tried to fool us. Shame on them. */
383 sec = find_section(manf->vals[0]);
387 /* Emit end of table */
389 fprintf(ofp, "\n\n");
394 dump_addreg(const char *s, int devidx)
399 /* Find the addreg section */
400 sec = find_section(s);
402 /* Dump all the keys defined in it. */
403 TAILQ_FOREACH(reg, &rh, link) {
405 * Keys with an empty subkey are very easy to parse,
406 * so just deal with them here. If a parameter key
407 * of the same name also exists, prefer that one and
410 if (reg->section == sec) {
411 if (reg->subkey == NULL) {
412 fprintf(ofp, "\n\t{ \"%s\",", reg->key);
413 fprintf(ofp,"\n\t\"%s \",", reg->key);
414 fprintf(ofp, "\n\t{ \"%s\" }, %d },",
415 reg->value == NULL ? "" :
416 stringcvt(reg->value), devidx);
417 } else if (strncasecmp(reg->subkey,
418 "Ndi\\params", strlen("Ndi\\params")-1) == 0 &&
419 (reg->key != NULL && strcasecmp(reg->key,
421 dump_paramreg(sec, reg, devidx);
429 dump_enumreg(const struct section *s, const struct reg *r)
434 sprintf(enumkey, "%s\\enum", r->subkey);
435 TAILQ_FOREACH(reg, &rh, link) {
436 if (reg->section != s)
438 if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey))
440 fprintf(ofp, " [%s=%s]", reg->key,
441 stringcvt(reg->value));
447 dump_editreg(const struct section *s, const struct reg *r)
451 TAILQ_FOREACH(reg, &rh, link) {
452 if (reg->section != s)
454 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
456 if (reg->key == NULL)
458 if (strcasecmp(reg->key, "LimitText") == 0)
459 fprintf(ofp, " [maxchars=%s]", reg->value);
460 if (strcasecmp(reg->key, "Optional") == 0 &&
461 strcmp(reg->value, "1") == 0)
462 fprintf(ofp, " [optional]");
467 /* Use this for int too */
469 dump_dwordreg(const struct section *s, const struct reg *r)
473 TAILQ_FOREACH(reg, &rh, link) {
474 if (reg->section != s)
476 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
478 if (reg->key == NULL)
480 if (strcasecmp(reg->key, "min") == 0)
481 fprintf(ofp, " [min=%s]", reg->value);
482 if (strcasecmp(reg->key, "max") == 0)
483 fprintf(ofp, " [max=%s]", reg->value);
489 dump_defaultinfo(const struct section *s, const struct reg *r, int devidx)
492 TAILQ_FOREACH(reg, &rh, link) {
493 if (reg->section != s)
495 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
497 if (reg->key == NULL || strcasecmp(reg->key, "Default"))
499 fprintf(ofp, "\n\t{ \"%s\" }, %d },", reg->value == NULL ? "" :
500 stringcvt(reg->value), devidx);
507 dump_paramdesc(const struct section *s, const struct reg *r)
510 TAILQ_FOREACH(reg, &rh, link) {
511 if (reg->section != s)
513 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
515 if (reg->key == NULL || strcasecmp(reg->key, "ParamDesc"))
517 fprintf(ofp, "\n\t\"%s", stringcvt(r->value));
524 dump_typeinfo(const struct section *s, const struct reg *r)
527 TAILQ_FOREACH(reg, &rh, link) {
528 if (reg->section != s)
530 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
532 if (reg->key == NULL)
534 if (strcasecmp(reg->key, "type"))
536 if (strcasecmp(reg->value, "dword") == 0 ||
537 strcasecmp(reg->value, "int") == 0)
539 if (strcasecmp(reg->value, "enum") == 0)
541 if (strcasecmp(reg->value, "edit") == 0)
548 dump_paramreg(const struct section *s, const struct reg *r, int devidx)
552 keyname = r->subkey + strlen("Ndi\\params\\");
553 fprintf(ofp, "\n\t{ \"%s\",", keyname);
554 dump_paramdesc(s, r);
557 dump_defaultinfo(s, r, devidx);
565 struct assign *manf, *dev;
567 struct assign *assign;
569 int found = 0, i, is_winxp = 0, is_winnt = 0, devidx = 0;
571 /* Find signature to check for special case of WinNT. */
572 assign = find_assign("version", "signature");
573 if (strcasecmp(assign->vals[0], "$windows nt$") == 0)
576 /* Find manufacturer name */
577 manf = find_assign("Manufacturer", NULL);
579 /* Find manufacturer section */
580 if (manf->vals[1] != NULL &&
581 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
582 strcasecmp(manf->vals[1], "NTx86") == 0 ||
583 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
584 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
586 /* Handle Windows XP INF files. */
587 snprintf(sname, sizeof(sname), "%s.%s",
588 manf->vals[0], manf->vals[1]);
589 sec = find_section(sname);
591 sec = find_section(manf->vals[0]);
593 /* Emit start of block */
594 fprintf (ofp, "ndis_cfg ndis_regvals[] = {");
598 TAILQ_FOREACH(assign, &ah, link) {
599 if (assign->section == sec) {
602 * Find all the AddReg sections.
603 * Look for section names with .NT, unless
604 * this is a WinXP .INF file.
608 sprintf(sname, "%s.NTx86", assign->vals[0]);
609 dev = find_assign(sname, "AddReg");
611 sprintf(sname, "%s.NT",
613 dev = find_assign(sname, "AddReg");
616 dev = find_assign(assign->vals[0],
619 sprintf(sname, "%s.NT", assign->vals[0]);
620 dev = find_assign(sname, "AddReg");
621 if (dev == NULL && is_winnt)
622 dev = find_assign(assign->vals[0],
625 /* Section not found. */
628 for (i = 0; i < W_MAX; i++) {
629 if (dev->vals[i] != NULL)
630 dump_addreg(dev->vals[i], devidx);
637 sec = find_section(manf->vals[0]);
643 fprintf(ofp, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
649 assign_add (const char *a)
651 struct assign *assign;
654 assign = malloc(sizeof(struct assign));
655 bzero(assign, sizeof(struct assign));
656 assign->section = TAILQ_LAST(&sh, section_head);
657 assign->key = sstrdup(a);
658 for (i = 0; i < idx; i++)
659 assign->vals[(idx - 1) - i] = sstrdup(words[i]);
660 TAILQ_INSERT_TAIL(&ah, assign, link);
667 define_add (const char *d __unused)
670 fprintf(stderr, "define \"%s\"\n", d);
676 sstrdup(const char *str)
678 if (str != NULL && strlen(str))
679 return (strdup(str));
684 satoi (const char *nptr)
686 if (nptr != NULL && strlen(nptr))
692 regkey_add (const char *r)
696 reg = malloc(sizeof(struct reg));
697 bzero(reg, sizeof(struct reg));
698 reg->section = TAILQ_LAST(&sh, section_head);
699 reg->root = sstrdup(r);
700 reg->subkey = sstrdup(words[3]);
701 reg->key = sstrdup(words[2]);
702 reg->flags = satoi(words[1]);
703 reg->value = sstrdup(words[0]);
704 TAILQ_INSERT_TAIL(&rh, reg, link);
706 free(__DECONST(char *, r));
712 push_word (const char *w)
726 for (i = 0; i < idx; i++) {
728 free(__DECONST(char *, words[i]));
732 bzero(words, sizeof(words));