inf.c revision 123620
1123475Swpaul/*
2123475Swpaul * $Id: inf.c,v 1.3 2003/11/30 21:58:16 winter Exp $
3123475Swpaul */
4123475Swpaul
5123475Swpaul#include <sys/cdefs.h>
6123475Swpaul__FBSDID("$FreeBSD: head/usr.sbin/ndiscvt/inf.c 123620 2003-12-18 03:51:21Z wpaul $");
7123475Swpaul
8123475Swpaul#include <stdio.h>
9123475Swpaul#include <stdlib.h>
10123475Swpaul#include <string.h>
11123475Swpaul#include <sys/types.h>
12123475Swpaul
13123475Swpaul#include <sys/queue.h>
14123475Swpaul
15123475Swpaul#include "inf.h"
16123475Swpaul
17123475Swpaulextern FILE *yyin;
18123475Swpaulint yyparse (void);
19123475Swpaul
20123475Swpaulconst char *words[W_MAX];	/* More than we'll need. */
21123475Swpaulint idx;
22123475Swpaul
23123475Swpaulstatic struct section_head sh;
24123475Swpaulstatic struct reg_head rh;
25123475Swpaulstatic struct assign_head ah;
26123475Swpaul
27123475Swpaulstatic char	*sstrdup	(const char *);
28123475Swpaulstatic struct assign
29123475Swpaul		*find_assign	(const char *, const char *);
30123475Swpaulstatic struct section
31123475Swpaul		*find_section	(const char *);
32123475Swpaulstatic void	dump_deviceids	(void);
33123475Swpaulstatic void	dump_pci_id	(const char *);
34123475Swpaulstatic void	dump_regvals	(void);
35123620Swpaulstatic void	dump_paramreg	(const struct section *,
36123620Swpaul				const struct reg *, int);
37123475Swpaul
38123475Swpaulstatic FILE	*ofp;
39123475Swpaul
40123475Swpaulint
41123475Swpaulinf_parse (FILE *fp, FILE *outfp)
42123475Swpaul{
43123475Swpaul	TAILQ_INIT(&sh);
44123475Swpaul	TAILQ_INIT(&rh);
45123475Swpaul	TAILQ_INIT(&ah);
46123475Swpaul
47123475Swpaul	ofp = outfp;
48123475Swpaul	yyin = fp;
49123475Swpaul	yyparse();
50123475Swpaul
51123475Swpaul	dump_deviceids();
52123475Swpaul	dump_regvals();
53123475Swpaul
54123475Swpaul	return (0);
55123475Swpaul}
56123475Swpaul
57123475Swpaulvoid
58123475Swpaulsection_add (const char *s)
59123475Swpaul{
60123475Swpaul	struct section *sec;
61123475Swpaul
62123475Swpaul	sec = malloc(sizeof(struct section));
63123475Swpaul	bzero(sec, sizeof(struct section));
64123475Swpaul	sec->name = s;
65123475Swpaul	TAILQ_INSERT_TAIL(&sh, sec, link);
66123475Swpaul
67123475Swpaul	return;
68123475Swpaul}
69123475Swpaul
70123475Swpaulstatic struct assign *
71123475Swpaulfind_assign (const char *s, const char *k)
72123475Swpaul{
73123475Swpaul	struct assign *assign;
74123475Swpaul	char newkey[256];
75123475Swpaul
76123475Swpaul	/* Deal with string section lookups. */
77123475Swpaul
78123475Swpaul	if (k != NULL && k[0] == '%') {
79123475Swpaul		bzero(newkey, sizeof(newkey));
80123475Swpaul		strncpy(newkey, k + 1, strlen(k) - 2);
81123475Swpaul		k = newkey;
82123475Swpaul	}
83123475Swpaul
84123475Swpaul	TAILQ_FOREACH(assign, &ah, link) {
85123475Swpaul		if (strcasecmp(assign->section->name, s) == 0) {
86123475Swpaul			if (k == NULL)
87123475Swpaul				return(assign);
88123475Swpaul			else
89123475Swpaul				if (strcasecmp(assign->key, k) == 0)
90123475Swpaul					return(assign);
91123475Swpaul		}
92123475Swpaul	}
93123475Swpaul	return(NULL);
94123475Swpaul}
95123475Swpaul
96123475Swpaulstatic const char *
97123475Swpaulstringcvt(const char *s)
98123475Swpaul{
99123475Swpaul	struct assign *manf;
100123475Swpaul
101123475Swpaul	manf = find_assign("strings", s);
102123475Swpaul	if (manf == NULL)
103123475Swpaul		return(s);
104123475Swpaul	return(manf->vals[0]);
105123475Swpaul}
106123475Swpaul
107123475Swpaulstruct section *
108123475Swpaulfind_section (const char *s)
109123475Swpaul{
110123475Swpaul	struct section *section;
111123475Swpaul
112123475Swpaul	TAILQ_FOREACH(section, &sh, link) {
113123475Swpaul		if (strcasecmp(section->name, s) == 0)
114123475Swpaul			return(section);
115123475Swpaul	}
116123475Swpaul	return(NULL);
117123475Swpaul}
118123475Swpaul
119123475Swpaulstatic void
120123475Swpauldump_pci_id(const char *s)
121123475Swpaul{
122123475Swpaul	char *p;
123123620Swpaul	char vidstr[7], didstr[7], subsysstr[14];
124123475Swpaul
125123475Swpaul	p = strcasestr(s, "VEN_");
126123475Swpaul	if (p == NULL)
127123475Swpaul		return;
128123475Swpaul	p += 4;
129123475Swpaul	strcpy(vidstr, "0x");
130123475Swpaul	strncat(vidstr, p, 4);
131123475Swpaul	p = strcasestr(s, "DEV_");
132123475Swpaul	if (p == NULL)
133123475Swpaul		return;
134123475Swpaul	p += 4;
135123475Swpaul	strcpy(didstr, "0x");
136123475Swpaul	strncat(didstr, p, 4);
137123475Swpaul	if (p == NULL)
138123475Swpaul		return;
139123620Swpaul	p = strcasestr(s, "SUBSYS_");
140123620Swpaul	if (p == NULL)
141123620Swpaul		strcpy(subsysstr, "0x00000000");
142123620Swpaul	else {
143123620Swpaul		p += 7;
144123620Swpaul		strcpy(subsysstr, "0x");
145123620Swpaul		strncat(subsysstr, p, 8);
146123620Swpaul	}
147123475Swpaul
148123620Swpaul	fprintf(ofp, "\t\\\n\t{ %s, %s, %s, ", vidstr, didstr, subsysstr);
149123475Swpaul	return;
150123475Swpaul}
151123475Swpaul
152123475Swpaulstatic void
153123475Swpauldump_deviceids()
154123475Swpaul{
155123475Swpaul	struct assign *manf, *dev;
156123475Swpaul	struct section *sec;
157123475Swpaul	struct assign *assign;
158123483Swpaul	char xpsec[256];
159123475Swpaul
160123475Swpaul	/* Find manufacturer name */
161123475Swpaul	manf = find_assign("Manufacturer", NULL);
162123475Swpaul
163123475Swpaul	/* Find manufacturer section */
164123483Swpaul	if (manf->vals[1] != NULL &&
165123511Swpaul	    (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
166123511Swpaul	    strcasecmp(manf->vals[1], "NTx86.5.1") == 0)) {
167123483Swpaul		/* Handle Windows XP INF files. */
168123483Swpaul		snprintf(xpsec, sizeof(xpsec), "%s.%s",
169123483Swpaul		    manf->vals[0], manf->vals[1]);
170123483Swpaul		sec = find_section(xpsec);
171123483Swpaul	} else
172123483Swpaul		sec = find_section(manf->vals[0]);
173123475Swpaul
174123475Swpaul	/* Emit start of device table */
175123475Swpaul	fprintf (ofp, "#define NDIS_DEV_TABLE");
176123475Swpaul
177123475Swpaul	/*
178123475Swpaul	 * Now run through all the device names listed
179123475Swpaul	 * in the manufacturer section and dump out the
180123475Swpaul	 * device descriptions and vendor/device IDs.
181123475Swpaul	 */
182123475Swpaul
183123475Swpaul	TAILQ_FOREACH(assign, &ah, link) {
184123475Swpaul		if (assign->section == sec) {
185123475Swpaul			dev = find_assign("strings", assign->key);
186123475Swpaul			/* Emit device IDs. */
187123475Swpaul			if (strcasestr(assign->vals[1], "PCI") != NULL)
188123475Swpaul				dump_pci_id(assign->vals[1]);
189123475Swpaul#ifdef notdef
190123475Swpaul			else if (strcasestr(assign->vals[1], "PCMCIA") != NULL)
191123475Swpaul				dump_pcmcia_id(assign->vals[1]);
192123475Swpaul#endif
193123475Swpaul			/* Emit device description */
194123480Swpaul			fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
195123475Swpaul		}
196123475Swpaul	}
197123475Swpaul
198123475Swpaul	/* Emit end of table */
199123475Swpaul
200123480Swpaul	fprintf(ofp, "\n\n");
201123480Swpaul
202123475Swpaul}
203123475Swpaul
204123475Swpaulstatic void
205123620Swpauldump_addreg(const char *s, int devidx)
206123475Swpaul{
207123475Swpaul	struct section *sec;
208123475Swpaul	struct reg *reg;
209123475Swpaul
210123475Swpaul	/* Find the addreg section */
211123475Swpaul	sec = find_section(s);
212123475Swpaul
213123475Swpaul	/* Dump all the keys defined in it. */
214123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
215123475Swpaul		/*
216123475Swpaul		 * Keys with an empty subkey are very easy to parse,
217123475Swpaul		 * so just deal with them here. If a parameter key
218123475Swpaul		 * of the same name also exists, prefer that one and
219123475Swpaul		 * skip this one.
220123475Swpaul		 */
221123475Swpaul		if (reg->section == sec) {
222123475Swpaul			if (reg->subkey == NULL) {
223123475Swpaul				fprintf(ofp, "\n\t{ \"%s\",", reg->key);
224123475Swpaul				fprintf(ofp,"\n\t\"%s \",", reg->key);
225123620Swpaul				fprintf(ofp, "\n\t{ \"%s\" }, %d },",
226123475Swpaul				    reg->value == NULL ? "" :
227123620Swpaul				    stringcvt(reg->value), devidx);
228123475Swpaul			} else if (strcasestr(reg->subkey,
229123475Swpaul			    "Ndi\\params") != NULL &&
230123475Swpaul			    strcasecmp(reg->key, "ParamDesc") == 0)
231123620Swpaul				dump_paramreg(sec, reg, devidx);
232123475Swpaul		}
233123475Swpaul	}
234123475Swpaul
235123475Swpaul	return;
236123475Swpaul}
237123475Swpaul
238123475Swpaulstatic void
239123475Swpauldump_enumreg(const struct section *s, const struct reg *r)
240123475Swpaul{
241123475Swpaul	struct reg *reg;
242123475Swpaul	char enumkey[256];
243123475Swpaul
244123475Swpaul	sprintf(enumkey, "%s\\enum", r->subkey);
245123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
246123475Swpaul		if (reg->section != s)
247123475Swpaul			continue;
248123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey))
249123475Swpaul			continue;
250123483Swpaul		fprintf(ofp, " [%s=%s]", reg->key,
251123483Swpaul		    stringcvt(reg->value));
252123475Swpaul	}
253123475Swpaul	return;
254123475Swpaul}
255123475Swpaul
256123475Swpaulstatic void
257123475Swpauldump_editreg(const struct section *s, const struct reg *r)
258123475Swpaul{
259123475Swpaul	struct reg *reg;
260123475Swpaul
261123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
262123475Swpaul		if (reg->section != s)
263123475Swpaul			continue;
264123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
265123475Swpaul			continue;
266123475Swpaul		if (strcasecmp(reg->key, "LimitText") == 0)
267123475Swpaul			fprintf(ofp, " [maxchars=%s]", reg->value);
268123475Swpaul		if (strcasecmp(reg->key, "Optional") == 0 &&
269123475Swpaul		    strcmp(reg->value, "1") == 0)
270123475Swpaul			fprintf(ofp, " [optional]");
271123475Swpaul	}
272123475Swpaul	return;
273123475Swpaul}
274123475Swpaul
275123475Swpaul/* Use this for int too */
276123475Swpaulstatic void
277123475Swpauldump_dwordreg(const struct section *s, const struct reg *r)
278123475Swpaul{
279123475Swpaul	struct reg *reg;
280123475Swpaul
281123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
282123475Swpaul		if (reg->section != s)
283123475Swpaul			continue;
284123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
285123475Swpaul			continue;
286123475Swpaul		if (strcasecmp(reg->key, "min") == 0)
287123475Swpaul			fprintf(ofp, " [min=%s]", reg->value);
288123475Swpaul		if (strcasecmp(reg->key, "max") == 0)
289123475Swpaul			fprintf(ofp, " [max=%s]", reg->value);
290123475Swpaul	}
291123475Swpaul	return;
292123475Swpaul}
293123475Swpaul
294123475Swpaulstatic void
295123620Swpauldump_defaultinfo(const struct section *s, const struct reg *r, int devidx)
296123475Swpaul{
297123475Swpaul	struct reg *reg;
298123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
299123475Swpaul		if (reg->section != s)
300123475Swpaul			continue;
301123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
302123475Swpaul			continue;
303123475Swpaul		if (strcasecmp(reg->key, "Default"))
304123475Swpaul			continue;
305123620Swpaul		fprintf(ofp, "\n\t{ \"%s\" }, %d },", reg->value == NULL ? "" :
306123620Swpaul		    reg->value, devidx);
307123475Swpaul			break;
308123475Swpaul	}
309123475Swpaul	return;
310123475Swpaul}
311123475Swpaul
312123475Swpaulstatic void
313123475Swpauldump_paramdesc(const struct section *s, const struct reg *r)
314123475Swpaul{
315123475Swpaul	struct reg *reg;
316123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
317123475Swpaul		if (reg->section != s)
318123475Swpaul			continue;
319123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
320123475Swpaul			continue;
321123475Swpaul		if (strcasecmp(reg->key, "ParamDesc"))
322123475Swpaul			continue;
323123475Swpaul		fprintf(ofp, "\n\t\"%s", stringcvt(r->value));
324123475Swpaul			break;
325123475Swpaul	}
326123475Swpaul	return;
327123475Swpaul}
328123475Swpaul
329123475Swpaulstatic void
330123475Swpauldump_typeinfo(const struct section *s, const struct reg *r)
331123475Swpaul{
332123475Swpaul	struct reg *reg;
333123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
334123475Swpaul		if (reg->section != s)
335123475Swpaul			continue;
336123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
337123475Swpaul			continue;
338123475Swpaul		if (strcasecmp(reg->key, "type"))
339123475Swpaul			continue;
340123475Swpaul		if (strcasecmp(reg->value, "dword") == 0 ||
341123475Swpaul		    strcasecmp(reg->value, "int") == 0)
342123475Swpaul			dump_dwordreg(s, r);
343123475Swpaul		if (strcasecmp(reg->value, "enum") == 0)
344123475Swpaul			dump_enumreg(s, r);
345123475Swpaul		if (strcasecmp(reg->value, "edit") == 0)
346123475Swpaul			dump_editreg(s, r);
347123475Swpaul	}
348123475Swpaul	return;
349123475Swpaul}
350123475Swpaul
351123475Swpaulstatic void
352123620Swpauldump_paramreg(const struct section *s, const struct reg *r, int devidx)
353123475Swpaul{
354123475Swpaul	const char *keyname;
355123475Swpaul
356123475Swpaul	keyname = r->subkey + strlen("Ndi\\params\\");
357123475Swpaul	fprintf(ofp, "\n\t{ \"%s\",", keyname);
358123475Swpaul	dump_paramdesc(s, r);
359123475Swpaul	dump_typeinfo(s, r);
360123475Swpaul	fprintf(ofp, "\",");
361123620Swpaul	dump_defaultinfo(s, r, devidx);
362123475Swpaul
363123475Swpaul	return;
364123475Swpaul}
365123475Swpaul
366123475Swpaulstatic void
367123475Swpauldump_regvals(void)
368123475Swpaul{
369123620Swpaul	struct assign *manf, *dev;
370123475Swpaul	struct section *sec;
371123475Swpaul	struct assign *assign;
372123475Swpaul	char sname[256];
373123620Swpaul	int i, is_winxp = 0, devidx = 0;
374123475Swpaul
375123475Swpaul	/* Find manufacturer name */
376123475Swpaul	manf = find_assign("Manufacturer", NULL);
377123475Swpaul
378123475Swpaul	/* Find manufacturer section */
379123483Swpaul	if (manf->vals[1] != NULL &&
380123511Swpaul	    (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
381123511Swpaul	    strcasecmp(manf->vals[1], "NTx86.5.1") == 0)) {
382123483Swpaul		is_winxp++;
383123483Swpaul		/* Handle Windows XP INF files. */
384123483Swpaul		snprintf(sname, sizeof(sname), "%s.%s",
385123483Swpaul		    manf->vals[0], manf->vals[1]);
386123483Swpaul		sec = find_section(sname);
387123483Swpaul	} else
388123483Swpaul		sec = find_section(manf->vals[0]);
389123475Swpaul
390123475Swpaul	/* Emit start of block */
391123475Swpaul	fprintf (ofp, "ndis_cfg ndis_regvals[] = {");
392123475Swpaul
393123475Swpaul	TAILQ_FOREACH(assign, &ah, link) {
394123475Swpaul		if (assign->section == sec) {
395123483Swpaul			/*
396123483Swpaul			 * Find all the AddReg sections.
397123483Swpaul			 * Look for section names with .NT, unless
398123483Swpaul			 * this is a WinXP .INF file.
399123483Swpaul			 */
400123511Swpaul			if (is_winxp) {
401123511Swpaul				sprintf(sname, "%s.NTx86", assign->vals[0]);
402123511Swpaul				dev = find_assign(sname, "AddReg");
403123511Swpaul				if (dev == NULL)
404123511Swpaul					dev = find_assign(assign->vals[0],
405123511Swpaul					    "AddReg");
406123511Swpaul			} else {
407123483Swpaul				sprintf(sname, "%s.NT", assign->vals[0]);
408123483Swpaul				dev = find_assign(sname, "AddReg");
409123483Swpaul			}
410123483Swpaul			/* Section not found. */
411123483Swpaul			if (dev == NULL)
412123483Swpaul				continue;
413123475Swpaul			for (i = 0; i < W_MAX; i++) {
414123475Swpaul				if (dev->vals[i] != NULL)
415123620Swpaul					dump_addreg(dev->vals[i], devidx);
416123475Swpaul			}
417123620Swpaul			devidx++;
418123475Swpaul		}
419123475Swpaul	}
420123475Swpaul
421123620Swpaul	fprintf(ofp, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
422123475Swpaul
423123475Swpaul	return;
424123475Swpaul}
425123475Swpaul
426123475Swpaulvoid
427123475Swpaulassign_add (const char *a)
428123475Swpaul{
429123475Swpaul	struct assign *assign;
430123475Swpaul	int i;
431123475Swpaul
432123475Swpaul	assign = malloc(sizeof(struct assign));
433123475Swpaul	bzero(assign, sizeof(struct assign));
434123475Swpaul	assign->section = TAILQ_LAST(&sh, section_head);
435123475Swpaul	assign->key = sstrdup(a);
436123475Swpaul	for (i = 0; i < idx; i++)
437123475Swpaul		assign->vals[(idx - 1) - i] = sstrdup(words[i]);
438123475Swpaul	TAILQ_INSERT_TAIL(&ah, assign, link);
439123475Swpaul
440123475Swpaul	clear_words();
441123475Swpaul	return;
442123475Swpaul}
443123475Swpaul
444123475Swpaulvoid
445123475Swpauldefine_add (const char *d __unused)
446123475Swpaul{
447123475Swpaul#ifdef notdef
448123475Swpaul	fprintf(stderr, "define \"%s\"\n", d);
449123475Swpaul#endif
450123475Swpaul	return;
451123475Swpaul}
452123475Swpaul
453123475Swpaulstatic char *
454123475Swpaulsstrdup(const char *str)
455123475Swpaul{
456123475Swpaul	if (str != NULL && strlen(str))
457123475Swpaul		return (strdup(str));
458123475Swpaul	return (NULL);
459123475Swpaul}
460123475Swpaul
461123475Swpaulstatic int
462123475Swpaulsatoi (const char *nptr)
463123475Swpaul{
464123475Swpaul	if (nptr != NULL && strlen(nptr))
465123475Swpaul		return (atoi(nptr));
466123475Swpaul	return (0);
467123475Swpaul}
468123475Swpaul
469123475Swpaulvoid
470123475Swpaulregkey_add (const char *r)
471123475Swpaul{
472123475Swpaul	struct reg *reg;
473123475Swpaul
474123475Swpaul	reg = malloc(sizeof(struct reg));
475123475Swpaul	bzero(reg, sizeof(struct reg));
476123475Swpaul	reg->section = TAILQ_LAST(&sh, section_head);
477123475Swpaul	reg->root = sstrdup(r);
478123475Swpaul	reg->subkey = sstrdup(words[3]);
479123475Swpaul	reg->key = sstrdup(words[2]);
480123475Swpaul	reg->flags = satoi(words[1]);
481123475Swpaul	reg->value = sstrdup(words[0]);
482123475Swpaul	TAILQ_INSERT_TAIL(&rh, reg, link);
483123475Swpaul
484123475Swpaul	free(__DECONST(char *, r));
485123475Swpaul	clear_words();
486123475Swpaul	return;
487123475Swpaul}
488123475Swpaul
489123475Swpaulvoid
490123475Swpaulpush_word (const char *w)
491123475Swpaul{
492123475Swpaul	if (w && strlen(w))
493123475Swpaul		words[idx++] = w;
494123475Swpaul	else
495123475Swpaul		words[idx++] = NULL;
496123475Swpaul	return;
497123475Swpaul}
498123475Swpaul
499123475Swpaulvoid
500123475Swpaulclear_words (void)
501123475Swpaul{
502123475Swpaul	int i;
503123475Swpaul
504123475Swpaul	for (i = 0; i < idx; i++) {
505123475Swpaul		if (words[i]) {
506123475Swpaul			free(__DECONST(char *, words[i]));
507123475Swpaul		}
508123475Swpaul	}
509123475Swpaul	idx = 0;
510123475Swpaul	bzero(words, sizeof(words));
511123475Swpaul	return;
512123475Swpaul}
513