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 * $DragonFly: src/usr.sbin/ndiscvt/inf.c,v 1.2 2005/12/05 02:40:27 swildner 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 *);
58 *find_section (const char *);
59 static void dump_deviceids_pci (void);
60 static void dump_deviceids_pcmcia (void);
61 static void dump_pci_id (const char *);
62 static void dump_pcmcia_id (const char *);
63 static void dump_regvals (void);
64 static void dump_paramreg (const struct section
*,
65 const struct reg
*, int);
70 inf_parse(FILE *fp
, FILE *outfp
)
81 dump_deviceids_pcmcia();
82 fprintf(outfp
, "#ifdef NDIS_REGVALS\n");
84 fprintf(outfp
, "#endif /* NDIS_REGVALS */\n");
90 section_add(const char *s
)
94 sec
= malloc(sizeof(struct section
));
95 bzero(sec
, sizeof(struct section
));
97 TAILQ_INSERT_TAIL(&sh
, sec
, link
);
102 static struct assign
*
103 find_assign(const char *s
, const char *k
)
105 struct assign
*assign
;
108 /* Deal with string section lookups. */
110 if (k
!= NULL
&& k
[0] == '%') {
111 bzero(newkey
, sizeof(newkey
));
112 strncpy(newkey
, k
+ 1, strlen(k
) - 2);
116 TAILQ_FOREACH(assign
, &ah
, link
) {
117 if (strcasecmp(assign
->section
->name
, s
) == 0) {
121 if (strcasecmp(assign
->key
, k
) == 0)
129 stringcvt(const char *s
)
133 manf
= find_assign("strings", s
);
136 return(manf
->vals
[0]);
140 find_section(const char *s
)
142 struct section
*section
;
144 TAILQ_FOREACH(section
, &sh
, link
) {
145 if (strcasecmp(section
->name
, s
) == 0)
152 dump_pcmcia_id(const char *s
)
154 char *manstr
, *devstr
;
157 p0
= __DECONST(char *, s
);
159 p
= strchr(p0
, '\\');
171 /* Convert any underscores to spaces. */
173 while (*p0
!= '\0') {
187 /* Convert any underscores to spaces. */
189 while (*p0
!= '\0') {
195 fprintf(ofp
, "\t\\\n\t{ \"%s\", \"%s\", ", manstr
, devstr
);
200 dump_pci_id(const char *s
)
203 char vidstr
[7], didstr
[7], subsysstr
[14];
205 p
= strcasestr(s
, "VEN_");
209 strcpy(vidstr
, "0x");
210 strncat(vidstr
, p
, 4);
211 p
= strcasestr(s
, "DEV_");
215 strcpy(didstr
, "0x");
216 strncat(didstr
, p
, 4);
219 p
= strcasestr(s
, "SUBSYS_");
221 strcpy(subsysstr
, "0x00000000");
224 strcpy(subsysstr
, "0x");
225 strncat(subsysstr
, p
, 8);
228 fprintf(ofp
, "\t\\\n\t{ %s, %s, %s, ", vidstr
, didstr
, subsysstr
);
233 dump_deviceids_pci(void)
235 struct assign
*manf
, *dev
;
237 struct assign
*assign
;
241 /* Find manufacturer name */
242 manf
= find_assign("Manufacturer", NULL
);
244 /* Find manufacturer section */
245 if (manf
->vals
[1] != NULL
&&
246 (strcasecmp(manf
->vals
[1], "NT.5.1") == 0 ||
247 strcasecmp(manf
->vals
[1], "NTx86") == 0 ||
248 strcasecmp(manf
->vals
[1], "NTx86.5.1") == 0)) {
249 /* Handle Windows XP INF files. */
250 snprintf(xpsec
, sizeof(xpsec
), "%s.%s",
251 manf
->vals
[0], manf
->vals
[1]);
252 sec
= find_section(xpsec
);
254 sec
= find_section(manf
->vals
[0]);
256 /* See if there are any PCI device definitions. */
258 TAILQ_FOREACH(assign
, &ah
, link
) {
259 if (assign
->section
== sec
) {
260 dev
= find_assign("strings", assign
->key
);
261 if (strcasestr(assign
->vals
[1], "PCI") != NULL
) {
273 /* Emit start of PCI device table */
274 fprintf (ofp
, "#define NDIS_PCI_DEV_TABLE");
279 * Now run through all the device names listed
280 * in the manufacturer section and dump out the
281 * device descriptions and vendor/device IDs.
284 TAILQ_FOREACH(assign
, &ah
, link
) {
285 if (assign
->section
== sec
) {
286 dev
= find_assign("strings", assign
->key
);
287 /* Emit device IDs. */
288 if (strcasestr(assign
->vals
[1], "PCI") != NULL
)
289 dump_pci_id(assign
->vals
[1]);
292 /* Emit device description */
293 fprintf (ofp
, "\t\\\n\t\"%s\" },", dev
->vals
[0]);
298 /* Someone tried to fool us. Shame on them. */
301 sec
= find_section(manf
->vals
[0]);
305 /* Emit end of table */
307 fprintf(ofp
, "\n\n");
312 dump_deviceids_pcmcia(void)
314 struct assign
*manf
, *dev
;
316 struct assign
*assign
;
320 /* Find manufacturer name */
321 manf
= find_assign("Manufacturer", NULL
);
323 /* Find manufacturer section */
324 if (manf
->vals
[1] != NULL
&&
325 (strcasecmp(manf
->vals
[1], "NT.5.1") == 0 ||
326 strcasecmp(manf
->vals
[1], "NTx86") == 0 ||
327 strcasecmp(manf
->vals
[1], "NTx86.5.1") == 0)) {
328 /* Handle Windows XP INF files. */
329 snprintf(xpsec
, sizeof(xpsec
), "%s.%s",
330 manf
->vals
[0], manf
->vals
[1]);
331 sec
= find_section(xpsec
);
333 sec
= find_section(manf
->vals
[0]);
335 /* See if there are any PCMCIA device definitions. */
337 TAILQ_FOREACH(assign
, &ah
, link
) {
338 if (assign
->section
== sec
) {
339 dev
= find_assign("strings", assign
->key
);
340 if (strcasestr(assign
->vals
[1], "PCMCIA") != NULL
) {
352 /* Emit start of PCMCIA device table */
353 fprintf (ofp
, "#define NDIS_PCMCIA_DEV_TABLE");
358 * Now run through all the device names listed
359 * in the manufacturer section and dump out the
360 * device descriptions and vendor/device IDs.
363 TAILQ_FOREACH(assign
, &ah
, link
) {
364 if (assign
->section
== sec
) {
365 dev
= find_assign("strings", assign
->key
);
366 /* Emit device IDs. */
367 if (strcasestr(assign
->vals
[1], "PCMCIA") != NULL
)
368 dump_pcmcia_id(assign
->vals
[1]);
371 /* Emit device description */
372 fprintf (ofp
, "\t\\\n\t\"%s\" },", dev
->vals
[0]);
377 /* Someone tried to fool us. Shame on them. */
380 sec
= find_section(manf
->vals
[0]);
384 /* Emit end of table */
386 fprintf(ofp
, "\n\n");
391 dump_addreg(const char *s
, int devidx
)
396 /* Find the addreg section */
397 sec
= find_section(s
);
399 /* Dump all the keys defined in it. */
400 TAILQ_FOREACH(reg
, &rh
, link
) {
402 * Keys with an empty subkey are very easy to parse,
403 * so just deal with them here. If a parameter key
404 * of the same name also exists, prefer that one and
407 if (reg
->section
== sec
) {
408 if (reg
->subkey
== NULL
) {
409 fprintf(ofp
, "\n\t{ \"%s\",", reg
->key
);
410 fprintf(ofp
,"\n\t\"%s \",", reg
->key
);
411 fprintf(ofp
, "\n\t{ \"%s\" }, %d },",
412 reg
->value
== NULL
? "" :
413 stringcvt(reg
->value
), devidx
);
414 } else if (strncasecmp(reg
->subkey
,
415 "Ndi\\params", strlen("Ndi\\params")-1) == 0 &&
416 (reg
->key
!= NULL
&& strcasecmp(reg
->key
,
418 dump_paramreg(sec
, reg
, devidx
);
426 dump_enumreg(const struct section
*s
, const struct reg
*r
)
431 sprintf(enumkey
, "%s\\enum", r
->subkey
);
432 TAILQ_FOREACH(reg
, &rh
, link
) {
433 if (reg
->section
!= s
)
435 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, enumkey
))
437 fprintf(ofp
, " [%s=%s]", reg
->key
,
438 stringcvt(reg
->value
));
444 dump_editreg(const struct section
*s
, const struct reg
*r
)
448 TAILQ_FOREACH(reg
, &rh
, link
) {
449 if (reg
->section
!= s
)
451 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
453 if (reg
->key
== NULL
)
455 if (strcasecmp(reg
->key
, "LimitText") == 0)
456 fprintf(ofp
, " [maxchars=%s]", reg
->value
);
457 if (strcasecmp(reg
->key
, "Optional") == 0 &&
458 strcmp(reg
->value
, "1") == 0)
459 fprintf(ofp
, " [optional]");
464 /* Use this for int too */
466 dump_dwordreg(const struct section
*s
, const struct reg
*r
)
470 TAILQ_FOREACH(reg
, &rh
, link
) {
471 if (reg
->section
!= s
)
473 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
475 if (reg
->key
== NULL
)
477 if (strcasecmp(reg
->key
, "min") == 0)
478 fprintf(ofp
, " [min=%s]", reg
->value
);
479 if (strcasecmp(reg
->key
, "max") == 0)
480 fprintf(ofp
, " [max=%s]", reg
->value
);
486 dump_defaultinfo(const struct section
*s
, const struct reg
*r
, int devidx
)
489 TAILQ_FOREACH(reg
, &rh
, link
) {
490 if (reg
->section
!= s
)
492 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
494 if (reg
->key
== NULL
|| strcasecmp(reg
->key
, "Default"))
496 fprintf(ofp
, "\n\t{ \"%s\" }, %d },", reg
->value
== NULL
? "" :
497 stringcvt(reg
->value
), devidx
);
504 dump_paramdesc(const struct section
*s
, const struct reg
*r
)
507 TAILQ_FOREACH(reg
, &rh
, link
) {
508 if (reg
->section
!= s
)
510 if (reg
->subkey
== NULL
|| strcasecmp(reg
->subkey
, r
->subkey
))
512 if (reg
->key
== NULL
|| strcasecmp(reg
->key
, "ParamDesc"))
514 fprintf(ofp
, "\n\t\"%s", stringcvt(r
->value
));
521 dump_typeinfo(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
)
531 if (strcasecmp(reg
->key
, "type"))
533 if (strcasecmp(reg
->value
, "dword") == 0 ||
534 strcasecmp(reg
->value
, "int") == 0)
536 if (strcasecmp(reg
->value
, "enum") == 0)
538 if (strcasecmp(reg
->value
, "edit") == 0)
545 dump_paramreg(const struct section
*s
, const struct reg
*r
, int devidx
)
549 keyname
= r
->subkey
+ strlen("Ndi\\params\\");
550 fprintf(ofp
, "\n\t{ \"%s\",", keyname
);
551 dump_paramdesc(s
, r
);
554 dump_defaultinfo(s
, r
, devidx
);
562 struct assign
*manf
, *dev
;
564 struct assign
*assign
;
566 int found
= 0, i
, is_winxp
= 0, is_winnt
= 0, devidx
= 0;
568 /* Find signature to check for special case of WinNT. */
569 assign
= find_assign("version", "signature");
570 if (strcasecmp(assign
->vals
[0], "$windows nt$") == 0)
573 /* Find manufacturer name */
574 manf
= find_assign("Manufacturer", NULL
);
576 /* Find manufacturer section */
577 if (manf
->vals
[1] != NULL
&&
578 (strcasecmp(manf
->vals
[1], "NT.5.1") == 0 ||
579 strcasecmp(manf
->vals
[1], "NTx86") == 0 ||
580 strcasecmp(manf
->vals
[1], "NTx86.5.1") == 0)) {
582 /* Handle Windows XP INF files. */
583 snprintf(sname
, sizeof(sname
), "%s.%s",
584 manf
->vals
[0], manf
->vals
[1]);
585 sec
= find_section(sname
);
587 sec
= find_section(manf
->vals
[0]);
589 /* Emit start of block */
590 fprintf (ofp
, "ndis_cfg ndis_regvals[] = {");
594 TAILQ_FOREACH(assign
, &ah
, link
) {
595 if (assign
->section
== sec
) {
598 * Find all the AddReg sections.
599 * Look for section names with .NT, unless
600 * this is a WinXP .INF file.
603 sprintf(sname
, "%s.NTx86", assign
->vals
[0]);
604 dev
= find_assign(sname
, "AddReg");
606 dev
= find_assign(assign
->vals
[0],
609 sprintf(sname
, "%s.NT", assign
->vals
[0]);
610 dev
= find_assign(sname
, "AddReg");
611 if (dev
== NULL
&& is_winnt
)
612 dev
= find_assign(assign
->vals
[0],
615 /* Section not found. */
618 for (i
= 0; i
< W_MAX
; i
++) {
619 if (dev
->vals
[i
] != NULL
)
620 dump_addreg(dev
->vals
[i
], devidx
);
627 sec
= find_section(manf
->vals
[0]);
633 fprintf(ofp
, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
639 assign_add(const char *a
)
641 struct assign
*assign
;
644 assign
= malloc(sizeof(struct assign
));
645 bzero(assign
, sizeof(struct assign
));
646 assign
->section
= TAILQ_LAST(&sh
, section_head
);
647 assign
->key
= sstrdup(a
);
648 for (i
= 0; i
< idx
; i
++)
649 assign
->vals
[(idx
- 1) - i
] = sstrdup(words
[i
]);
650 TAILQ_INSERT_TAIL(&ah
, assign
, link
);
657 define_add(const char *d __unused
)
660 fprintf(stderr
, "define \"%s\"\n", d
);
666 sstrdup(const char *str
)
668 if (str
!= NULL
&& strlen(str
))
669 return (strdup(str
));
674 satoi(const char *nptr
)
676 if (nptr
!= NULL
&& strlen(nptr
))
682 regkey_add(const char *r
)
686 reg
= malloc(sizeof(struct reg
));
687 bzero(reg
, sizeof(struct reg
));
688 reg
->section
= TAILQ_LAST(&sh
, section_head
);
689 reg
->root
= sstrdup(r
);
690 reg
->subkey
= sstrdup(words
[3]);
691 reg
->key
= sstrdup(words
[2]);
692 reg
->flags
= satoi(words
[1]);
693 reg
->value
= sstrdup(words
[0]);
694 TAILQ_INSERT_TAIL(&rh
, reg
, link
);
696 free(__DECONST(char *, r
));
702 push_word(const char *w
)
716 for (i
= 0; i
< idx
; i
++) {
718 free(__DECONST(char *, words
[i
]));
722 bzero(words
, sizeof(words
));