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.
32 * $FreeBSD: src/usr.sbin/ndiscvt/inf.c,v 1.19 2008/12/27 08:03:32 weongyo Exp $
38 #include <sys/types.h>
40 #include <sys/queue.h>
47 const char *words
[W_MAX
]; /* More than we'll need. */
50 static struct section_head sh
;
51 static struct reg_head rh
;
52 static struct assign_head ah
;
54 static char *sstrdup (const char *);
56 *find_assign (const char *, const char *);
61 *find_section (const char *);
62 static void dump_deviceids_pci (void);
63 static void dump_deviceids_pcmcia (void);
64 static void dump_deviceids_usb (void);
65 static void dump_pci_id (const char *);
66 static void dump_pcmcia_id (const char *);
67 static void dump_usb_id (const char *);
68 static void dump_regvals (void);
69 static void dump_paramreg (const struct section
*,
70 const struct reg
*, int);
75 inf_parse(FILE *fp
, FILE *outfp
)
86 dump_deviceids_pcmcia();
88 fprintf(outfp
, "#ifdef NDIS_REGVALS\n");
90 fprintf(outfp
, "#endif /* NDIS_REGVALS */\n");
96 section_add(const char *s
)
100 sec
= malloc(sizeof(struct section
));
101 bzero(sec
, sizeof(struct section
));
103 TAILQ_INSERT_TAIL(&sh
, sec
, link
);
108 static struct assign
*
109 find_assign(const char *s
, const char *k
)
111 struct assign
*assign
;
114 /* Deal with string section lookups. */
116 if (k
!= NULL
&& k
[0] == '%') {
117 bzero(newkey
, sizeof(newkey
));
118 strncpy(newkey
, k
+ 1, strlen(k
) - 2);
122 TAILQ_FOREACH(assign
, &ah
, link
) {
123 if (strcasecmp(assign
->section
->name
, s
) == 0) {
127 if (strcasecmp(assign
->key
, k
) == 0)
134 static struct assign
*
135 find_next_assign(struct assign
*a
)
137 struct assign
*assign
;
139 TAILQ_FOREACH(assign
, &ah
, link
) {
144 assign
= assign
->link
.tqe_next
;
146 if (assign
== NULL
|| assign
->section
!= a
->section
)
153 stringcvt(const char *s
)
157 manf
= find_assign("strings", s
);
160 return(manf
->vals
[0]);
164 find_section(const char *s
)
166 struct section
*section
;
168 TAILQ_FOREACH(section
, &sh
, link
) {
169 if (strcasecmp(section
->name
, s
) == 0)
176 dump_pcmcia_id(const char *s
)
178 char *manstr
, *devstr
;
181 p0
= __DECONST(char *, s
);
183 p
= strchr(p0
, '\\');
195 /* Convert any underscores to spaces. */
197 while (*p0
!= '\0') {
211 /* Convert any underscores to spaces. */
213 while (*p0
!= '\0') {
219 fprintf(ofp
, "\t\\\n\t{ \"%s\", \"%s\", ", manstr
, devstr
);
224 dump_pci_id(const char *s
)
227 char vidstr
[7], didstr
[7], subsysstr
[14];
229 p
= strcasestr(s
, "VEN_");
233 strcpy(vidstr
, "0x");
234 strncat(vidstr
, p
, 4);
235 p
= strcasestr(s
, "DEV_");
239 strcpy(didstr
, "0x");
240 strncat(didstr
, p
, 4);
243 p
= strcasestr(s
, "SUBSYS_");
245 strcpy(subsysstr
, "0x00000000");
248 strcpy(subsysstr
, "0x");
249 strncat(subsysstr
, p
, 8);
252 fprintf(ofp
, "\t\\\n\t{ %s, %s, %s, ", vidstr
, didstr
, subsysstr
);
257 dump_usb_id(const char *s
)
260 char vidstr
[7], pidstr
[7];
262 p
= strcasestr(s
, "VID_");
266 strcpy(vidstr
, "0x");
267 strncat(vidstr
, p
, 4);
268 p
= strcasestr(s
, "PID_");
272 strcpy(pidstr
, "0x");
273 strncat(pidstr
, p
, 4);
277 fprintf(ofp
, "\t\\\n\t{ %s, %s, ", vidstr
, pidstr
);
281 dump_deviceids_pci(void)
283 struct assign
*manf
, *dev
;
285 struct assign
*assign
;
287 int first
= 1, found
= 0;
289 /* Find manufacturer name */
290 manf
= find_assign("Manufacturer", NULL
);
294 /* Find manufacturer section */
295 if (manf
->vals
[1] != NULL
&&
296 (strcasecmp(manf
->vals
[1], "NT.5.1") == 0 ||
297 strcasecmp(manf
->vals
[1], "NTx86") == 0 ||
298 strcasecmp(manf
->vals
[1], "NTx86.5.1") == 0 ||
299 strcasecmp(manf
->vals
[1], "NTamd64") == 0)) {
300 /* Handle Windows XP INF files. */
301 snprintf(xpsec
, sizeof(xpsec
), "%s.%s",
302 manf
->vals
[0], manf
->vals
[1]);
303 sec
= find_section(xpsec
);
305 sec
= find_section(manf
->vals
[0]);
307 /* See if there are any PCI device definitions. */
309 TAILQ_FOREACH(assign
, &ah
, link
) {
310 if (assign
->section
== sec
) {
311 dev
= find_assign("strings", assign
->key
);
312 if (strcasestr(assign
->vals
[1], "PCI") != NULL
) {
325 /* Emit start of PCI device table */
326 fprintf (ofp
, "#define NDIS_PCI_DEV_TABLE");
333 * Now run through all the device names listed
334 * in the manufacturer section and dump out the
335 * device descriptions and vendor/device IDs.
338 TAILQ_FOREACH(assign
, &ah
, link
) {
339 if (assign
->section
== sec
) {
340 dev
= find_assign("strings", assign
->key
);
341 /* Emit device IDs. */
342 if (strcasestr(assign
->vals
[1], "PCI") != NULL
)
343 dump_pci_id(assign
->vals
[1]);
346 /* Emit device description */
347 fprintf (ofp
, "\t\\\n\t\"%s\" },", dev
->vals
[0]);
352 /* Someone tried to fool us. Shame on them. */
355 sec
= find_section(manf
->vals
[0]);
359 /* Handle Manufacturer sections with multiple entries. */
360 manf
= find_next_assign(manf
);
366 /* Emit end of table */
368 fprintf(ofp
, "\n\n");
374 dump_deviceids_pcmcia(void)
376 struct assign
*manf
, *dev
;
378 struct assign
*assign
;
380 int first
= 1, found
= 0;
382 /* Find manufacturer name */
383 manf
= find_assign("Manufacturer", NULL
);
387 /* Find manufacturer section */
388 if (manf
->vals
[1] != NULL
&&
389 (strcasecmp(manf
->vals
[1], "NT.5.1") == 0 ||
390 strcasecmp(manf
->vals
[1], "NTx86") == 0 ||
391 strcasecmp(manf
->vals
[1], "NTx86.5.1") == 0 ||
392 strcasecmp(manf
->vals
[1], "NTamd64") == 0)) {
393 /* Handle Windows XP INF files. */
394 snprintf(xpsec
, sizeof(xpsec
), "%s.%s",
395 manf
->vals
[0], manf
->vals
[1]);
396 sec
= find_section(xpsec
);
398 sec
= find_section(manf
->vals
[0]);
400 /* See if there are any PCMCIA device definitions. */
402 TAILQ_FOREACH(assign
, &ah
, link
) {
403 if (assign
->section
== sec
) {
404 dev
= find_assign("strings", assign
->key
);
405 if (strcasestr(assign
->vals
[1], "PCMCIA") != NULL
) {
418 /* Emit start of PCMCIA device table */
419 fprintf (ofp
, "#define NDIS_PCMCIA_DEV_TABLE");
426 * Now run through all the device names listed
427 * in the manufacturer section and dump out the
428 * device descriptions and vendor/device IDs.
431 TAILQ_FOREACH(assign
, &ah
, link
) {
432 if (assign
->section
== sec
) {
433 dev
= find_assign("strings", assign
->key
);
434 /* Emit device IDs. */
435 if (strcasestr(assign
->vals
[1], "PCMCIA") != NULL
)
436 dump_pcmcia_id(assign
->vals
[1]);
439 /* Emit device description */
440 fprintf (ofp
, "\t\\\n\t\"%s\" },", dev
->vals
[0]);
445 /* Someone tried to fool us. Shame on them. */
448 sec
= find_section(manf
->vals
[0]);
452 /* Handle Manufacturer sections with multiple entries. */
453 manf
= find_next_assign(manf
);
459 /* Emit end of table */
461 fprintf(ofp
, "\n\n");
467 dump_deviceids_usb(void)
469 struct assign
*manf
, *dev
;
471 struct assign
*assign
;
473 int first
= 1, found
= 0;
475 /* Find manufacturer name */
476 manf
= find_assign("Manufacturer", NULL
);
480 /* Find manufacturer section */
481 if (manf
->vals
[1] != NULL
&&
482 (strcasecmp(manf
->vals
[1], "NT.5.1") == 0 ||
483 strcasecmp(manf
->vals
[1], "NTx86") == 0 ||
484 strcasecmp(manf
->vals
[1], "NTx86.5.1") == 0 ||
485 strcasecmp(manf
->vals
[1], "NTamd64") == 0)) {
486 /* Handle Windows XP INF files. */
487 snprintf(xpsec
, sizeof(xpsec
), "%s.%s",
488 manf
->vals
[0], manf
->vals
[1]);
489 sec
= find_section(xpsec
);
491 sec
= find_section(manf
->vals
[0]);
493 /* See if there are any USB device definitions. */
495 TAILQ_FOREACH(assign
, &ah
, link
) {
496 if (assign
->section
== sec
) {
497 dev
= find_assign("strings", assign
->key
);
498 if (strcasestr(assign
->vals
[1], "USB") != NULL
) {
511 /* Emit start of USB device table */
512 fprintf (ofp
, "#define NDIS_USB_DEV_TABLE");
519 * Now run through all the device names listed
520 * in the manufacturer section and dump out the
521 * device descriptions and vendor/device IDs.
524 TAILQ_FOREACH(assign
, &ah
, link
) {
525 if (assign
->section
== sec
) {
526 dev
= find_assign("strings", assign
->key
);
527 /* Emit device IDs. */
528 if (strcasestr(assign
->vals
[1], "USB") != NULL
)
529 dump_usb_id(assign
->vals
[1]);
532 /* Emit device description */
533 fprintf (ofp
, "\t\\\n\t\"%s\" },", dev
->vals
[0]);
538 /* Someone tried to fool us. Shame on them. */
541 sec
= find_section(manf
->vals
[0]);
545 /* Handle Manufacturer sections with multiple entries. */
546 manf
= find_next_assign(manf
);
552 /* Emit end of table */
554 fprintf(ofp
, "\n\n");
560 dump_addreg(const char *s
, int devidx
)
565 /* Find the addreg section */
566 sec
= find_section(s
);
568 /* Dump all the keys defined in it. */
569 TAILQ_FOREACH(reg
, &rh
, link
) {
571 * Keys with an empty subkey are very easy to parse,
572 * so just deal with them here. If a parameter key
573 * of the same name also exists, prefer that one and
576 if (reg
->section
== sec
) {
577 if (reg
->subkey
== NULL
) {
578 fprintf(ofp
, "\n\t{ \"%s\",", reg
->key
);
579 fprintf(ofp
,"\n\t\"%s \",", reg
->key
);
580 fprintf(ofp
, "\n\t{ \"%s\" }, %d },",
581 reg
->value
== NULL
? "" :
582 stringcvt(reg
->value
), devidx
);
583 } else if (strncasecmp(reg
->subkey
,
584 "Ndi\\params", strlen("Ndi\\params")-1) == 0 &&
585 (reg
->key
!= NULL
&& strcasecmp(reg
->key
,
587 dump_paramreg(sec
, reg
, devidx
);
595 dump_enumreg(const struct section
*s
, const struct reg
*r
)
600 sprintf(enumkey
, "%s\\enum", r
->subkey
);
601 TAILQ_FOREACH(reg
, &rh
, link
) {
602 if (reg
->section
!= s
)
604 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, enumkey
))
606 fprintf(ofp
, " [%s=%s]", reg
->key
,
607 stringcvt(reg
->value
));
613 dump_editreg(const struct section
*s
, const struct reg
*r
)
617 TAILQ_FOREACH(reg
, &rh
, link
) {
618 if (reg
->section
!= s
)
620 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
622 if (reg
->key
== NULL
)
624 if (strcasecmp(reg
->key
, "LimitText") == 0)
625 fprintf(ofp
, " [maxchars=%s]", reg
->value
);
626 if (strcasecmp(reg
->key
, "Optional") == 0 &&
627 strcmp(reg
->value
, "1") == 0)
628 fprintf(ofp
, " [optional]");
633 /* Use this for int too */
635 dump_dwordreg(const struct section
*s
, const struct reg
*r
)
639 TAILQ_FOREACH(reg
, &rh
, link
) {
640 if (reg
->section
!= s
)
642 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
644 if (reg
->key
== NULL
)
646 if (strcasecmp(reg
->key
, "min") == 0)
647 fprintf(ofp
, " [min=%s]", reg
->value
);
648 if (strcasecmp(reg
->key
, "max") == 0)
649 fprintf(ofp
, " [max=%s]", reg
->value
);
655 dump_defaultinfo(const struct section
*s
, const struct reg
*r
, int devidx
)
658 TAILQ_FOREACH(reg
, &rh
, link
) {
659 if (reg
->section
!= s
)
661 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
663 if (reg
->key
== NULL
|| strcasecmp(reg
->key
, "Default"))
665 fprintf(ofp
, "\n\t{ \"%s\" }, %d },", reg
->value
== NULL
? "" :
666 stringcvt(reg
->value
), devidx
);
669 /* Default registry entry missing */
670 fprintf(ofp
, "\n\t{ \"\" }, %d },", devidx
);
675 dump_paramdesc(const struct section
*s
, const struct reg
*r
)
678 TAILQ_FOREACH(reg
, &rh
, link
) {
679 if (reg
->section
!= s
)
681 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
683 if (reg
->key
== NULL
|| strcasecmp(reg
->key
, "ParamDesc"))
685 fprintf(ofp
, "\n\t\"%s", stringcvt(r
->value
));
692 dump_typeinfo(const struct section
*s
, const struct reg
*r
)
695 TAILQ_FOREACH(reg
, &rh
, link
) {
696 if (reg
->section
!= s
)
698 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
700 if (reg
->key
== NULL
)
702 if (strcasecmp(reg
->key
, "type"))
704 if (strcasecmp(reg
->value
, "dword") == 0 ||
705 strcasecmp(reg
->value
, "int") == 0)
707 if (strcasecmp(reg
->value
, "enum") == 0)
709 if (strcasecmp(reg
->value
, "edit") == 0)
716 dump_paramreg(const struct section
*s
, const struct reg
*r
, int devidx
)
720 keyname
= r
->subkey
+ strlen("Ndi\\params\\");
721 fprintf(ofp
, "\n\t{ \"%s\",", keyname
);
722 dump_paramdesc(s
, r
);
725 dump_defaultinfo(s
, r
, devidx
);
733 struct assign
*manf
, *dev
;
735 struct assign
*assign
;
737 int found
= 0, i
, is_winxp
= 0, is_winnt
= 0, devidx
= 0;
739 /* Find signature to check for special case of WinNT. */
740 assign
= find_assign("version", "signature");
741 if (strcasecmp(assign
->vals
[0], "$windows nt$") == 0)
744 /* Emit start of block */
745 fprintf (ofp
, "ndis_cfg ndis_regvals[] = {");
747 /* Find manufacturer name */
748 manf
= find_assign("Manufacturer", NULL
);
752 /* Find manufacturer section */
753 if (manf
->vals
[1] != NULL
&&
754 (strcasecmp(manf
->vals
[1], "NT.5.1") == 0 ||
755 strcasecmp(manf
->vals
[1], "NTx86") == 0 ||
756 strcasecmp(manf
->vals
[1], "NTx86.5.1") == 0 ||
757 strcasecmp(manf
->vals
[1], "NTamd64") == 0)) {
759 /* Handle Windows XP INF files. */
760 snprintf(sname
, sizeof(sname
), "%s.%s",
761 manf
->vals
[0], manf
->vals
[1]);
762 sec
= find_section(sname
);
764 sec
= find_section(manf
->vals
[0]);
768 TAILQ_FOREACH(assign
, &ah
, link
) {
769 if (assign
->section
== sec
) {
772 * Find all the AddReg sections.
773 * Look for section names with .NT, unless
774 * this is a WinXP .INF file.
778 sprintf(sname
, "%s.NTx86", assign
->vals
[0]);
779 dev
= find_assign(sname
, "AddReg");
781 sprintf(sname
, "%s.NT",
783 dev
= find_assign(sname
, "AddReg");
786 dev
= find_assign(assign
->vals
[0],
789 sprintf(sname
, "%s.NT", assign
->vals
[0]);
790 dev
= find_assign(sname
, "AddReg");
791 if (dev
== NULL
&& is_winnt
)
792 dev
= find_assign(assign
->vals
[0],
795 /* Section not found. */
798 for (i
= 0; i
< W_MAX
; i
++) {
799 if (dev
->vals
[i
] != NULL
)
800 dump_addreg(dev
->vals
[i
], devidx
);
807 sec
= find_section(manf
->vals
[0]);
813 manf
= find_next_assign(manf
);
818 fprintf(ofp
, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
824 assign_add(const char *a
)
826 struct assign
*assign
;
829 assign
= malloc(sizeof(struct assign
));
830 bzero(assign
, sizeof(struct assign
));
831 assign
->section
= TAILQ_LAST(&sh
, section_head
);
832 assign
->key
= sstrdup(a
);
833 for (i
= 0; i
< idx
; i
++)
834 assign
->vals
[(idx
- 1) - i
] = sstrdup(words
[i
]);
835 TAILQ_INSERT_TAIL(&ah
, assign
, link
);
842 define_add(const char *d __unused
)
845 fprintf(stderr
, "define \"%s\"\n", d
);
851 sstrdup(const char *str
)
853 if (str
!= NULL
&& strlen(str
))
854 return (strdup(str
));
859 satoi(const char *nptr
)
861 if (nptr
!= NULL
&& strlen(nptr
))
867 regkey_add(const char *r
)
871 reg
= malloc(sizeof(struct reg
));
872 bzero(reg
, sizeof(struct reg
));
873 reg
->section
= TAILQ_LAST(&sh
, section_head
);
874 reg
->root
= sstrdup(r
);
875 reg
->subkey
= sstrdup(words
[3]);
876 reg
->key
= sstrdup(words
[2]);
877 reg
->flags
= satoi(words
[1]);
878 reg
->value
= sstrdup(words
[0]);
879 TAILQ_INSERT_TAIL(&rh
, reg
, link
);
881 free(__DECONST(char *, r
));
887 push_word(const char *w
)
901 for (i
= 0; i
< idx
; i
++) {
903 free(__DECONST(char *, words
[i
]));
907 bzero(words
, sizeof(words
));