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