/* * getdb.c - Read system definitions from database file * * Copyright (C) 1998-2003 Gero Kuhlmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: getdb.c,v 1.6 2003/03/09 00:43:08 gkminix Exp $ */ #include #include #include "makerom.h" #include "doconfig.h" #include "protini.h" /* Variables private to this module */ static struct bootdef bootd; /* boot definition record */ static char *protini = NULL; /* protocol.ini contents */ /* * Table containing option names for "ldoptsX" parameters. */ static struct { char *name; int boolval; int intmin, intmax; int *optptr[MAXLOADERS]; } opttbl[] = { { "useint18", TRUE, 0, 0, {&bootd.loaders[0].useint18, &bootd.loaders[1].useint18, &bootd.loaders[2].useint18}}, { "cardinst", TRUE, 0, 0, {&bootd.loaders[0].cardinst, &bootd.loaders[1].cardinst, &bootd.loaders[2].cardinst}}, { "bootask", TRUE, 0, 0, {&bootd.loaders[0].bootask, &bootd.loaders[1].bootask, &bootd.loaders[2].bootask}}, { "asktime", FALSE, 0, 31, {&bootd.loaders[0].asktime, &bootd.loaders[0].asktime, &bootd.loaders[0].asktime}}, {NULL, FALSE, 0, 0, {NULL, NULL, NULL}} }; /* * Read bootrom loader options. This routine gets called everytime * a "ldoptsX" parameter is found in the database file. */ static char *readopts(name, arg) char *name; char *arg; { char *tok, *val, *cp; int i, num; long l; /* Isolate loader number from parameter name */ assert(strlen(name) == 7 && isdigit(name[6])); num = name[6] - '1'; assert(num >= 0 && num < MAXLOADERS); /* Find each option in the list */ tok = strtok(arg, ","); while (tok) { /* Skip leading blanks */ while (*tok && (*tok == ' ' || *tok == '\t')) tok++; cp = tok; /* Find end of option name */ while (*cp && (*cp != ' ' && *cp != '\t')) cp++; if (*cp) { /* Skip trailing blanks */ while (*cp && (*cp == ' ' || *cp == '\t')) *(cp++) = '\0'; if (*cp && *(cp++) != '=') return("invalid characters following option name"); } /* Find option value */ val = NULL; if (*cp == '=') { /* Skip leading blanks of option value */ while (*cp && (*cp == ' ' || *cp == '\t')) cp++; if (!*cp) return("missing option value"); val = cp; /* Find end of option value */ while (*cp && (*cp != ' ' && *cp != '\t')) { *cp = toupper(*cp); cp++; } if (*cp) { /* Skip trailing blanks */ while (*cp && (*cp == ' ' || *cp == '\t')) *(cp++) = '\0'; if (*cp) return("invalid characters following option value"); } } /* Find option name in list */ for (i = 0; opttbl[i].name != NULL; i++) if (!strcmp(tok, opttbl[i].name)) break; if (opttbl[i].name == NULL) return("invalid option"); /* Set option value */ if (opttbl[i].boolval) { if (!strcmp(val, "TRUE")) *opttbl[i].optptr[num] = TRUE; else if (!strcmp(val, "FALSE")) *opttbl[i].optptr[num] = FALSE; else return("invalid boolean option value"); } else { l = strtol(val, &cp, 10); if (cp != NULL && *cp) return("invalid integer option value"); if (l < opttbl[i].intmin || l > opttbl[i].intmax) return("integer option value out of range"); *opttbl[i].optptr[num] = l; } /* Proceed with next option */ tok = strtok(NULL, ","); } return(NULL); } /* Available network driver interface types */ static char *dtypes[] = { "packet driver", "ndis driver", "undi driver", NULL }; /* Available bus types */ static char *btypes[] = { "ISA", "EISA", "MCA", "PCI", NULL }; /* Available types for output file */ static char *ftypes[] = { "binary", "intel hex", "motorola hex", "tektronix hex", "flashcard", "flash", NULL }; /* Parameters in each bootrom section of database file */ static struct paramdef dbparams[] = { /* General bootrom parameters */ { "kernel", par_string, NULL, {&bootd.kernelname}}, { "bustype", par_enum, btypes, {(char **)&bootd.bus_type}}, { "pcivendor", par_int, NULL, {(char **)&bootd.pci_vendid}}, { "pcidevice", par_int, NULL, {(char **)&bootd.pci_devid}}, { "pnpdevid", par_string, NULL, {&bootd.pnp_devid}}, { "netdriver", par_string, NULL, {&bootd.netdrv.name}}, { "netdrvtype", par_enum, dtypes, {(char **)&bootd.netdrv.drivertype}}, #if MAXLOADERS < 3 #error Invalid number of loaders #endif /* Parameters for defining loaders */ { "loader1", par_string, NULL, {&bootd.loaders[0].name}}, { "loader2", par_string, NULL, {&bootd.loaders[1].name}}, { "loader3", par_string, NULL, {&bootd.loaders[2].name}}, { "outname1", par_string, NULL, {&bootd.loaders[0].outname}}, { "outname2", par_string, NULL, {&bootd.loaders[1].outname}}, { "outname3", par_string, NULL, {&bootd.loaders[2].outname}}, { "outsize1", par_int, NULL, {(char **)&bootd.loaders[0].outsize}}, { "outsize2", par_int, NULL, {(char **)&bootd.loaders[1].outsize}}, { "outsize3", par_int, NULL, {(char **)&bootd.loaders[2].outsize}}, { "outtype1", par_enum, ftypes, {(char **)&bootd.loaders[0].outtype}}, { "outtype2", par_enum, ftypes, {(char **)&bootd.loaders[1].outtype}}, { "outtype3", par_enum, ftypes, {(char **)&bootd.loaders[2].outtype}}, { "ldopts1", par_proc, NULL, {(char **)&readopts}}, { "ldopts2", par_proc, NULL, {(char **)&readopts}}, { "ldopts3", par_proc, NULL, {(char **)&readopts}}, #if MAXPROGS < 8 #error Invalid number of drivers #endif /* Parameters for packet driver interface */ { "pktdrvidx", par_int, NULL, {(char **)&bootd.netdrv.driverdefs.pd.drvindex}}, { "pdprog0", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.prognames[0]}}, { "pdprog1", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.prognames[1]}}, { "pdprog2", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.prognames[2]}}, { "pdprog3", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.prognames[3]}}, { "pdprog4", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.prognames[4]}}, { "pdprog5", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.prognames[5]}}, { "pdprog6", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.prognames[6]}}, { "pdprog7", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.prognames[7]}}, { "pdargs0", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.progargs[0]}}, { "pdargs1", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.progargs[1]}}, { "pdargs2", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.progargs[2]}}, { "pdargs3", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.progargs[3]}}, { "pdargs4", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.progargs[4]}}, { "pdargs5", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.progargs[5]}}, { "pdargs6", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.progargs[6]}}, { "pdargs7", par_string, NULL, {&bootd.netdrv.driverdefs.pd.progs.progargs[7]}}, { "pdminsize0", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.minsizes[0]}}, { "pdminsize1", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.minsizes[1]}}, { "pdminsize2", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.minsizes[2]}}, { "pdminsize3", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.minsizes[3]}}, { "pdminsize4", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.minsizes[4]}}, { "pdminsize5", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.minsizes[5]}}, { "pdminsize6", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.minsizes[6]}}, { "pdminsize7", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.minsizes[7]}}, { "pdmaxsize0", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.maxsizes[0]}}, { "pdmaxsize1", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.maxsizes[1]}}, { "pdmaxsize2", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.maxsizes[2]}}, { "pdmaxsize3", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.maxsizes[3]}}, { "pdmaxsize4", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.maxsizes[4]}}, { "pdmaxsize5", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.maxsizes[5]}}, { "pdmaxsize6", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.maxsizes[6]}}, { "pdmaxsize7", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.pd.progs.maxsizes[7]}}, /* Parameters for NDIS interface */ { "protini", par_string, NULL, {&protini}}, { "ndisdrvidx", par_int, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.drvindex}}, { "ndprog0", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.prognames[0]}}, { "ndprog1", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.prognames[1]}}, { "ndprog2", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.prognames[2]}}, { "ndprog3", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.prognames[3]}}, { "ndprog4", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.prognames[4]}}, { "ndprog5", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.prognames[5]}}, { "ndprog6", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.prognames[6]}}, { "ndprog7", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.prognames[7]}}, { "ndargs0", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.progargs[0]}}, { "ndargs1", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.progargs[1]}}, { "ndargs2", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.progargs[2]}}, { "ndargs3", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.progargs[3]}}, { "ndargs4", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.progargs[4]}}, { "ndargs5", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.progargs[5]}}, { "ndargs6", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.progargs[6]}}, { "ndargs7", par_string, NULL, {&bootd.netdrv.driverdefs.ndis.progs.progargs[7]}}, { "ndminsize0", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.minsizes[0]}}, { "ndminsize1", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.minsizes[1]}}, { "ndminsize2", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.minsizes[2]}}, { "ndminsize3", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.minsizes[3]}}, { "ndminsize4", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.minsizes[4]}}, { "ndminsize5", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.minsizes[5]}}, { "ndminsize6", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.minsizes[6]}}, { "ndminsize7", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.minsizes[7]}}, { "ndmaxsize0", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.maxsizes[0]}}, { "ndmaxsize1", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.maxsizes[1]}}, { "ndmaxsize2", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.maxsizes[2]}}, { "ndmaxsize3", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.maxsizes[3]}}, { "ndmaxsize4", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.maxsizes[4]}}, { "ndmaxsize5", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.maxsizes[5]}}, { "ndmaxsize6", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.maxsizes[6]}}, { "ndmaxsize7", par_long, NULL, {(char **)&bootd.netdrv.driverdefs.ndis.progs.maxsizes[7]}}, /* Parameters for UNDI interface */ { "undiprog", par_string, NULL, {&bootd.netdrv.driverdefs.undi.name}}, { NULL, par_null, NULL, {NULL}} }; /* * Check and reorder a list of DOS programs */ static void checkprogs(pdp, drvindex, namebuf) struct progdef *pdp; int *drvindex; char *namebuf; { int i, j; char *configdir; pdp->prognum = 0; for (i = 0, j = -1; i < MAXPROGS; i++) { if (pdp->prognames[i] != NULL) { if (i == *drvindex) configdir = config.netdrvdir; else configdir = config.utilsdir; checkaccess(&(pdp->prognames[i]), configdir); if (pdp->prognames[i] == NULL) { prnerr2("program %d invalid in section <%s>", i, namebuf); exit(EXIT_DB); } } if (pdp->prognames[i] == NULL) { if (pdp->progargs[i] != NULL) { free(pdp->progargs[i]); pdp->progargs[i] = NULL; } if (j < 0) j = i; } else if (j >= 0) { if (i == *drvindex) *drvindex = j; pdp->prognames[j] = pdp->prognames[i]; pdp->progargs[j] = pdp->progargs[i]; pdp->minsizes[j] = pdp->minsizes[i]; pdp->maxsizes[j] = pdp->maxsizes[i]; pdp->prognames[i] = NULL; pdp->progargs[i] = NULL; pdp->minsizes[i] = -1L; pdp->maxsizes[i] = -1L; pdp->prognum++; i = j; j = -1; } else pdp->prognum++; } if (*drvindex < 0 || *drvindex >= pdp->prognum) { prnerr2("network driver index %d invalid in section <%s>", *drvindex, namebuf); exit(EXIT_DB); } for (i = 0; i < pdp->prognum; i++) { if (pdp->minsizes[i] < 0L) pdp->minsizes[i] = -1L; if (pdp->maxsizes[i] < 0L) pdp->maxsizes[i] = -1L; if (pdp->maxsizes[i] == 0L || (i == 0 && pdp->minsizes[i] == 0L) || (pdp->minsizes[i] > 0L && pdp->maxsizes[i] > 0L && pdp->minsizes[i] > pdp->maxsizes[i])) { prnerr2("invalid execution size for program %d in section <%s>", i, namebuf); exit(EXIT_DB); } } } /* * Read one entry from the database file */ struct bootdef *getdb(name) char *name; { struct sectdef sect; char *namebuf, *cp; int i, j; /* Generate section record */ namebuf = (char *)nbmalloc(strlen(name) + 9); sprintf(namebuf, "%s:makerom", name); sect.name = namebuf; sect.params = dbparams; sect.startsect = NULL; sect.endsect = NULL; /* Get entry from database */ memset(&bootd, 0, sizeof(bootd)); for (i = 0; i < MAXPROGS; i++) { bootd.netdrv.driverdefs.pd.progs.minsizes[i] = -1L; bootd.netdrv.driverdefs.pd.progs.maxsizes[i] = -1L; bootd.netdrv.driverdefs.ndis.progs.minsizes[i] = -1L; bootd.netdrv.driverdefs.ndis.progs.maxsizes[i] = -1L; } readdb(§, dbname); /* Check for correct and missing values */ copystr(&bootd.name, name); checkaccess(&bootd.kernelname, config.bindir); if (!bootd.kernelname) { prnerr1("no or invalid kernel file name given in section <%s>", namebuf); exit(EXIT_DB); } if (bootd.pnp_devid != NULL && strlen(bootd.pnp_devid) == 0) { free(bootd.pnp_devid); bootd.pnp_devid = NULL; } if (bootd.bus_type == BUSTYPE_NONE) bootd.bus_type = BUSTYPE_ISA; if (bootd.bus_type == BUSTYPE_PCI) { if (bootd.pci_vendid == 0 || bootd.pci_devid == 0) { prnerr1("missing PCI vendor/device ID in section <%s>", namebuf); exit(EXIT_DB); } if (bootd.pnp_devid != NULL) { prnerr1("PnP device ID for PCI network card in section <%s>", namebuf); exit(EXIT_DB); } } else if (bootd.pci_vendid != 0 || bootd.pci_devid != 0) { prnerr1("PCI vendor/device ID specified for non-PCI device in section <%s>", namebuf); exit(EXIT_DB); } if (bootd.pnp_devid != NULL) { if (strlen(bootd.pnp_devid) != PNPIDLEN || !isalpha(bootd.pnp_devid[0]) || !isalpha(bootd.pnp_devid[1]) || !isalpha(bootd.pnp_devid[2]) || !isxdigit(bootd.pnp_devid[3]) || !isxdigit(bootd.pnp_devid[4]) || !isxdigit(bootd.pnp_devid[5]) || !isxdigit(bootd.pnp_devid[6])) { prnerr1("invalid PnP device ID in section <%s>", namebuf); exit(EXIT_DB); } } bootd.canflash = checkflash(&bootd); checkaccess(&bootd.netdrv.name, config.bindir); if (!bootd.netdrv.name) { prnerr1("no or invalid network driver name given in section <%s>", namebuf); exit(EXIT_DB); } if (bootd.netdrv.drivertype == DRVTYPE_NONE) { prnerr1("missing driver type in section <%s>", namebuf); exit(EXIT_DB); } /* Reorder the loader list and check for correct values */ bootd.loadernum = 0; for (i = 0, j = -1; i < MAXLOADERS; i++) { if (bootd.loaders[i].name != NULL) { checkaccess(&bootd.loaders[i].name, config.bindir); if (bootd.loaders[i].name == NULL) { prnerr2("loader %d invalid in section <%s>", i, namebuf); exit(EXIT_DB); } } if (bootd.loaders[i].name == NULL) { if (bootd.loaders[i].outname != NULL) { free(bootd.loaders[i].outname); bootd.loaders[i].outname = NULL; } if (j < 0) j = i; } else { if (bootd.loaders[i].outname == NULL) { prnerr2("no output file given for loader %d in section <%s>", i, namebuf); exit(EXIT_DB); } if (bootd.loaders[i].outtype == OUT_NONE) bootd.loaders[i].outtype = OUT_BINARY; if (bootd.loaders[i].outtype == OUT_FLASH && !bootd.canflash) { prnerr2("flash output type unsupported for loader %d in section <%s>", i, namebuf); exit(EXIT_DB); } bootd.loadernum++; if (j >= 0) { bootd.loaders[j] = bootd.loaders[i]; bootd.loaders[i].name = NULL; i = j; j = -1; } } } if (bootd.loadernum == 0) { prnerr1("no bootrom loader specified in section <%s>", namebuf); exit(EXIT_DB); } /* Check for correct values for the different network driver types */ if (bootd.netdrv.drivertype == DRVTYPE_PD) { struct pktdrvdef *pdp = &(bootd.netdrv.driverdefs.pd); checkprogs(&(pdp->progs), &(pdp->drvindex), namebuf); if (pdp->progs.prognum == 0) { prnerr1("no or invalid packet driver specified in section <%s>", namebuf); exit(EXIT_DB); } } else if (bootd.netdrv.drivertype == DRVTYPE_NDIS) { struct ndisdef *np = &(bootd.netdrv.driverdefs.ndis); checkprogs(&(np->progs), &(np->drvindex), namebuf); if (np->progs.prognum == 0) { prnerr1("no or invalid NDIS driver specified in section <%s>", namebuf); exit(EXIT_DB); } if (np->progs.progargs[np->drvindex] != NULL) { free(np->progs.progargs[np->drvindex]); np->progs.progargs[np->drvindex] = NULL; } if (protini == NULL) { prnerr1("missing \'protini\' entry in section <%s>\n", namebuf); exit(EXIT_DB); } if (!strncmp(protini, "file:", 5)) { cp = readprotini(&protini[5]); parseprotini(cp, &(np->protocolini), &(np->protinisize)); free(cp); } else parseprotini(protini, &(np->protocolini), &(np->protinisize)); } else if (bootd.netdrv.drivertype == DRVTYPE_UNDI) { checkaccess(&bootd.netdrv.driverdefs.undi.name, config.netdrvdir); if (bootd.netdrv.driverdefs.undi.name == NULL) { prnerr1("missing or invalid UNDI driver name in section <%s>", namebuf); exit(EXIT_DB); } } free(namebuf); return(&bootd); }