]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/ndiscvt/inf.c
This commit was generated by cvs2svn to compensate for changes in r145673,
[FreeBSD/FreeBSD.git] / usr.sbin / ndiscvt / inf.c
1 /*
2  * Copyright (c) 2003
3  *      Bill Paul <wpaul@windriver.com>.  All rights reserved.
4  *
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.
19  *
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.
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/types.h>
40
41 #include <sys/queue.h>
42
43 #include "inf.h"
44
45 extern FILE *yyin;
46 int yyparse (void);
47
48 const char *words[W_MAX];       /* More than we'll need. */
49 int idx;
50
51 static struct section_head sh;
52 static struct reg_head rh;
53 static struct assign_head ah;
54
55 static char     *sstrdup        (const char *);
56 static struct assign
57                 *find_assign    (const char *, const char *);
58 static struct section
59                 *find_section   (const char *);
60 static void     dump_deviceids_pci      (void);
61 static void     dump_deviceids_pcmcia   (void);
62 static void     dump_pci_id     (const char *);
63 static void     dump_pcmcia_id  (const char *);
64 static void     dump_regvals    (void);
65 static void     dump_paramreg   (const struct section *,
66                                 const struct reg *, int);
67
68 static FILE     *ofp;
69
70 int
71 inf_parse (FILE *fp, FILE *outfp)
72 {
73         TAILQ_INIT(&sh);
74         TAILQ_INIT(&rh);
75         TAILQ_INIT(&ah);
76
77         ofp = outfp;
78         yyin = fp;
79         yyparse();
80
81         dump_deviceids_pci();
82         dump_deviceids_pcmcia();
83         fprintf(outfp, "#ifdef NDIS_REGVALS\n");
84         dump_regvals();
85         fprintf(outfp, "#endif /* NDIS_REGVALS */\n");
86
87         return (0);
88 }
89
90 void
91 section_add (const char *s)
92 {
93         struct section *sec;
94
95         sec = malloc(sizeof(struct section));
96         bzero(sec, sizeof(struct section));
97         sec->name = s;
98         TAILQ_INSERT_TAIL(&sh, sec, link);
99
100         return;
101 }
102
103 static struct assign *
104 find_assign (const char *s, const char *k)
105 {
106         struct assign *assign;
107         char newkey[256];
108
109         /* Deal with string section lookups. */
110
111         if (k != NULL && k[0] == '%') {
112                 bzero(newkey, sizeof(newkey));
113                 strncpy(newkey, k + 1, strlen(k) - 2);
114                 k = newkey;
115         }
116
117         TAILQ_FOREACH(assign, &ah, link) {
118                 if (strcasecmp(assign->section->name, s) == 0) {
119                         if (k == NULL)
120                                 return(assign);
121                         else
122                                 if (strcasecmp(assign->key, k) == 0)
123                                         return(assign);
124                 }
125         }
126         return(NULL);
127 }
128
129 static const char *
130 stringcvt(const char *s)
131 {
132         struct assign *manf;
133
134         manf = find_assign("strings", s);
135         if (manf == NULL)
136                 return(s);
137         return(manf->vals[0]);
138 }
139
140 struct section *
141 find_section (const char *s)
142 {
143         struct section *section;
144
145         TAILQ_FOREACH(section, &sh, link) {
146                 if (strcasecmp(section->name, s) == 0)
147                         return(section);
148         }
149         return(NULL);
150 }
151
152 static void
153 dump_pcmcia_id(const char *s)
154 {
155         char *manstr, *devstr;
156         char *p0, *p;
157
158         p0 = __DECONST(char *, s);
159
160         p = strchr(p0, '\\');
161         if (p == NULL)
162                 return;
163         p0 = p + 1;
164
165         p = strchr(p0, '-');
166         if (p == NULL)
167                 return;
168         *p = '\0';
169
170         manstr = p0;
171
172         /* Convert any underscores to spaces. */
173
174         while (*p0 != '\0') {
175                 if (*p0 == '_')
176                         *p0 = ' ';
177                 p0++;
178         }
179
180         p0 = p + 1;
181         p = strchr(p0, '-');
182         if (p == NULL)
183                 return;
184         *p = '\0';
185
186         devstr = p0;
187
188         /* Convert any underscores to spaces. */
189
190         while (*p0 != '\0') {
191                 if (*p0 == '_')
192                         *p0 = ' ';
193                 p0++;
194         }
195
196         fprintf(ofp, "\t\\\n\t{ \"%s\", \"%s\", ", manstr, devstr);
197         return;
198 }
199
200 static void
201 dump_pci_id(const char *s)
202 {
203         char *p;
204         char vidstr[7], didstr[7], subsysstr[14];
205
206         p = strcasestr(s, "VEN_");
207         if (p == NULL)
208                 return;
209         p += 4;
210         strcpy(vidstr, "0x");
211         strncat(vidstr, p, 4);
212         p = strcasestr(s, "DEV_");
213         if (p == NULL)
214                 return;
215         p += 4;
216         strcpy(didstr, "0x");
217         strncat(didstr, p, 4);
218         if (p == NULL)
219                 return;
220         p = strcasestr(s, "SUBSYS_");
221         if (p == NULL)
222                 strcpy(subsysstr, "0x00000000");
223         else {
224                 p += 7;
225                 strcpy(subsysstr, "0x");
226                 strncat(subsysstr, p, 8);
227         }
228
229         fprintf(ofp, "\t\\\n\t{ %s, %s, %s, ", vidstr, didstr, subsysstr);
230         return;
231 }
232
233 static void
234 dump_deviceids_pci()
235 {
236         struct assign *manf, *dev;
237         struct section *sec;
238         struct assign *assign;
239         char xpsec[256];
240         int found = 0;
241
242         /* Find manufacturer name */
243         manf = find_assign("Manufacturer", NULL);
244
245         /* Find manufacturer section */
246         if (manf->vals[1] != NULL &&
247             (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
248             strcasecmp(manf->vals[1], "NTx86") == 0 ||
249             strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
250             strcasecmp(manf->vals[1], "NTamd64") == 0)) {
251                 /* Handle Windows XP INF files. */
252                 snprintf(xpsec, sizeof(xpsec), "%s.%s",
253                     manf->vals[0], manf->vals[1]);
254                 sec = find_section(xpsec);
255         } else
256                 sec = find_section(manf->vals[0]);
257
258         /* See if there are any PCI device definitions. */
259
260         TAILQ_FOREACH(assign, &ah, link) {
261                 if (assign->section == sec) {
262                         dev = find_assign("strings", assign->key);
263                         if (strcasestr(assign->vals[1], "PCI") != NULL) {
264                                 found++;
265                                 break;
266                         }
267                 }
268         }
269
270         if (found == 0)
271                 return;
272
273         found = 0;
274
275         /* Emit start of PCI device table */
276         fprintf (ofp, "#define NDIS_PCI_DEV_TABLE");
277
278 retry:
279
280         /*
281          * Now run through all the device names listed
282          * in the manufacturer section and dump out the
283          * device descriptions and vendor/device IDs.
284          */
285
286         TAILQ_FOREACH(assign, &ah, link) {
287                 if (assign->section == sec) {
288                         dev = find_assign("strings", assign->key);
289                         /* Emit device IDs. */
290                         if (strcasestr(assign->vals[1], "PCI") != NULL)
291                                 dump_pci_id(assign->vals[1]);
292                         else
293                                 continue;
294                         /* Emit device description */
295                         fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
296                         found++;
297                 }
298         }
299
300         /* Someone tried to fool us. Shame on them. */
301         if (!found) {
302                 found++;
303                 sec = find_section(manf->vals[0]);
304                 goto retry;
305         }
306
307         /* Emit end of table */
308
309         fprintf(ofp, "\n\n");
310
311 }
312
313 static void
314 dump_deviceids_pcmcia()
315 {
316         struct assign *manf, *dev;
317         struct section *sec;
318         struct assign *assign;
319         char xpsec[256];
320         int found = 0;
321
322         /* Find manufacturer name */
323         manf = find_assign("Manufacturer", NULL);
324
325         /* Find manufacturer section */
326         if (manf->vals[1] != NULL &&
327             (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
328             strcasecmp(manf->vals[1], "NTx86") == 0 ||
329             strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
330             strcasecmp(manf->vals[1], "NTamd64") == 0)) {
331                 /* Handle Windows XP INF files. */
332                 snprintf(xpsec, sizeof(xpsec), "%s.%s",
333                     manf->vals[0], manf->vals[1]);
334                 sec = find_section(xpsec);
335         } else
336                 sec = find_section(manf->vals[0]);
337
338         /* See if there are any PCMCIA device definitions. */
339
340         TAILQ_FOREACH(assign, &ah, link) {
341                 if (assign->section == sec) {
342                         dev = find_assign("strings", assign->key);
343                         if (strcasestr(assign->vals[1], "PCMCIA") != NULL) {
344                                 found++;
345                                 break;
346                         }
347                 }
348         }
349
350         if (found == 0)
351                 return;
352
353         found = 0;
354
355         /* Emit start of PCMCIA device table */
356         fprintf (ofp, "#define NDIS_PCMCIA_DEV_TABLE");
357
358 retry:
359
360         /*
361          * Now run through all the device names listed
362          * in the manufacturer section and dump out the
363          * device descriptions and vendor/device IDs.
364          */
365
366         TAILQ_FOREACH(assign, &ah, link) {
367                 if (assign->section == sec) {
368                         dev = find_assign("strings", assign->key);
369                         /* Emit device IDs. */
370                         if (strcasestr(assign->vals[1], "PCMCIA") != NULL)
371                                 dump_pcmcia_id(assign->vals[1]);
372                         else
373                                 continue;
374                         /* Emit device description */
375                         fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
376                         found++;
377                 }
378         }
379
380         /* Someone tried to fool us. Shame on them. */
381         if (!found) {
382                 found++;
383                 sec = find_section(manf->vals[0]);
384                 goto retry;
385         }
386
387         /* Emit end of table */
388
389         fprintf(ofp, "\n\n");
390
391 }
392
393 static void
394 dump_addreg(const char *s, int devidx)
395 {
396         struct section *sec;
397         struct reg *reg;
398
399         /* Find the addreg section */
400         sec = find_section(s);
401
402         /* Dump all the keys defined in it. */
403         TAILQ_FOREACH(reg, &rh, link) {
404                 /*
405                  * Keys with an empty subkey are very easy to parse,
406                  * so just deal with them here. If a parameter key
407                  * of the same name also exists, prefer that one and
408                  * skip this one.
409                  */
410                 if (reg->section == sec) {
411                         if (reg->subkey == NULL) {
412                                 fprintf(ofp, "\n\t{ \"%s\",", reg->key);
413                                 fprintf(ofp,"\n\t\"%s \",", reg->key);
414                                 fprintf(ofp, "\n\t{ \"%s\" }, %d },",
415                                     reg->value == NULL ? "" :
416                                     stringcvt(reg->value), devidx);
417                         } else if (strncasecmp(reg->subkey,
418                             "Ndi\\params", strlen("Ndi\\params")-1) == 0 &&
419                             (reg->key != NULL && strcasecmp(reg->key,
420                             "ParamDesc") == 0))
421                                 dump_paramreg(sec, reg, devidx);
422                 }
423         }
424
425         return;
426 }
427
428 static void
429 dump_enumreg(const struct section *s, const struct reg *r)
430 {
431         struct reg *reg;
432         char enumkey[256];
433
434         sprintf(enumkey, "%s\\enum", r->subkey);
435         TAILQ_FOREACH(reg, &rh, link) {
436                 if (reg->section != s)
437                         continue;
438                 if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey))
439                         continue;
440                 fprintf(ofp, " [%s=%s]", reg->key,
441                     stringcvt(reg->value));
442         }
443         return;
444 }
445
446 static void
447 dump_editreg(const struct section *s, const struct reg *r)
448 {
449         struct reg *reg;
450
451         TAILQ_FOREACH(reg, &rh, link) {
452                 if (reg->section != s)
453                         continue;
454                 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
455                         continue;
456                 if (reg->key == NULL)
457                         continue;
458                 if (strcasecmp(reg->key, "LimitText") == 0)
459                         fprintf(ofp, " [maxchars=%s]", reg->value);
460                 if (strcasecmp(reg->key, "Optional") == 0 &&
461                     strcmp(reg->value, "1") == 0)
462                         fprintf(ofp, " [optional]");
463         }
464         return;
465 }
466
467 /* Use this for int too */
468 static void
469 dump_dwordreg(const struct section *s, const struct reg *r)
470 {
471         struct reg *reg;
472
473         TAILQ_FOREACH(reg, &rh, link) {
474                 if (reg->section != s)
475                         continue;
476                 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
477                         continue;
478                 if (reg->key == NULL)
479                         continue;
480                 if (strcasecmp(reg->key, "min") == 0)
481                         fprintf(ofp, " [min=%s]", reg->value);
482                 if (strcasecmp(reg->key, "max") == 0)
483                         fprintf(ofp, " [max=%s]", reg->value);
484         }
485         return;
486 }
487
488 static void
489 dump_defaultinfo(const struct section *s, const struct reg *r, int devidx)
490 {
491         struct reg *reg;
492         TAILQ_FOREACH(reg, &rh, link) {
493                 if (reg->section != s)
494                         continue;
495                 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
496                         continue;
497                 if (reg->key == NULL || strcasecmp(reg->key, "Default"))
498                         continue;
499                 fprintf(ofp, "\n\t{ \"%s\" }, %d },", reg->value == NULL ? "" :
500                     stringcvt(reg->value), devidx);
501                         break;
502         }
503         return;
504 }
505
506 static void
507 dump_paramdesc(const struct section *s, const struct reg *r)
508 {
509         struct reg *reg;
510         TAILQ_FOREACH(reg, &rh, link) {
511                 if (reg->section != s)
512                         continue;
513                 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
514                         continue;
515                 if (reg->key == NULL || strcasecmp(reg->key, "ParamDesc"))
516                         continue;
517                 fprintf(ofp, "\n\t\"%s", stringcvt(r->value));
518                         break;
519         }
520         return;
521 }
522
523 static void
524 dump_typeinfo(const struct section *s, const struct reg *r)
525 {
526         struct reg *reg;
527         TAILQ_FOREACH(reg, &rh, link) {
528                 if (reg->section != s)
529                         continue;
530                 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
531                         continue;
532                 if (reg->key == NULL)
533                         continue;
534                 if (strcasecmp(reg->key, "type"))
535                         continue;
536                 if (strcasecmp(reg->value, "dword") == 0 ||
537                     strcasecmp(reg->value, "int") == 0)
538                         dump_dwordreg(s, r);
539                 if (strcasecmp(reg->value, "enum") == 0)
540                         dump_enumreg(s, r);
541                 if (strcasecmp(reg->value, "edit") == 0)
542                         dump_editreg(s, r);
543         }
544         return;
545 }
546
547 static void
548 dump_paramreg(const struct section *s, const struct reg *r, int devidx)
549 {
550         const char *keyname;
551
552         keyname = r->subkey + strlen("Ndi\\params\\");
553         fprintf(ofp, "\n\t{ \"%s\",", keyname);
554         dump_paramdesc(s, r);
555         dump_typeinfo(s, r);
556         fprintf(ofp, "\",");
557         dump_defaultinfo(s, r, devidx);
558
559         return;
560 }
561
562 static void
563 dump_regvals(void)
564 {
565         struct assign *manf, *dev;
566         struct section *sec;
567         struct assign *assign;
568         char sname[256];
569         int found = 0, i, is_winxp = 0, is_winnt = 0, devidx = 0;
570
571         /* Find signature to check for special case of WinNT. */
572         assign = find_assign("version", "signature");
573         if (strcasecmp(assign->vals[0], "$windows nt$") == 0)
574                 is_winnt++;
575
576         /* Find manufacturer name */
577         manf = find_assign("Manufacturer", NULL);
578
579         /* Find manufacturer section */
580         if (manf->vals[1] != NULL &&
581             (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
582             strcasecmp(manf->vals[1], "NTx86") == 0 ||
583             strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
584             strcasecmp(manf->vals[1], "NTamd64") == 0)) {
585                 is_winxp++;
586                 /* Handle Windows XP INF files. */
587                 snprintf(sname, sizeof(sname), "%s.%s",
588                     manf->vals[0], manf->vals[1]);
589                 sec = find_section(sname);
590         } else
591                 sec = find_section(manf->vals[0]);
592
593         /* Emit start of block */
594         fprintf (ofp, "ndis_cfg ndis_regvals[] = {");
595
596 retry:
597
598         TAILQ_FOREACH(assign, &ah, link) {
599                 if (assign->section == sec) {
600                         found++;
601                         /*
602                          * Find all the AddReg sections.
603                          * Look for section names with .NT, unless
604                          * this is a WinXP .INF file.
605                          */
606
607                         if (is_winxp) {
608                                 sprintf(sname, "%s.NTx86", assign->vals[0]);
609                                 dev = find_assign(sname, "AddReg");
610                                 if (dev == NULL) {
611                                         sprintf(sname, "%s.NT",
612                                             assign->vals[0]);
613                                         dev = find_assign(sname, "AddReg");
614                                 }
615                                 if (dev == NULL)
616                                         dev = find_assign(assign->vals[0],
617                                             "AddReg");
618                         } else {
619                                 sprintf(sname, "%s.NT", assign->vals[0]);
620                                 dev = find_assign(sname, "AddReg");
621                                 if (dev == NULL && is_winnt)
622                                         dev = find_assign(assign->vals[0],
623                                             "AddReg");
624                         }
625                         /* Section not found. */
626                         if (dev == NULL)
627                                 continue;
628                         for (i = 0; i < W_MAX; i++) {
629                                 if (dev->vals[i] != NULL)
630                                         dump_addreg(dev->vals[i], devidx);
631                         }
632                         devidx++;
633                 }
634         }
635
636         if (!found) {
637                 sec = find_section(manf->vals[0]);
638                 is_winxp = 0;
639                 found++;
640                 goto retry;
641         }
642
643         fprintf(ofp, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
644
645         return;
646 }
647
648 void
649 assign_add (const char *a)
650 {
651         struct assign *assign;
652         int i;
653
654         assign = malloc(sizeof(struct assign));
655         bzero(assign, sizeof(struct assign));
656         assign->section = TAILQ_LAST(&sh, section_head);
657         assign->key = sstrdup(a);
658         for (i = 0; i < idx; i++)
659                 assign->vals[(idx - 1) - i] = sstrdup(words[i]);
660         TAILQ_INSERT_TAIL(&ah, assign, link);
661
662         clear_words();
663         return;
664 }
665
666 void
667 define_add (const char *d __unused)
668 {
669 #ifdef notdef
670         fprintf(stderr, "define \"%s\"\n", d);
671 #endif
672         return;
673 }
674
675 static char *
676 sstrdup(const char *str)
677 {
678         if (str != NULL && strlen(str))
679                 return (strdup(str));
680         return (NULL);
681 }
682
683 static int
684 satoi (const char *nptr)
685 {
686         if (nptr != NULL && strlen(nptr))
687                 return (atoi(nptr));
688         return (0);
689 }
690
691 void
692 regkey_add (const char *r)
693 {
694         struct reg *reg;
695
696         reg = malloc(sizeof(struct reg));
697         bzero(reg, sizeof(struct reg));
698         reg->section = TAILQ_LAST(&sh, section_head);
699         reg->root = sstrdup(r);
700         reg->subkey = sstrdup(words[3]);
701         reg->key = sstrdup(words[2]);
702         reg->flags = satoi(words[1]);
703         reg->value = sstrdup(words[0]);
704         TAILQ_INSERT_TAIL(&rh, reg, link);
705
706         free(__DECONST(char *, r));
707         clear_words();
708         return;
709 }
710
711 void
712 push_word (const char *w)
713 {
714         if (w && strlen(w))
715                 words[idx++] = w;
716         else
717                 words[idx++] = NULL;
718         return;
719 }
720
721 void
722 clear_words (void)
723 {
724         int i;
725
726         for (i = 0; i < idx; i++) {
727                 if (words[i]) {
728                         free(__DECONST(char *, words[i]));
729                 }
730         }
731         idx = 0;
732         bzero(words, sizeof(words));
733         return;
734 }