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>
35 __FBSDID("$FreeBSD: src/usr.sbin/ndiscvt/inf.c,v 1.13.2.1 2005/02/18 16:30:10 wpaul Exp $");
38 __RCSID("$NetBSD: inf.c,v 1.3 2006/04/18 16:49:19 rittera Exp $");
45 #include <sys/types.h>
47 #include <sys/stdint.h>
50 #include <sys/queue.h>
55 #define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
59 extern FILE *ndiscvt_in
;
60 int ndiscvt_parse (void);
62 const char *words
[W_MAX
]; /* More than we'll need. */
65 static struct section_head sh
;
66 static struct reg_head rh
;
67 static struct assign_head ah
;
69 static char *sstrdup (const char *);
71 *find_assign (const char *, const char *);
73 *find_section (const char *);
74 static void dump_deviceids_pci (void);
75 static void dump_deviceids_pcmcia (void);
76 static void dump_pci_id (const char *);
77 static void dump_pcmcia_id (const char *);
78 static void dump_regvals (void);
79 static void dump_paramreg (const struct section
*,
80 const struct reg
*, int);
85 inf_parse (FILE *fp
, FILE *outfp
)
96 dump_deviceids_pcmcia();
97 fprintf(outfp
, "#ifdef NDIS_REGVALS\n");
99 fprintf(outfp
, "#endif /* NDIS_REGVALS */\n");
105 section_add (const char *s
)
109 sec
= malloc(sizeof(struct section
));
110 bzero(sec
, sizeof(struct section
));
112 TAILQ_INSERT_TAIL(&sh
, sec
, link
);
117 static struct assign
*
118 find_assign (const char *s
, const char *k
)
120 struct assign
*assign
;
123 /* Deal with string section lookups. */
125 if (k
!= NULL
&& k
[0] == '%') {
126 bzero(newkey
, sizeof(newkey
));
127 strncpy(newkey
, k
+ 1, strlen(k
) - 2);
131 TAILQ_FOREACH(assign
, &ah
, link
) {
132 if (strcasecmp(assign
->section
->name
, s
) == 0) {
136 if (strcasecmp(assign
->key
, k
) == 0)
144 stringcvt(const char *s
)
148 manf
= find_assign("strings", s
);
151 return(manf
->vals
[0]);
155 find_section (const char *s
)
157 struct section
*section
;
159 TAILQ_FOREACH(section
, &sh
, link
) {
160 if (strcasecmp(section
->name
, s
) == 0)
167 dump_pcmcia_id(const char *s
)
169 char *manstr
, *devstr
;
172 p0
= __DECONST(char *, s
);
174 p
= strchr(p0
, '\\');
186 /* Convert any underscores to spaces. */
188 while (*p0
!= '\0') {
202 /* Convert any underscores to spaces. */
204 while (*p0
!= '\0') {
210 fprintf(ofp
, "\t\\\n\t{ \"%s\", \"%s\", ", manstr
, devstr
);
215 dump_pci_id(const char *s
)
218 char vidstr
[7], didstr
[7], subsysstr
[14];
220 p
= strcasestr(s
, "VEN_");
224 strcpy(vidstr
, "0x");
225 strncat(vidstr
, p
, 4);
226 p
= strcasestr(s
, "DEV_");
230 strcpy(didstr
, "0x");
231 strncat(didstr
, p
, 4);
234 p
= strcasestr(s
, "SUBSYS_");
236 strcpy(subsysstr
, "0x00000000");
239 strcpy(subsysstr
, "0x");
240 strncat(subsysstr
, p
, 8);
243 fprintf(ofp
, "\t\\\n\t{ %s, %s, %s, ", vidstr
, didstr
, subsysstr
);
250 struct assign
*manf
, *dev
;
252 struct assign
*assign
;
256 /* Find manufacturer name */
257 manf
= find_assign("Manufacturer", NULL
);
259 /* Find manufacturer section */
260 if (manf
->vals
[1] != NULL
&&
261 (strcasecmp(manf
->vals
[1], "NT.5.1") == 0 ||
262 strcasecmp(manf
->vals
[1], "NTx86") == 0 ||
263 strcasecmp(manf
->vals
[1], "NTx86.5.1") == 0 ||
264 strcasecmp(manf
->vals
[1], "NTamd64") == 0)) {
265 /* Handle Windows XP INF files. */
266 snprintf(xpsec
, sizeof(xpsec
), "%s.%s",
267 manf
->vals
[0], manf
->vals
[1]);
268 sec
= find_section(xpsec
);
270 sec
= find_section(manf
->vals
[0]);
272 /* See if there are any PCI device definitions. */
274 TAILQ_FOREACH(assign
, &ah
, link
) {
275 if (assign
->section
== sec
) {
276 dev
= find_assign("strings", assign
->key
);
277 if (strcasestr(assign
->vals
[1], "PCI") != NULL
) {
289 /* Emit start of PCI device table */
290 fprintf (ofp
, "#define NDIS_PCI_DEV_TABLE");
295 * Now run through all the device names listed
296 * in the manufacturer section and dump out the
297 * device descriptions and vendor/device IDs.
300 TAILQ_FOREACH(assign
, &ah
, link
) {
301 if (assign
->section
== sec
) {
302 dev
= find_assign("strings", assign
->key
);
303 /* Emit device IDs. */
304 if (strcasestr(assign
->vals
[1], "PCI") != NULL
)
305 dump_pci_id(assign
->vals
[1]);
308 /* Emit device description */
309 fprintf (ofp
, "\t\\\n\t\"%s\" },", dev
->vals
[0]);
314 /* Someone tried to fool us. Shame on them. */
317 sec
= find_section(manf
->vals
[0]);
321 /* Emit end of table */
323 fprintf(ofp
, "\n\n");
328 dump_deviceids_pcmcia()
330 struct assign
*manf
, *dev
;
332 struct assign
*assign
;
336 /* Find manufacturer name */
337 manf
= find_assign("Manufacturer", NULL
);
339 /* Find manufacturer section */
340 if (manf
->vals
[1] != NULL
&&
341 (strcasecmp(manf
->vals
[1], "NT.5.1") == 0 ||
342 strcasecmp(manf
->vals
[1], "NTx86") == 0 ||
343 strcasecmp(manf
->vals
[1], "NTx86.5.1") == 0 ||
344 strcasecmp(manf
->vals
[1], "NTamd64") == 0)) {
345 /* Handle Windows XP INF files. */
346 snprintf(xpsec
, sizeof(xpsec
), "%s.%s",
347 manf
->vals
[0], manf
->vals
[1]);
348 sec
= find_section(xpsec
);
350 sec
= find_section(manf
->vals
[0]);
352 /* See if there are any PCMCIA device definitions. */
354 TAILQ_FOREACH(assign
, &ah
, link
) {
355 if (assign
->section
== sec
) {
356 dev
= find_assign("strings", assign
->key
);
357 if (strcasestr(assign
->vals
[1], "PCMCIA") != NULL
) {
369 /* Emit start of PCMCIA device table */
370 fprintf (ofp
, "#define NDIS_PCMCIA_DEV_TABLE");
375 * Now run through all the device names listed
376 * in the manufacturer section and dump out the
377 * device descriptions and vendor/device IDs.
380 TAILQ_FOREACH(assign
, &ah
, link
) {
381 if (assign
->section
== sec
) {
382 dev
= find_assign("strings", assign
->key
);
383 /* Emit device IDs. */
384 if (strcasestr(assign
->vals
[1], "PCMCIA") != NULL
)
385 dump_pcmcia_id(assign
->vals
[1]);
388 /* Emit device description */
389 fprintf (ofp
, "\t\\\n\t\"%s\" },", dev
->vals
[0]);
394 /* Someone tried to fool us. Shame on them. */
397 sec
= find_section(manf
->vals
[0]);
401 /* Emit end of table */
403 fprintf(ofp
, "\n\n");
408 dump_addreg(const char *s
, int devidx
)
413 /* Find the addreg section */
414 sec
= find_section(s
);
416 /* Dump all the keys defined in it. */
417 TAILQ_FOREACH(reg
, &rh
, link
) {
419 * Keys with an empty subkey are very easy to parse,
420 * so just deal with them here. If a parameter key
421 * of the same name also exists, prefer that one and
424 if (reg
->section
== sec
) {
425 if (reg
->subkey
== NULL
) {
426 fprintf(ofp
, "\n\t{ \"%s\",", reg
->key
);
427 fprintf(ofp
,"\n\t\"%s \",", reg
->key
);
428 fprintf(ofp
, "\n\t{ \"%s\" }, %d },",
429 reg
->value
== NULL
? "" :
430 stringcvt(reg
->value
), devidx
);
431 } else if (strncasecmp(reg
->subkey
,
432 "Ndi\\params", strlen("Ndi\\params")-1) == 0 &&
433 (reg
->key
!= NULL
&& strcasecmp(reg
->key
,
435 dump_paramreg(sec
, reg
, devidx
);
443 dump_enumreg(const struct section
*s
, const struct reg
*r
)
448 sprintf(enumkey
, "%s\\enum", r
->subkey
);
449 TAILQ_FOREACH(reg
, &rh
, link
) {
450 if (reg
->section
!= s
)
452 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, enumkey
))
454 fprintf(ofp
, " [%s=%s]", reg
->key
,
455 stringcvt(reg
->value
));
461 dump_editreg(const struct section
*s
, const struct reg
*r
)
465 TAILQ_FOREACH(reg
, &rh
, link
) {
466 if (reg
->section
!= s
)
468 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
470 if (reg
->key
== NULL
)
472 if (strcasecmp(reg
->key
, "LimitText") == 0)
473 fprintf(ofp
, " [maxchars=%s]", reg
->value
);
474 if (strcasecmp(reg
->key
, "Optional") == 0 &&
475 strcmp(reg
->value
, "1") == 0)
476 fprintf(ofp
, " [optional]");
481 /* Use this for int too */
483 dump_dwordreg(const struct section
*s
, const struct reg
*r
)
487 TAILQ_FOREACH(reg
, &rh
, link
) {
488 if (reg
->section
!= s
)
490 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
492 if (reg
->key
== NULL
)
494 if (strcasecmp(reg
->key
, "min") == 0)
495 fprintf(ofp
, " [min=%s]", reg
->value
);
496 if (strcasecmp(reg
->key
, "max") == 0)
497 fprintf(ofp
, " [max=%s]", reg
->value
);
503 dump_defaultinfo(const struct section
*s
, const struct reg
*r
, int devidx
)
506 TAILQ_FOREACH(reg
, &rh
, link
) {
507 if (reg
->section
!= s
)
509 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
511 if (reg
->key
== NULL
|| strcasecmp(reg
->key
, "Default"))
513 fprintf(ofp
, "\n\t{ \"%s\" }, %d },", reg
->value
== NULL
? "" :
514 stringcvt(reg
->value
), devidx
);
521 dump_paramdesc(const struct section
*s
, const struct reg
*r
)
524 TAILQ_FOREACH(reg
, &rh
, link
) {
525 if (reg
->section
!= s
)
527 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
529 if (reg
->key
== NULL
|| strcasecmp(reg
->key
, "ParamDesc"))
531 fprintf(ofp
, "\n\t\"%s", stringcvt(r
->value
));
538 dump_typeinfo(const struct section
*s
, const struct reg
*r
)
541 TAILQ_FOREACH(reg
, &rh
, link
) {
542 if (reg
->section
!= s
)
544 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
546 if (reg
->key
== NULL
)
548 if (strcasecmp(reg
->key
, "type"))
550 if (strcasecmp(reg
->value
, "dword") == 0 ||
551 strcasecmp(reg
->value
, "int") == 0)
553 if (strcasecmp(reg
->value
, "enum") == 0)
555 if (strcasecmp(reg
->value
, "edit") == 0)
562 dump_paramreg(const struct section
*s
, const struct reg
*r
, int devidx
)
566 keyname
= r
->subkey
+ strlen("Ndi\\params\\");
567 fprintf(ofp
, "\n\t{ \"%s\",", keyname
);
568 dump_paramdesc(s
, r
);
571 dump_defaultinfo(s
, r
, devidx
);
579 struct assign
*manf
, *dev
;
581 struct assign
*assign
;
583 int found
= 0, i
, is_winxp
= 0, is_winnt
= 0, devidx
= 0;
585 /* Find signature to check for special case of WinNT. */
586 assign
= find_assign("version", "signature");
587 if (strcasecmp(assign
->vals
[0], "$windows nt$") == 0)
590 /* Find manufacturer name */
591 manf
= find_assign("Manufacturer", NULL
);
593 /* Find manufacturer section */
594 if (manf
->vals
[1] != NULL
&&
595 (strcasecmp(manf
->vals
[1], "NT.5.1") == 0 ||
596 strcasecmp(manf
->vals
[1], "NTx86") == 0 ||
597 strcasecmp(manf
->vals
[1], "NTx86.5.1") == 0 ||
598 strcasecmp(manf
->vals
[1], "NTamd64") == 0)) {
600 /* Handle Windows XP INF files. */
601 snprintf(sname
, sizeof(sname
), "%s.%s",
602 manf
->vals
[0], manf
->vals
[1]);
603 sec
= find_section(sname
);
605 sec
= find_section(manf
->vals
[0]);
607 /* Emit start of block */
608 fprintf (ofp
, "ndis_cfg ndis_regvals[] = {");
612 TAILQ_FOREACH(assign
, &ah
, link
) {
613 if (assign
->section
== sec
) {
616 * Find all the AddReg sections.
617 * Look for section names with .NT, unless
618 * this is a WinXP .INF file.
622 sprintf(sname
, "%s.NTx86", assign
->vals
[0]);
623 dev
= find_assign(sname
, "AddReg");
625 sprintf(sname
, "%s.NT",
627 dev
= find_assign(sname
, "AddReg");
630 dev
= find_assign(assign
->vals
[0],
633 sprintf(sname
, "%s.NT", assign
->vals
[0]);
634 dev
= find_assign(sname
, "AddReg");
635 if (dev
== NULL
&& is_winnt
)
636 dev
= find_assign(assign
->vals
[0],
639 /* Section not found. */
642 for (i
= 0; i
< W_MAX
; i
++) {
643 if (dev
->vals
[i
] != NULL
)
644 dump_addreg(dev
->vals
[i
], devidx
);
651 sec
= find_section(manf
->vals
[0]);
657 fprintf(ofp
, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
663 assign_add (const char *a
)
665 struct assign
*assign
;
668 assign
= malloc(sizeof(struct assign
));
669 bzero(assign
, sizeof(struct assign
));
670 assign
->section
= TAILQ_LAST(&sh
, section_head
);
671 assign
->key
= sstrdup(a
);
672 for (i
= 0; i
< idx
; i
++)
673 assign
->vals
[(idx
- 1) - i
] = sstrdup(words
[i
]);
674 TAILQ_INSERT_TAIL(&ah
, assign
, link
);
681 define_add (const char *d __unused
)
684 fprintf(stderr
, "define \"%s\"\n", d
);
690 sstrdup(const char *str
)
692 if (str
!= NULL
&& strlen(str
))
693 return (strdup(str
));
698 satoi (const char *nptr
)
700 if (nptr
!= NULL
&& strlen(nptr
))
706 regkey_add (const char *r
)
710 reg
= malloc(sizeof(struct reg
));
711 bzero(reg
, sizeof(struct reg
));
712 reg
->section
= TAILQ_LAST(&sh
, section_head
);
713 reg
->root
= sstrdup(r
);
714 reg
->subkey
= sstrdup(words
[3]);
715 reg
->key
= sstrdup(words
[2]);
716 reg
->flags
= satoi(words
[1]);
717 reg
->value
= sstrdup(words
[0]);
718 TAILQ_INSERT_TAIL(&rh
, reg
, link
);
720 free(__DECONST(char *, r
));
726 push_word (const char *w
)
740 for (i
= 0; i
< idx
; i
++) {
742 free(__DECONST(char *, words
[i
]));
746 bzero(words
, sizeof(words
));