Ignore machine-check MSRs
[freebsd-src/fkvm-freebsd.git] / usr.sbin / ndiscvt / inf.c
blob05f863de9bbe543abaccbb6fea2ca2e7ed10befe
1 /*
2 * Copyright (c) 2003
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
7 * are met:
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$");
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/types.h>
41 #include <sys/queue.h>
43 #include "inf.h"
45 extern FILE *yyin;
46 int yyparse (void);
48 const char *words[W_MAX]; /* More than we'll need. */
49 int idx;
51 static struct section_head sh;
52 static struct reg_head rh;
53 static struct assign_head ah;
55 static char *sstrdup (const char *);
56 static struct assign
57 *find_assign (const char *, const char *);
58 static struct assign
59 *find_next_assign
60 (struct assign *);
61 static struct section
62 *find_section (const char *);
63 static void dump_deviceids_pci (void);
64 static void dump_deviceids_pcmcia (void);
65 static void dump_pci_id (const char *);
66 static void dump_pcmcia_id (const char *);
67 static void dump_regvals (void);
68 static void dump_paramreg (const struct section *,
69 const struct reg *, int);
71 static FILE *ofp;
73 int
74 inf_parse (FILE *fp, FILE *outfp)
76 TAILQ_INIT(&sh);
77 TAILQ_INIT(&rh);
78 TAILQ_INIT(&ah);
80 ofp = outfp;
81 yyin = fp;
82 yyparse();
84 dump_deviceids_pci();
85 dump_deviceids_pcmcia();
86 fprintf(outfp, "#ifdef NDIS_REGVALS\n");
87 dump_regvals();
88 fprintf(outfp, "#endif /* NDIS_REGVALS */\n");
90 return (0);
93 void
94 section_add (const char *s)
96 struct section *sec;
98 sec = malloc(sizeof(struct section));
99 bzero(sec, sizeof(struct section));
100 sec->name = s;
101 TAILQ_INSERT_TAIL(&sh, sec, link);
103 return;
106 static struct assign *
107 find_assign (const char *s, const char *k)
109 struct assign *assign;
110 char newkey[256];
112 /* Deal with string section lookups. */
114 if (k != NULL && k[0] == '%') {
115 bzero(newkey, sizeof(newkey));
116 strncpy(newkey, k + 1, strlen(k) - 2);
117 k = newkey;
120 TAILQ_FOREACH(assign, &ah, link) {
121 if (strcasecmp(assign->section->name, s) == 0) {
122 if (k == NULL)
123 return(assign);
124 else
125 if (strcasecmp(assign->key, k) == 0)
126 return(assign);
129 return(NULL);
132 static struct assign *
133 find_next_assign (struct assign *a)
135 struct assign *assign;
137 TAILQ_FOREACH(assign, &ah, link) {
138 if (assign == a)
139 break;
142 assign = assign->link.tqe_next;
144 if (assign == NULL || assign->section != a->section)
145 return(NULL);
147 return (assign);
150 static const char *
151 stringcvt(const char *s)
153 struct assign *manf;
155 manf = find_assign("strings", s);
156 if (manf == NULL)
157 return(s);
158 return(manf->vals[0]);
161 struct section *
162 find_section (const char *s)
164 struct section *section;
166 TAILQ_FOREACH(section, &sh, link) {
167 if (strcasecmp(section->name, s) == 0)
168 return(section);
170 return(NULL);
173 static void
174 dump_pcmcia_id(const char *s)
176 char *manstr, *devstr;
177 char *p0, *p;
179 p0 = __DECONST(char *, s);
181 p = strchr(p0, '\\');
182 if (p == NULL)
183 return;
184 p0 = p + 1;
186 p = strchr(p0, '-');
187 if (p == NULL)
188 return;
189 *p = '\0';
191 manstr = p0;
193 /* Convert any underscores to spaces. */
195 while (*p0 != '\0') {
196 if (*p0 == '_')
197 *p0 = ' ';
198 p0++;
201 p0 = p + 1;
202 p = strchr(p0, '-');
203 if (p == NULL)
204 return;
205 *p = '\0';
207 devstr = p0;
209 /* Convert any underscores to spaces. */
211 while (*p0 != '\0') {
212 if (*p0 == '_')
213 *p0 = ' ';
214 p0++;
217 fprintf(ofp, "\t\\\n\t{ \"%s\", \"%s\", ", manstr, devstr);
218 return;
221 static void
222 dump_pci_id(const char *s)
224 char *p;
225 char vidstr[7], didstr[7], subsysstr[14];
227 p = strcasestr(s, "VEN_");
228 if (p == NULL)
229 return;
230 p += 4;
231 strcpy(vidstr, "0x");
232 strncat(vidstr, p, 4);
233 p = strcasestr(s, "DEV_");
234 if (p == NULL)
235 return;
236 p += 4;
237 strcpy(didstr, "0x");
238 strncat(didstr, p, 4);
239 if (p == NULL)
240 return;
241 p = strcasestr(s, "SUBSYS_");
242 if (p == NULL)
243 strcpy(subsysstr, "0x00000000");
244 else {
245 p += 7;
246 strcpy(subsysstr, "0x");
247 strncat(subsysstr, p, 8);
250 fprintf(ofp, "\t\\\n\t{ %s, %s, %s, ", vidstr, didstr, subsysstr);
251 return;
254 static void
255 dump_deviceids_pci()
257 struct assign *manf, *dev;
258 struct section *sec;
259 struct assign *assign;
260 char xpsec[256];
261 int first = 1, found = 0;
263 /* Find manufacturer name */
264 manf = find_assign("Manufacturer", NULL);
266 nextmanf:
268 /* Find manufacturer section */
269 if (manf->vals[1] != NULL &&
270 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
271 strcasecmp(manf->vals[1], "NTx86") == 0 ||
272 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
273 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
274 /* Handle Windows XP INF files. */
275 snprintf(xpsec, sizeof(xpsec), "%s.%s",
276 manf->vals[0], manf->vals[1]);
277 sec = find_section(xpsec);
278 } else
279 sec = find_section(manf->vals[0]);
281 /* See if there are any PCI device definitions. */
283 TAILQ_FOREACH(assign, &ah, link) {
284 if (assign->section == sec) {
285 dev = find_assign("strings", assign->key);
286 if (strcasestr(assign->vals[1], "PCI") != NULL) {
287 found++;
288 break;
293 if (found == 0)
294 goto done;
296 found = 0;
298 if (first == 1) {
299 /* Emit start of PCI device table */
300 fprintf (ofp, "#define NDIS_PCI_DEV_TABLE");
301 first = 0;
304 retry:
307 * Now run through all the device names listed
308 * in the manufacturer section and dump out the
309 * device descriptions and vendor/device IDs.
312 TAILQ_FOREACH(assign, &ah, link) {
313 if (assign->section == sec) {
314 dev = find_assign("strings", assign->key);
315 /* Emit device IDs. */
316 if (strcasestr(assign->vals[1], "PCI") != NULL)
317 dump_pci_id(assign->vals[1]);
318 else
319 continue;
320 /* Emit device description */
321 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
322 found++;
326 /* Someone tried to fool us. Shame on them. */
327 if (!found) {
328 found++;
329 sec = find_section(manf->vals[0]);
330 goto retry;
333 /* Handle Manufacturer sections with multiple entries. */
334 manf = find_next_assign(manf);
336 if (manf != NULL)
337 goto nextmanf;
339 done:
340 /* Emit end of table */
342 fprintf(ofp, "\n\n");
344 return;
347 static void
348 dump_deviceids_pcmcia()
350 struct assign *manf, *dev;
351 struct section *sec;
352 struct assign *assign;
353 char xpsec[256];
354 int first = 1, found = 0;
356 /* Find manufacturer name */
357 manf = find_assign("Manufacturer", NULL);
359 nextmanf:
361 /* Find manufacturer section */
362 if (manf->vals[1] != NULL &&
363 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
364 strcasecmp(manf->vals[1], "NTx86") == 0 ||
365 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
366 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
367 /* Handle Windows XP INF files. */
368 snprintf(xpsec, sizeof(xpsec), "%s.%s",
369 manf->vals[0], manf->vals[1]);
370 sec = find_section(xpsec);
371 } else
372 sec = find_section(manf->vals[0]);
374 /* See if there are any PCMCIA device definitions. */
376 TAILQ_FOREACH(assign, &ah, link) {
377 if (assign->section == sec) {
378 dev = find_assign("strings", assign->key);
379 if (strcasestr(assign->vals[1], "PCMCIA") != NULL) {
380 found++;
381 break;
386 if (found == 0)
387 goto done;
389 found = 0;
391 if (first == 1) {
392 /* Emit start of PCMCIA device table */
393 fprintf (ofp, "#define NDIS_PCMCIA_DEV_TABLE");
394 first = 0;
397 retry:
400 * Now run through all the device names listed
401 * in the manufacturer section and dump out the
402 * device descriptions and vendor/device IDs.
405 TAILQ_FOREACH(assign, &ah, link) {
406 if (assign->section == sec) {
407 dev = find_assign("strings", assign->key);
408 /* Emit device IDs. */
409 if (strcasestr(assign->vals[1], "PCMCIA") != NULL)
410 dump_pcmcia_id(assign->vals[1]);
411 else
412 continue;
413 /* Emit device description */
414 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
415 found++;
419 /* Someone tried to fool us. Shame on them. */
420 if (!found) {
421 found++;
422 sec = find_section(manf->vals[0]);
423 goto retry;
426 /* Handle Manufacturer sections with multiple entries. */
427 manf = find_next_assign(manf);
429 if (manf != NULL)
430 goto nextmanf;
432 done:
433 /* Emit end of table */
435 fprintf(ofp, "\n\n");
437 return;
440 static void
441 dump_addreg(const char *s, int devidx)
443 struct section *sec;
444 struct reg *reg;
446 /* Find the addreg section */
447 sec = find_section(s);
449 /* Dump all the keys defined in it. */
450 TAILQ_FOREACH(reg, &rh, link) {
452 * Keys with an empty subkey are very easy to parse,
453 * so just deal with them here. If a parameter key
454 * of the same name also exists, prefer that one and
455 * skip this one.
457 if (reg->section == sec) {
458 if (reg->subkey == NULL) {
459 fprintf(ofp, "\n\t{ \"%s\",", reg->key);
460 fprintf(ofp,"\n\t\"%s \",", reg->key);
461 fprintf(ofp, "\n\t{ \"%s\" }, %d },",
462 reg->value == NULL ? "" :
463 stringcvt(reg->value), devidx);
464 } else if (strncasecmp(reg->subkey,
465 "Ndi\\params", strlen("Ndi\\params")-1) == 0 &&
466 (reg->key != NULL && strcasecmp(reg->key,
467 "ParamDesc") == 0))
468 dump_paramreg(sec, reg, devidx);
472 return;
475 static void
476 dump_enumreg(const struct section *s, const struct reg *r)
478 struct reg *reg;
479 char enumkey[256];
481 sprintf(enumkey, "%s\\enum", r->subkey);
482 TAILQ_FOREACH(reg, &rh, link) {
483 if (reg->section != s)
484 continue;
485 if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey))
486 continue;
487 fprintf(ofp, " [%s=%s]", reg->key,
488 stringcvt(reg->value));
490 return;
493 static void
494 dump_editreg(const struct section *s, const struct reg *r)
496 struct reg *reg;
498 TAILQ_FOREACH(reg, &rh, link) {
499 if (reg->section != s)
500 continue;
501 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
502 continue;
503 if (reg->key == NULL)
504 continue;
505 if (strcasecmp(reg->key, "LimitText") == 0)
506 fprintf(ofp, " [maxchars=%s]", reg->value);
507 if (strcasecmp(reg->key, "Optional") == 0 &&
508 strcmp(reg->value, "1") == 0)
509 fprintf(ofp, " [optional]");
511 return;
514 /* Use this for int too */
515 static void
516 dump_dwordreg(const struct section *s, const struct reg *r)
518 struct reg *reg;
520 TAILQ_FOREACH(reg, &rh, link) {
521 if (reg->section != s)
522 continue;
523 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
524 continue;
525 if (reg->key == NULL)
526 continue;
527 if (strcasecmp(reg->key, "min") == 0)
528 fprintf(ofp, " [min=%s]", reg->value);
529 if (strcasecmp(reg->key, "max") == 0)
530 fprintf(ofp, " [max=%s]", reg->value);
532 return;
535 static void
536 dump_defaultinfo(const struct section *s, const struct reg *r, int devidx)
538 struct reg *reg;
539 TAILQ_FOREACH(reg, &rh, link) {
540 if (reg->section != s)
541 continue;
542 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
543 continue;
544 if (reg->key == NULL || strcasecmp(reg->key, "Default"))
545 continue;
546 fprintf(ofp, "\n\t{ \"%s\" }, %d },", reg->value == NULL ? "" :
547 stringcvt(reg->value), devidx);
548 return;
550 /* Default registry entry missing */
551 fprintf(ofp, "\n\t{ \"\" }, %d },", devidx);
552 return;
555 static void
556 dump_paramdesc(const struct section *s, const struct reg *r)
558 struct reg *reg;
559 TAILQ_FOREACH(reg, &rh, link) {
560 if (reg->section != s)
561 continue;
562 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
563 continue;
564 if (reg->key == NULL || strcasecmp(reg->key, "ParamDesc"))
565 continue;
566 fprintf(ofp, "\n\t\"%s", stringcvt(r->value));
567 break;
569 return;
572 static void
573 dump_typeinfo(const struct section *s, const struct reg *r)
575 struct reg *reg;
576 TAILQ_FOREACH(reg, &rh, link) {
577 if (reg->section != s)
578 continue;
579 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
580 continue;
581 if (reg->key == NULL)
582 continue;
583 if (strcasecmp(reg->key, "type"))
584 continue;
585 if (strcasecmp(reg->value, "dword") == 0 ||
586 strcasecmp(reg->value, "int") == 0)
587 dump_dwordreg(s, r);
588 if (strcasecmp(reg->value, "enum") == 0)
589 dump_enumreg(s, r);
590 if (strcasecmp(reg->value, "edit") == 0)
591 dump_editreg(s, r);
593 return;
596 static void
597 dump_paramreg(const struct section *s, const struct reg *r, int devidx)
599 const char *keyname;
601 keyname = r->subkey + strlen("Ndi\\params\\");
602 fprintf(ofp, "\n\t{ \"%s\",", keyname);
603 dump_paramdesc(s, r);
604 dump_typeinfo(s, r);
605 fprintf(ofp, "\",");
606 dump_defaultinfo(s, r, devidx);
608 return;
611 static void
612 dump_regvals(void)
614 struct assign *manf, *dev;
615 struct section *sec;
616 struct assign *assign;
617 char sname[256];
618 int found = 0, i, is_winxp = 0, is_winnt = 0, devidx = 0;
620 /* Find signature to check for special case of WinNT. */
621 assign = find_assign("version", "signature");
622 if (strcasecmp(assign->vals[0], "$windows nt$") == 0)
623 is_winnt++;
625 /* Emit start of block */
626 fprintf (ofp, "ndis_cfg ndis_regvals[] = {");
628 /* Find manufacturer name */
629 manf = find_assign("Manufacturer", NULL);
631 nextmanf:
633 /* Find manufacturer section */
634 if (manf->vals[1] != NULL &&
635 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
636 strcasecmp(manf->vals[1], "NTx86") == 0 ||
637 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
638 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
639 is_winxp++;
640 /* Handle Windows XP INF files. */
641 snprintf(sname, sizeof(sname), "%s.%s",
642 manf->vals[0], manf->vals[1]);
643 sec = find_section(sname);
644 } else
645 sec = find_section(manf->vals[0]);
647 retry:
649 TAILQ_FOREACH(assign, &ah, link) {
650 if (assign->section == sec) {
651 found++;
653 * Find all the AddReg sections.
654 * Look for section names with .NT, unless
655 * this is a WinXP .INF file.
658 if (is_winxp) {
659 sprintf(sname, "%s.NTx86", assign->vals[0]);
660 dev = find_assign(sname, "AddReg");
661 if (dev == NULL) {
662 sprintf(sname, "%s.NT",
663 assign->vals[0]);
664 dev = find_assign(sname, "AddReg");
666 if (dev == NULL)
667 dev = find_assign(assign->vals[0],
668 "AddReg");
669 } else {
670 sprintf(sname, "%s.NT", assign->vals[0]);
671 dev = find_assign(sname, "AddReg");
672 if (dev == NULL && is_winnt)
673 dev = find_assign(assign->vals[0],
674 "AddReg");
676 /* Section not found. */
677 if (dev == NULL)
678 continue;
679 for (i = 0; i < W_MAX; i++) {
680 if (dev->vals[i] != NULL)
681 dump_addreg(dev->vals[i], devidx);
683 devidx++;
687 if (!found) {
688 sec = find_section(manf->vals[0]);
689 is_winxp = 0;
690 found++;
691 goto retry;
694 manf = find_next_assign(manf);
696 if (manf != NULL)
697 goto nextmanf;
699 fprintf(ofp, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
701 return;
704 void
705 assign_add (const char *a)
707 struct assign *assign;
708 int i;
710 assign = malloc(sizeof(struct assign));
711 bzero(assign, sizeof(struct assign));
712 assign->section = TAILQ_LAST(&sh, section_head);
713 assign->key = sstrdup(a);
714 for (i = 0; i < idx; i++)
715 assign->vals[(idx - 1) - i] = sstrdup(words[i]);
716 TAILQ_INSERT_TAIL(&ah, assign, link);
718 clear_words();
719 return;
722 void
723 define_add (const char *d __unused)
725 #ifdef notdef
726 fprintf(stderr, "define \"%s\"\n", d);
727 #endif
728 return;
731 static char *
732 sstrdup(const char *str)
734 if (str != NULL && strlen(str))
735 return (strdup(str));
736 return (NULL);
739 static int
740 satoi (const char *nptr)
742 if (nptr != NULL && strlen(nptr))
743 return (atoi(nptr));
744 return (0);
747 void
748 regkey_add (const char *r)
750 struct reg *reg;
752 reg = malloc(sizeof(struct reg));
753 bzero(reg, sizeof(struct reg));
754 reg->section = TAILQ_LAST(&sh, section_head);
755 reg->root = sstrdup(r);
756 reg->subkey = sstrdup(words[3]);
757 reg->key = sstrdup(words[2]);
758 reg->flags = satoi(words[1]);
759 reg->value = sstrdup(words[0]);
760 TAILQ_INSERT_TAIL(&rh, reg, link);
762 free(__DECONST(char *, r));
763 clear_words();
764 return;
767 void
768 push_word (const char *w)
770 if (w && strlen(w))
771 words[idx++] = w;
772 else
773 words[idx++] = NULL;
774 return;
777 void
778 clear_words (void)
780 int i;
782 for (i = 0; i < idx; i++) {
783 if (words[i]) {
784 free(__DECONST(char *, words[i]));
787 idx = 0;
788 bzero(words, sizeof(words));
789 return;