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 *);
62 *find_section (const char *);
63 static void dump_deviceids_pci (void);
64 static void dump_deviceids_pcmcia (void);
65 static void dump_deviceids_usb (void);
66 static void dump_pci_id (const char *);
67 static void dump_pcmcia_id (const char *);
68 static void dump_usb_id (const char *);
69 static void dump_regvals (void);
70 static void dump_paramreg (const struct section *,
71 const struct reg *, int);
76 inf_parse (FILE *fp, FILE *outfp)
87 dump_deviceids_pcmcia();
89 fprintf(outfp, "#ifdef NDIS_REGVALS\n");
91 fprintf(outfp, "#endif /* NDIS_REGVALS */\n");
97 section_add (const char *s)
101 sec = malloc(sizeof(struct section));
102 bzero(sec, sizeof(struct section));
104 TAILQ_INSERT_TAIL(&sh, sec, link);
109 static struct assign *
110 find_assign (const char *s, const char *k)
112 struct assign *assign;
115 /* Deal with string section lookups. */
117 if (k != NULL && k[0] == '%') {
118 bzero(newkey, sizeof(newkey));
119 strncpy(newkey, k + 1, strlen(k) - 2);
123 TAILQ_FOREACH(assign, &ah, link) {
124 if (strcasecmp(assign->section->name, s) == 0) {
128 if (strcasecmp(assign->key, k) == 0)
135 static struct assign *
136 find_next_assign (struct assign *a)
138 struct assign *assign;
140 TAILQ_FOREACH(assign, &ah, link) {
145 assign = assign->link.tqe_next;
147 if (assign == NULL || assign->section != a->section)
154 stringcvt(const char *s)
158 manf = find_assign("strings", s);
161 return(manf->vals[0]);
165 find_section (const char *s)
167 struct section *section;
169 TAILQ_FOREACH(section, &sh, link) {
170 if (strcasecmp(section->name, s) == 0)
177 dump_pcmcia_id(const char *s)
179 char *manstr, *devstr;
182 p0 = __DECONST(char *, s);
184 p = strchr(p0, '\\');
196 /* Convert any underscores to spaces. */
198 while (*p0 != '\0') {
212 /* Convert any underscores to spaces. */
214 while (*p0 != '\0') {
220 fprintf(ofp, "\t\\\n\t{ \"%s\", \"%s\", ", manstr, devstr);
225 dump_pci_id(const char *s)
228 char vidstr[7], didstr[7], subsysstr[14];
230 p = strcasestr(s, "VEN_");
234 strcpy(vidstr, "0x");
235 strncat(vidstr, p, 4);
236 p = strcasestr(s, "DEV_");
240 strcpy(didstr, "0x");
241 strncat(didstr, p, 4);
244 p = strcasestr(s, "SUBSYS_");
246 strcpy(subsysstr, "0x00000000");
249 strcpy(subsysstr, "0x");
250 strncat(subsysstr, p, 8);
253 fprintf(ofp, "\t\\\n\t{ %s, %s, %s, ", vidstr, didstr, subsysstr);
258 dump_usb_id(const char *s)
261 char vidstr[7], pidstr[7];
263 p = strcasestr(s, "VID_");
267 strcpy(vidstr, "0x");
268 strncat(vidstr, p, 4);
269 p = strcasestr(s, "PID_");
273 strcpy(pidstr, "0x");
274 strncat(pidstr, p, 4);
278 fprintf(ofp, "\t\\\n\t{ %s, %s, ", vidstr, pidstr);
284 struct assign *manf, *dev;
286 struct assign *assign;
288 int first = 1, found = 0;
290 /* Find manufacturer name */
291 manf = find_assign("Manufacturer", NULL);
295 /* Find manufacturer section */
296 if (manf->vals[1] != NULL &&
297 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
298 strcasecmp(manf->vals[1], "NTx86") == 0 ||
299 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
300 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
301 /* Handle Windows XP INF files. */
302 snprintf(xpsec, sizeof(xpsec), "%s.%s",
303 manf->vals[0], manf->vals[1]);
304 sec = find_section(xpsec);
306 sec = find_section(manf->vals[0]);
308 /* See if there are any PCI device definitions. */
310 TAILQ_FOREACH(assign, &ah, link) {
311 if (assign->section == sec) {
312 dev = find_assign("strings", assign->key);
313 if (strcasestr(assign->vals[1], "PCI") != NULL) {
326 /* Emit start of PCI device table */
327 fprintf (ofp, "#define NDIS_PCI_DEV_TABLE");
334 * Now run through all the device names listed
335 * in the manufacturer section and dump out the
336 * device descriptions and vendor/device IDs.
339 TAILQ_FOREACH(assign, &ah, link) {
340 if (assign->section == sec) {
341 dev = find_assign("strings", assign->key);
342 /* Emit device IDs. */
343 if (strcasestr(assign->vals[1], "PCI") != NULL)
344 dump_pci_id(assign->vals[1]);
347 /* Emit device description */
348 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
353 /* Someone tried to fool us. Shame on them. */
356 sec = find_section(manf->vals[0]);
360 /* Handle Manufacturer sections with multiple entries. */
361 manf = find_next_assign(manf);
367 /* Emit end of table */
369 fprintf(ofp, "\n\n");
375 dump_deviceids_pcmcia()
377 struct assign *manf, *dev;
379 struct assign *assign;
381 int first = 1, found = 0;
383 /* Find manufacturer name */
384 manf = find_assign("Manufacturer", NULL);
388 /* Find manufacturer section */
389 if (manf->vals[1] != NULL &&
390 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
391 strcasecmp(manf->vals[1], "NTx86") == 0 ||
392 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
393 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
394 /* Handle Windows XP INF files. */
395 snprintf(xpsec, sizeof(xpsec), "%s.%s",
396 manf->vals[0], manf->vals[1]);
397 sec = find_section(xpsec);
399 sec = find_section(manf->vals[0]);
401 /* See if there are any PCMCIA device definitions. */
403 TAILQ_FOREACH(assign, &ah, link) {
404 if (assign->section == sec) {
405 dev = find_assign("strings", assign->key);
406 if (strcasestr(assign->vals[1], "PCMCIA") != NULL) {
419 /* Emit start of PCMCIA device table */
420 fprintf (ofp, "#define NDIS_PCMCIA_DEV_TABLE");
427 * Now run through all the device names listed
428 * in the manufacturer section and dump out the
429 * device descriptions and vendor/device IDs.
432 TAILQ_FOREACH(assign, &ah, link) {
433 if (assign->section == sec) {
434 dev = find_assign("strings", assign->key);
435 /* Emit device IDs. */
436 if (strcasestr(assign->vals[1], "PCMCIA") != NULL)
437 dump_pcmcia_id(assign->vals[1]);
440 /* Emit device description */
441 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
446 /* Someone tried to fool us. Shame on them. */
449 sec = find_section(manf->vals[0]);
453 /* Handle Manufacturer sections with multiple entries. */
454 manf = find_next_assign(manf);
460 /* Emit end of table */
462 fprintf(ofp, "\n\n");
470 struct assign *manf, *dev;
472 struct assign *assign;
474 int first = 1, found = 0;
476 /* Find manufacturer name */
477 manf = find_assign("Manufacturer", NULL);
481 /* Find manufacturer section */
482 if (manf->vals[1] != NULL &&
483 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
484 strcasecmp(manf->vals[1], "NTx86") == 0 ||
485 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
486 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
487 /* Handle Windows XP INF files. */
488 snprintf(xpsec, sizeof(xpsec), "%s.%s",
489 manf->vals[0], manf->vals[1]);
490 sec = find_section(xpsec);
492 sec = find_section(manf->vals[0]);
494 /* See if there are any USB device definitions. */
496 TAILQ_FOREACH(assign, &ah, link) {
497 if (assign->section == sec) {
498 dev = find_assign("strings", assign->key);
499 if (strcasestr(assign->vals[1], "USB") != NULL) {
512 /* Emit start of USB device table */
513 fprintf (ofp, "#define NDIS_USB_DEV_TABLE");
520 * Now run through all the device names listed
521 * in the manufacturer section and dump out the
522 * device descriptions and vendor/device IDs.
525 TAILQ_FOREACH(assign, &ah, link) {
526 if (assign->section == sec) {
527 dev = find_assign("strings", assign->key);
528 /* Emit device IDs. */
529 if (strcasestr(assign->vals[1], "USB") != NULL)
530 dump_usb_id(assign->vals[1]);
533 /* Emit device description */
534 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
539 /* Someone tried to fool us. Shame on them. */
542 sec = find_section(manf->vals[0]);
546 /* Handle Manufacturer sections with multiple entries. */
547 manf = find_next_assign(manf);
553 /* Emit end of table */
555 fprintf(ofp, "\n\n");
561 dump_addreg(const char *s, int devidx)
566 /* Find the addreg section */
567 sec = find_section(s);
569 /* Dump all the keys defined in it. */
570 TAILQ_FOREACH(reg, &rh, link) {
572 * Keys with an empty subkey are very easy to parse,
573 * so just deal with them here. If a parameter key
574 * of the same name also exists, prefer that one and
577 if (reg->section == sec) {
578 if (reg->subkey == NULL) {
579 fprintf(ofp, "\n\t{ \"%s\",", reg->key);
580 fprintf(ofp,"\n\t\"%s \",", reg->key);
581 fprintf(ofp, "\n\t{ \"%s\" }, %d },",
582 reg->value == NULL ? "" :
583 stringcvt(reg->value), devidx);
584 } else if (strncasecmp(reg->subkey,
585 "Ndi\\params", strlen("Ndi\\params")-1) == 0 &&
586 (reg->key != NULL && strcasecmp(reg->key,
588 dump_paramreg(sec, reg, devidx);
596 dump_enumreg(const struct section *s, const struct reg *r)
601 sprintf(enumkey, "%s\\enum", r->subkey);
602 TAILQ_FOREACH(reg, &rh, link) {
603 if (reg->section != s)
605 if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey))
607 fprintf(ofp, " [%s=%s]", reg->key,
608 stringcvt(reg->value));
614 dump_editreg(const struct section *s, const struct reg *r)
618 TAILQ_FOREACH(reg, &rh, link) {
619 if (reg->section != s)
621 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
623 if (reg->key == NULL)
625 if (strcasecmp(reg->key, "LimitText") == 0)
626 fprintf(ofp, " [maxchars=%s]", reg->value);
627 if (strcasecmp(reg->key, "Optional") == 0 &&
628 strcmp(reg->value, "1") == 0)
629 fprintf(ofp, " [optional]");
634 /* Use this for int too */
636 dump_dwordreg(const struct section *s, const struct reg *r)
640 TAILQ_FOREACH(reg, &rh, link) {
641 if (reg->section != s)
643 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
645 if (reg->key == NULL)
647 if (strcasecmp(reg->key, "min") == 0)
648 fprintf(ofp, " [min=%s]", reg->value);
649 if (strcasecmp(reg->key, "max") == 0)
650 fprintf(ofp, " [max=%s]", reg->value);
656 dump_defaultinfo(const struct section *s, const struct reg *r, int devidx)
659 TAILQ_FOREACH(reg, &rh, link) {
660 if (reg->section != s)
662 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
664 if (reg->key == NULL || strcasecmp(reg->key, "Default"))
666 fprintf(ofp, "\n\t{ \"%s\" }, %d },", reg->value == NULL ? "" :
667 stringcvt(reg->value), devidx);
670 /* Default registry entry missing */
671 fprintf(ofp, "\n\t{ \"\" }, %d },", devidx);
676 dump_paramdesc(const struct section *s, const struct reg *r)
679 TAILQ_FOREACH(reg, &rh, link) {
680 if (reg->section != s)
682 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
684 if (reg->key == NULL || strcasecmp(reg->key, "ParamDesc"))
686 fprintf(ofp, "\n\t\"%s", stringcvt(r->value));
693 dump_typeinfo(const struct section *s, const struct reg *r)
696 TAILQ_FOREACH(reg, &rh, link) {
697 if (reg->section != s)
699 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
701 if (reg->key == NULL)
703 if (strcasecmp(reg->key, "type"))
705 if (strcasecmp(reg->value, "dword") == 0 ||
706 strcasecmp(reg->value, "int") == 0)
708 if (strcasecmp(reg->value, "enum") == 0)
710 if (strcasecmp(reg->value, "edit") == 0)
717 dump_paramreg(const struct section *s, const struct reg *r, int devidx)
721 keyname = r->subkey + strlen("Ndi\\params\\");
722 fprintf(ofp, "\n\t{ \"%s\",", keyname);
723 dump_paramdesc(s, r);
726 dump_defaultinfo(s, r, devidx);
734 struct assign *manf, *dev;
736 struct assign *assign;
738 int found = 0, i, is_winxp = 0, is_winnt = 0, devidx = 0;
740 /* Find signature to check for special case of WinNT. */
741 assign = find_assign("version", "signature");
742 if (strcasecmp(assign->vals[0], "$windows nt$") == 0)
745 /* Emit start of block */
746 fprintf (ofp, "ndis_cfg ndis_regvals[] = {");
748 /* Find manufacturer name */
749 manf = find_assign("Manufacturer", NULL);
753 /* Find manufacturer section */
754 if (manf->vals[1] != NULL &&
755 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
756 strcasecmp(manf->vals[1], "NTx86") == 0 ||
757 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
758 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
760 /* Handle Windows XP INF files. */
761 snprintf(sname, sizeof(sname), "%s.%s",
762 manf->vals[0], manf->vals[1]);
763 sec = find_section(sname);
765 sec = find_section(manf->vals[0]);
769 TAILQ_FOREACH(assign, &ah, link) {
770 if (assign->section == sec) {
773 * Find all the AddReg sections.
774 * Look for section names with .NT, unless
775 * this is a WinXP .INF file.
779 sprintf(sname, "%s.NTx86", assign->vals[0]);
780 dev = find_assign(sname, "AddReg");
782 sprintf(sname, "%s.NT",
784 dev = find_assign(sname, "AddReg");
787 dev = find_assign(assign->vals[0],
790 sprintf(sname, "%s.NT", assign->vals[0]);
791 dev = find_assign(sname, "AddReg");
792 if (dev == NULL && is_winnt)
793 dev = find_assign(assign->vals[0],
796 /* Section not found. */
799 for (i = 0; i < W_MAX; i++) {
800 if (dev->vals[i] != NULL)
801 dump_addreg(dev->vals[i], devidx);
808 sec = find_section(manf->vals[0]);
814 manf = find_next_assign(manf);
819 fprintf(ofp, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
825 assign_add (const char *a)
827 struct assign *assign;
830 assign = malloc(sizeof(struct assign));
831 bzero(assign, sizeof(struct assign));
832 assign->section = TAILQ_LAST(&sh, section_head);
833 assign->key = sstrdup(a);
834 for (i = 0; i < idx; i++)
835 assign->vals[(idx - 1) - i] = sstrdup(words[i]);
836 TAILQ_INSERT_TAIL(&ah, assign, link);
843 define_add (const char *d __unused)
846 fprintf(stderr, "define \"%s\"\n", d);
852 sstrdup(const char *str)
854 if (str != NULL && strlen(str))
855 return (strdup(str));
860 satoi (const char *nptr)
862 if (nptr != NULL && strlen(nptr))
868 regkey_add (const char *r)
872 reg = malloc(sizeof(struct reg));
873 bzero(reg, sizeof(struct reg));
874 reg->section = TAILQ_LAST(&sh, section_head);
875 reg->root = sstrdup(r);
876 reg->subkey = sstrdup(words[3]);
877 reg->key = sstrdup(words[2]);
878 reg->flags = satoi(words[1]);
879 reg->value = sstrdup(words[0]);
880 TAILQ_INSERT_TAIL(&rh, reg, link);
882 free(__DECONST(char *, r));
888 push_word (const char *w)
892 fprintf(stderr, "too many words; try bumping W_MAX in inf.h\n");
908 for (i = 0; i < idx; i++) {
910 free(__DECONST(char *, words[i]));
914 bzero(words, sizeof(words));