/*
* config.c - Read configuration file for makerom
*
* Copyright (C) 1998-2003 Gero Kuhlmann <gero@gkminix.han.de>
*
* 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: doconfig.c,v 1.6 2003/03/09 00:43:08 gkminix Exp $
*/
#include <common.h>
#include <nblib.h>
#include "makerom.h"
#include "doconfig.h"
#include "md5.h"
/*
* Maximum execution size
*/
#define MAX_EXEC_SIZE (128L * 1024L)
/*
* Default path and file name definitions
*/
#define DRIVERFILE "//netboot.drivers"
#define MD5SUMFILE "//netdrvr/MD5SUMS"
#define BINDIR "//binaries"
#define NETDRVDIR "//netdrvr"
#define UTILSDIR "//utils://binaries"
#define KERNEL32 "kernel.bin"
#define KERNEL16 "kernel86.bin"
#define KERNELM "kernelm.bin"
#define ROM32 "rom.bin"
#define ROM16 "rom86.bin"
#define FLOPPY32 "floppy.bin"
#define FLOPPY16 "floppy86.bin"
#define PKTDRV32 "netpkt.bin"
#define PKTDRV16 "netpkt86.bin"
#define NDIS32 "netndis.bin"
#define NDIS16 "netndis86.bin"
#define UNDI32 "netundi.bin"
#define UNDI16 "netundi86.bin"
/*
* Global variables
*/
struct confstruct config; /* configuration information */
/*
* Local variables
*/
static char *tmpdrvfname = NULL; /* temporary drivers file name */
static char *tmpmd5fname = NULL; /* temporary MD5 sums file name */
/*
* Definition of makerom:general section in configuration file
*/
static struct paramdef general_params[] = {
{ "driverfile", par_string, NULL, {&tmpdrvfname}},
{ "md5sumfile", par_string, NULL, {&tmpmd5fname}},
{ "bindir", par_string, NULL, {&config.bindir}},
{ "netdrvdir", par_string, NULL, {&config.netdrvdir}},
{ "utilsdir", par_string, NULL, {&config.utilsdir}},
{ "kernel32", par_string, NULL, {&config.files[FILE_KERNEL].filename32}},
{ "kernel16", par_string, NULL, {&config.files[FILE_KERNEL].filename16}},
{ "kernelm32", par_string, NULL, {&config.files[FILE_KERNELM].filename32}},
{ "kernelm16", par_string, NULL, {&config.files[FILE_KERNELM].filename16}},
{ "rom32", par_string, NULL, {&config.files[FILE_ROM].filename32}},
{ "rom16", par_string, NULL, {&config.files[FILE_ROM].filename16}},
{ "floppy32", par_string, NULL, {&config.files[FILE_FLOPPY].filename32}},
{ "floppy16", par_string, NULL, {&config.files[FILE_FLOPPY].filename16}},
{ NULL, par_null, NULL, {NULL}}
};
/*
* Assign a new string to a string pointer
*/
static void assignstr(old, new)
char **old;
char *new;
{
if (new != NULL) {
if (*old != NULL)
free(*old);
*old = new;
}
}
/*
* Read network driver interface information from configuration file
*/
static char *dsections[] = {
"pktdrv", "ndis", "undi"
};
static struct {
char *filename32;
char *filename16;
char *description;
char *directory;
char *pattern;
} netdrv_vars;
static struct paramdef netdrv_params[] = {
{ "filename32", par_string, NULL, {&netdrv_vars.filename32}},
{ "filename16", par_string, NULL, {&netdrv_vars.filename16}},
{ "description", par_string, NULL, {&netdrv_vars.description}},
{ "directory", par_string, NULL, {&netdrv_vars.directory}},
{ "pattern", par_string, NULL, {&netdrv_vars.pattern}},
{ NULL, par_null, NULL, {NULL}}
};
static char *handle_netdrv_sect(sectname, cursect)
char *sectname;
struct sectdef *cursect;
{
struct netdrvinfo *ip;
int drvtype;
char *cp;
/* Determine name of section, e.g. driver interface type */
assert((cp = strrchr(sectname, ':')) != NULL);
cp++;
for (drvtype = DRVTYPE_MIN; drvtype <= DRVTYPE_MAX; drvtype++)
if (!strcmp(cp, dsections[drvtype - DRVTYPE_MIN]))
break;
if (drvtype > DRVTYPE_MAX) {
if (netdrv_vars.description != NULL)
free(netdrv_vars.description);
if (netdrv_vars.directory != NULL)
free(netdrv_vars.directory);
if (netdrv_vars.pattern != NULL)
free(netdrv_vars.pattern);
if (netdrv_vars.filename32 != NULL)
free(netdrv_vars.filename32);
if (netdrv_vars.filename16 != NULL)
free(netdrv_vars.filename16);
memset(&netdrv_vars, 0, sizeof(netdrv_vars));
return("invalid network driver interface section");
}
/* Add new item to info list */
ip = &config.netdrv[drvtype];
assignstr(&(ip->descript), netdrv_vars.description);
assignstr(&(ip->searchdir), netdrv_vars.directory);
assignstr(&(ip->patlist), netdrv_vars.pattern);
assignstr(&(ip->filename32), netdrv_vars.filename32);
assignstr(&(ip->filename16), netdrv_vars.filename16);
/* Clear out temporary space for next round */
memset(&netdrv_vars, 0, sizeof(netdrv_vars));
return(NULL);
}
/*
* List of recognized options for network driver binary files
*/
static struct {
char *optname;
int optval;
} netoptlist[] = {
{ "HW_IRQ", HW_IRQ },
{ "IO_ADDR", IO_ADDR },
{ "BASE_MEM", BASE_MEM },
{ "AUI_TYPE", AUI_TYPE },
{ "DMA_NUM", DMA_NUM },
{ NULL, 0 }
};
static int getoption(optstr)
char *optstr;
{
char *cp;
int i, len, optval = 0;
cp = optstr;
while (cp != NULL) {
cp += strspn(cp, " \t");
len = strcspn(cp, " \t,");
if (len > 0) {
for (i = 0; netoptlist[i].optname != NULL; i++)
if (strlen(netoptlist[i].optname) == len &&
!strncmp(netoptlist[i].optname, cp, len))
break;
if (netoptlist[i].optname == NULL)
return(-1);
optval |= netoptlist[i].optval;
}
if ((cp = strchr(cp, ',')) != NULL)
cp++;
}
return(optval);
}
/*
* Find a network driver description in the configuration file structure. If
* none is found, a new entry is generated and inserted into the description
* list.
*/
static struct filedesc *getfiledesc(sectname)
char *sectname;
{
struct filedesc *fp = config.drvdesc;
char *cp;
/* Determine driver name from section name */
assert((cp = strchr(sectname, ':')) != NULL);
if (!*(++cp))
return(NULL);
/* Find driver description in list */
while (fp != NULL) {
if (!strcmp(fp->name, cp))
break;
fp = fp->next;
}
/* Create new description record if not found */
if (fp == NULL) {
fp = (struct filedesc *)nbmalloc(sizeof(struct filedesc));
copystr(&(fp->name), cp);
fp->next = config.drvdesc;
config.drvdesc = fp;
}
return(fp);
}
/*
* Eliminate beginning and ending quotes from a string
*/
static char *delquotes(str)
char *str;
{
int i;
assert(str != NULL);
if (str[0] == '"') {
i = strlen(str);
if (str[i - 1] != '"')
return(NULL);
str[i - 1] = '\0';
str++;
}
return(str);
}
/*
* Read description string from config file. This routine gets called
* everytime a "description" parameter is found in the config file.
*/
static struct descstr *desclist = NULL;
static char *readdesc(name, arg)
char *name;
char *arg;
{
struct descstr *dp;
/* Eliminate quotes from argument */
if ((arg = delquotes(arg)) == NULL)
return("missing end quote");
/* Add new item to description string list */
dp = (struct descstr *)nbmalloc(sizeof(struct descstr));
copystr(&(dp->descript), arg);
dp->next = desclist;
desclist = dp;
return(NULL);
}
/*
* Delete a description string list
*/
static void deldesc(sp)
struct descstr *sp;
{
struct descstr *spt;
while (sp != NULL) {
if (sp->descript != NULL)
free(sp->descript);
spt = sp;
sp = sp->next;
free(spt);
}
}
/*
* Read network card information from configuration file
*/
static char *btypes[] = {
"ISA", "EISA", "MCA", "PCI", NULL
};
static struct {
char *usedriver;
char *pnp_devid;
int pci_vendid;
int pci_devid;
int bustype;
} card_vars;
static struct paramdef card_params[] = {
{ "description", par_proc, NULL, {(char **)&readdesc}},
{ "bustype", par_enum, btypes, {(char **)&card_vars.bustype}},
{ "pcivendor", par_int, NULL, {(char **)&card_vars.pci_vendid}},
{ "pcidevice", par_int, NULL, {(char **)&card_vars.pci_devid}},
{ "pnpdevid", par_string, NULL, {&card_vars.pnp_devid}},
{ "usedriver", par_string, NULL, {&card_vars.usedriver}},
{ NULL, par_null, NULL, {NULL}}
};
static char *handle_card_sect(sectname, cursect)
char *sectname;
struct sectdef *cursect;
{
struct filedesc *fp;
struct descstr *sp;
char *cp = NULL;
/* Analyze section name and create new item in description list */
if ((fp = getfiledesc(sectname)) == NULL)
cp = "invalid section name";
else {
/* Check that the bus type doesn't change from a previous definition */
if (card_vars.bustype != BUSTYPE_NONE) {
if (fp->bustype != BUSTYPE_NONE &&
fp->bustype != card_vars.bustype) {
if (cp == NULL)
cp = "bus type already defined differently";
} else
fp->bustype = card_vars.bustype;
}
/* Check that a PCI vendor/device ID doesn't change */
if (card_vars.pci_vendid != 0) {
if (fp->pci_vendid != 0 &&
fp->pci_vendid != card_vars.pci_vendid) {
if (cp == NULL)
cp = "PCI vendor ID already defined differently";
} else
fp->pci_vendid = card_vars.pci_vendid;
}
if (card_vars.pci_devid != 0) {
if (fp->pci_devid != 0 &&
fp->pci_devid != card_vars.pci_devid) {
if (cp == NULL)
cp = "PCI device ID already defined differently";
} else
fp->pci_devid = card_vars.pci_devid;
}
/* Check that the PnP device ID is correct and doesn't change */
if (card_vars.pnp_devid != NULL) {
if (fp->pnp_devid != NULL &&
strcmp(card_vars.pnp_devid, fp->pnp_devid)) {
if (cp == NULL)
cp = "PnP device ID already defined differently";
} else if (strlen(card_vars.pnp_devid) > 0 &&
(strlen(card_vars.pnp_devid) != PNPIDLEN ||
!isalpha(card_vars.pnp_devid[0]) ||
!isalpha(card_vars.pnp_devid[1]) ||
!isalpha(card_vars.pnp_devid[2]) ||
!isxdigit(card_vars.pnp_devid[3]) ||
!isxdigit(card_vars.pnp_devid[4]) ||
!isxdigit(card_vars.pnp_devid[5]) ||
!isxdigit(card_vars.pnp_devid[6]))) {
if (cp == NULL)
cp = "invalid PnP device ID string";
} else {
if (strlen(card_vars.pnp_devid) == 0) {
free(card_vars.pnp_devid);
card_vars.pnp_devid = NULL;
if (fp->pnp_devid != NULL)
free(fp->pnp_devid);
fp->pnp_devid = NULL;
} else {
assignstr(&(fp->pnp_devid), card_vars.pnp_devid);
card_vars.pnp_devid = NULL;
}
}
}
/* Check that the bus type is correct */
if (cp == NULL && fp->bustype != BUSTYPE_PCI &&
(fp->pci_vendid != 0 || fp->pci_devid != 0))
cp = "PCI vendor/device ID specified for non-PCI bus type";
if (cp == NULL && fp->bustype == BUSTYPE_PCI &&
fp->pnp_devid != NULL)
cp = "PnP device ID string defined for PCI bus type";
if (cp == NULL && fp->pnp_devid != NULL &&
(fp->pci_vendid != 0 || fp->pci_devid != 0))
cp = "PCI vendor/device ID and PnP device ID defined";
/* Add driver cross-reference */
assignstr(&(fp->usedriver), card_vars.usedriver);
card_vars.usedriver = NULL;
/* Add list of descriptions to item */
if ((sp = desclist) != NULL) {
while (sp->next != NULL)
sp = sp->next;
sp->next = fp->descript;
fp->descript = desclist;
}
desclist = NULL;
}
/* Clear all dynamic memory which hasn't been saved so far */
deldesc(desclist);
desclist = NULL;
if (card_vars.pnp_devid != NULL)
free(card_vars.pnp_devid);
if (card_vars.usedriver != NULL)
free(card_vars.usedriver);
memset(&card_vars, 0, sizeof(card_vars));
return(cp);
}
/*
* Read network driver information from configuration file
*/
static char *dtypes[] = {
"packet driver", "ndis driver", "undi driver", NULL
};
static struct {
char *filename;
char *parameters;
char *pd_cmdline;
char *ndis_protini;
char *drvdesc;
char *md5sum;
int drvtype;
long minsize;
long maxsize;
} driver_vars;
static struct paramdef driver_params[] = {
{ "driverdesc", par_string, NULL, {&driver_vars.drvdesc}},
{ "file", par_string, NULL, {&driver_vars.filename}},
{ "params", par_string, NULL, {&driver_vars.parameters}},
{ "cmdline", par_string, NULL, {&driver_vars.pd_cmdline}},
{ "protini", par_string, NULL, {&driver_vars.ndis_protini}},
{ "md5sum", par_string, NULL, {&driver_vars.md5sum}},
{ "drvtype", par_enum, dtypes, {(char **)&driver_vars.drvtype}},
{ "minsize", par_long, NULL, {(char **)&driver_vars.minsize}},
{ "maxsize", par_long, NULL, {(char **)&driver_vars.maxsize}},
{ NULL, par_null, NULL, {NULL}}
};
static char *handle_driver_sect(sectname, cursect)
char *sectname;
struct sectdef *cursect;
{
struct filedesc *fp;
struct drvdesc *dp;
char *drvdesc = NULL;
char *cp = NULL;
char *mdp;
int opt = -1;
/* Analyze section name and create new item in description list */
if ((fp = getfiledesc(sectname)) == NULL)
cp = "invalid section name";
else {
/* Check that parameter combinations are valid */
switch (driver_vars.drvtype) {
case DRVTYPE_NONE:
if (driver_vars.filename != NULL ||
driver_vars.parameters != NULL ||
driver_vars.minsize != -1L ||
driver_vars.maxsize != -1L ||
driver_vars.pd_cmdline != NULL ||
driver_vars.ndis_protini != NULL ||
driver_vars.md5sum != NULL ||
driver_vars.drvdesc != NULL)
cp = "missing driver type parameter";
break;
case DRVTYPE_PD:
if (driver_vars.ndis_protini != NULL)
cp = "bogus \'protini\' parameter in packet driver definition";
break;
case DRVTYPE_NDIS:
if (driver_vars.pd_cmdline != NULL)
cp = "bogus \'cmdline\' parameter in NDIS driver definition";
break;
case DRVTYPE_UNDI:
if (driver_vars.parameters != NULL)
cp = "bogus \'params\' parameter in UNDI driver definition";
else if (driver_vars.ndis_protini != NULL)
cp = "bogus \'protini\' parameter in UNDI driver definition";
else if (driver_vars.pd_cmdline != NULL)
cp = "bogus \'cmdline\' parameter in UNDI driver definition";
else if (driver_vars.minsize != -1L ||
driver_vars.maxsize != -1L)
cp = "bogus \'minsize\' or \'maxsize\' parameter in UNDI driver definition";
break;
default:
assert(driver_vars.drvtype >= DRVTYPE_MIN &&
driver_vars.drvtype <= DRVTYPE_MAX);
break;
}
/* Analyze options */
if (driver_vars.parameters != NULL) {
if ((opt = getoption(driver_vars.parameters)) < 0 && cp == NULL)
cp = "invalid \'params\' parameter";
free(driver_vars.parameters);
driver_vars.parameters = NULL;
}
/* Analyze execution sizes */
if (driver_vars.minsize < -2L)
driver_vars.minsize = -2L;
if (driver_vars.maxsize < -2L)
driver_vars.maxsize = -2L;
if (cp == NULL &&
((driver_vars.minsize > 0L &&
driver_vars.maxsize > 0L &&
driver_vars.minsize > driver_vars.maxsize) ||
driver_vars.minsize > MAX_EXEC_SIZE ||
driver_vars.maxsize > MAX_EXEC_SIZE))
cp = "invalid execution size values";
/* Check for correct driver description string */
if (driver_vars.drvdesc != NULL &&
(drvdesc = delquotes(driver_vars.drvdesc)) == NULL) {
if (cp == NULL)
cp = "missing end quotes in network driver description string";
}
/* Check for correct MD5 sum string, and convert it to lower case */
if (driver_vars.md5sum != NULL) {
for (mdp = driver_vars.md5sum; *mdp; mdp++) {
*mdp = tolower(*mdp);
if ((*mdp < '0' || *mdp > '9') &&
(*mdp < 'a' || *mdp > 'f'))
break;
}
if (cp == NULL && (mdp - driver_vars.md5sum) != MD5_SUM_LENGTH)
cp = "invalid MD5 checksum string";
}
/* Add new driver description record */
if (fp->usedriver != NULL) {
if (cp == NULL)
cp = "alternative driver list already defined";
} else if (driver_vars.drvtype != DRVTYPE_NONE) {
dp = (struct drvdesc *)nbmalloc(sizeof(struct drvdesc));
dp->type = driver_vars.drvtype;
switch (driver_vars.drvtype) {
case DRVTYPE_PD:
if (opt >= 0)
dp->drv.pd.options = opt;
dp->drv.pd.minsize = driver_vars.minsize;
dp->drv.pd.maxsize = driver_vars.maxsize;
assignstr(&(dp->drv.pd.cmdline), driver_vars.pd_cmdline);
driver_vars.pd_cmdline = NULL;
break;
case DRVTYPE_NDIS:
if (opt >= 0)
dp->drv.ndis.options = opt;
dp->drv.ndis.minsize = driver_vars.minsize;
dp->drv.ndis.maxsize = driver_vars.maxsize;
assignstr(&(dp->drv.ndis.protini), driver_vars.ndis_protini);
driver_vars.ndis_protini = NULL;
break;
case DRVTYPE_UNDI:
break;
}
if (driver_vars.drvdesc != NULL) {
if (drvdesc != NULL)
copystr(&(dp->descript), drvdesc);
free(driver_vars.drvdesc);
driver_vars.drvdesc = NULL;
}
assignstr(&(dp->filename), driver_vars.filename);
assignstr(&(dp->md5sum), driver_vars.md5sum);
driver_vars.filename = NULL;
driver_vars.md5sum = NULL;
dp->next = fp->drvlist;
fp->drvlist = dp;
}
}
/* Clear all dynamic memory before returning */
if (driver_vars.filename != NULL)
free(driver_vars.filename);
if (driver_vars.parameters != NULL)
free(driver_vars.parameters);
if (driver_vars.pd_cmdline != NULL)
free(driver_vars.pd_cmdline);
if (driver_vars.ndis_protini != NULL)
free(driver_vars.ndis_protini);
if (driver_vars.md5sum != NULL)
free(driver_vars.md5sum);
if (driver_vars.drvdesc != NULL)
free(driver_vars.drvdesc);
memset(&driver_vars, 0, sizeof(driver_vars));
driver_vars.minsize = -1L;
driver_vars.maxsize = -1L;
return(cp);
}
/*
* List of sections to read from configuration files at startup
*/
static struct sectdef confsects[] = {
{ "makerom:general", general_params, NULL, NULL },
{ NULL, NULL, NULL, NULL}
};
static struct sectdef driversects[] = {
{ "netdrv:*", netdrv_params, NULL, &handle_netdrv_sect },
{ "card:*", card_params, NULL, &handle_card_sect },
{ "driver:*", driver_params, NULL, &handle_driver_sect },
{ NULL, NULL, NULL, NULL}
};
/*
* Set configuration structure with default values
*/
static struct {
char **cnfptr;
char *defstr;
} filedefaults[] = {
{ &config.bindir, BINDIR },
{ &config.netdrvdir, NETDRVDIR },
{ &config.utilsdir, UTILSDIR },
{ &config.files[FILE_KERNEL].filename32, KERNEL32 },
{ &config.files[FILE_KERNEL].filename16, KERNEL16 },
{ &config.files[FILE_KERNELM].filename32, KERNELM },
{ &config.files[FILE_ROM].filename32, ROM32 },
{ &config.files[FILE_ROM].filename16, ROM16 },
{ &config.files[FILE_FLOPPY].filename32, FLOPPY32 },
{ &config.files[FILE_FLOPPY].filename16, FLOPPY16 },
{ &config.netdrv[DRVTYPE_PD].filename32, PKTDRV32 },
{ &config.netdrv[DRVTYPE_PD].filename16, PKTDRV16 },
{ &config.netdrv[DRVTYPE_NDIS].filename32, NDIS32 },
{ &config.netdrv[DRVTYPE_NDIS].filename16, NDIS16 },
{ &config.netdrv[DRVTYPE_UNDI].filename32, UNDI32 },
{ &config.netdrv[DRVTYPE_UNDI].filename16, UNDI16 },
{ NULL, NULL }
};
static char *netdescstr[] = {
"Packet Driver interface (PD)",
"Network Driver Interface Specification (NDIS)",
"Universal Network Driver Interface (UNDI)"
};
static char *netpathstr[] = {
"pktdrvr:pktdrvr/drivers",
"ndis2:ndis2/drivers",
"undi:undi/drivers"
};
static char *patternstr[] = {
"*.com:*.exe",
"*.sys:*.dos",
"*.undi"
};
static void setdefaults()
{
int i;
/* Clearout configuration structure */
memset(&config, 0, sizeof(config));
/* Copy default strings into structure */
for (i = 0; filedefaults[i].defstr != NULL; i++)
copystr(filedefaults[i].cnfptr, filedefaults[i].defstr);
/* Set defaults for network driver interface definitions */
for (i = DRVTYPE_MIN; i <= DRVTYPE_MAX; i++) {
copystr(&config.netdrv[i].descript, netdescstr[i - DRVTYPE_MIN]);
copystr(&config.netdrv[i].searchdir, netpathstr[i - DRVTYPE_MIN]);
copystr(&config.netdrv[i].patlist, patternstr[i - DRVTYPE_MIN]);
}
}
/*
* Normalize directory and file names and cleanup the network driver
* description list.
*/
static void donormalize()
{
struct filedesc *fp;
struct drvdesc *dp, *olddp, *dpt;
char *sdir;
int i;
/* Normalize main directory names */
setpath(&config.bindir, NULL);
setpath(&config.netdrvdir, NULL);
setpath(&config.utilsdir, NULL);
/* Normalize binary file names */
for (i = 0; i < FILE_NUMBER; i++) {
checkaccess(&config.files[i].filename32, config.bindir);
checkaccess(&config.files[i].filename16, config.bindir);
}
for (i = DRVTYPE_MIN; i <= DRVTYPE_MAX; i++) {
setpath(&config.netdrv[i].searchdir, config.netdrvdir);
checkaccess(&config.netdrv[i].filename32, config.bindir);
checkaccess(&config.netdrv[i].filename16, config.bindir);
}
/* Scan through all network cards and process their drivers */
fp = config.drvdesc;
while (fp != NULL) {
/* Normalize network driver file names and check MD5 checksums */
dp = fp->drvlist;
while (dp != NULL) {
assert(dp->type >= DRVTYPE_MIN &&
dp->type <= DRVTYPE_MAX);
sdir = NULL;
switch (dp->type) {
case DRVTYPE_PD:
sdir = config.netdrv[DRVTYPE_PD].searchdir;
break;
case DRVTYPE_NDIS:
sdir = config.netdrv[DRVTYPE_NDIS].searchdir;
break;
case DRVTYPE_UNDI:
sdir = config.netdrv[DRVTYPE_UNDI].searchdir;
break;
}
checkaccess(&(dp->filename), sdir);
checkmd5sum(&(dp->filename), dp->md5sum);
dp = dp->next;
}
/*
* Remove all drivers with the same file name but without an MD5
* checksum, if at least one driver has a checksum. We have to do
* this in a seperate loop because all filenames have to be
* normalized first.
*/
dp = fp->drvlist;
while (dp != NULL) {
if (dp->filename != NULL && dp->md5sum != NULL) {
dpt = fp->drvlist;
while (dpt != NULL) {
if (dpt != dp &&
dpt->md5sum == NULL &&
dpt->filename != NULL &&
!strcmp(dpt->filename, dp->filename)) {
free(dpt->filename);
dpt->filename = NULL;
}
dpt = dpt->next;
}
}
dp = dp->next;
}
/* Cleanup driver list by deleting all drivers with empty filename */
dp = fp->drvlist;
olddp = NULL;
while (dp != NULL) {
if (dp->filename == NULL) {
/* Delete item from list */
switch (dp->type) {
case DRVTYPE_PD:
if (dp->drv.pd.cmdline != NULL)
free(dp->drv.pd.cmdline);
break;
case DRVTYPE_NDIS:
if (dp->drv.ndis.protini != NULL)
free(dp->drv.ndis.protini);
break;
case DRVTYPE_UNDI:
break;
}
if (dp->md5sum != NULL)
free(dp->md5sum);
if (dp->descript != NULL)
free(dp->descript);
if (olddp == NULL)
fp->drvlist = dp->next;
else
olddp->next = dp->next;
dpt = dp;
dp = dp->next;
free(dpt);
} else {
/* Continue with next item */
olddp = dp;
dp = dp->next;
}
}
fp = fp->next;
}
}
/*
* Resolve cross-reference driver lists and cleanup network card list
*/
static void doresolve()
{
struct filedesc *fp, *oldfp, *fpt;
char *cp;
fp = config.drvdesc;
oldfp = NULL;
while (fp != NULL) {
fpt = NULL;
if (fp->drvlist == NULL && (cp = fp->usedriver) != NULL) {
fpt = config.drvdesc;
while (fpt != NULL) {
if (fpt != fp && !strcmp(fpt->name, cp))
break;
fpt = fpt->next;
}
}
if (fpt != NULL)
fp->drvlist = fpt->drvlist;
if (fp->drvlist == NULL) {
/* Delete item from list */
deldesc(fp->descript);
if (fp->name != NULL)
free(fp->name);
if (fp->pnp_devid != NULL)
free(fp->pnp_devid);
if (fp->usedriver != NULL)
free(fp->usedriver);
if (oldfp == NULL)
config.drvdesc = fp->next;
else
oldfp->next = fp->next;
fpt = fp;
fp = fp->next;
free(fpt);
} else {
oldfp = fp;
fp = fp->next;
}
}
}
/*
* Parse options and read configuration file
*/
void doconfig(argc, argv, opts)
int argc;
char **argv;
struct cmdopt *opts;
{
/* Clear config file read structures */
memset(&netdrv_vars, 0, sizeof(netdrv_vars));
memset(&card_vars, 0, sizeof(card_vars));
memset(&driver_vars, 0, sizeof(driver_vars));
driver_vars.minsize = -1L;
driver_vars.maxsize = -1L;
/* Set defaults */
setdefaults();
/* Parse options and read configuration file */
nbsetup(argc, argv, opts, confsects);
/* Let the command line file name override the one from the config file */
if (tmpmd5fname != NULL) {
if (config.md5fname == NULL)
config.md5fname = tmpmd5fname;
else
free(tmpmd5fname);
tmpmd5fname = NULL;
} else if (config.md5fname == NULL)
copystr(&config.md5fname, MD5SUMFILE);
/* Normalize name of MD5 sums file and read it */
checkaccess(&config.md5fname, NULL);
if (config.md5fname != NULL)
readmd5(config.md5fname);
else
prnerr0("WARNING: No or invalid MD5 checksum file specified!");
/* Let the command line file name override the one from the config file */
if (tmpdrvfname != NULL) {
if (config.drvfname == NULL)
config.drvfname = tmpdrvfname;
else
free(tmpdrvfname);
tmpdrvfname = NULL;
} else if (config.drvfname == NULL)
copystr(&config.drvfname, DRIVERFILE);
/* Normalize file name of network driver configuration file and read it */
checkaccess(&config.drvfname, NULL);
if (config.drvfname != NULL)
readconfig(driversects, config.drvfname);
else
prnerr0("WARNING: No or invalid network driver config file specified!");
/* Normalize directory and file names and resolve cross-references */
donormalize();
doresolve();
/* Cleanup MD5 checksum list, which is no longer needed */
clearmd5();
}
syntax highlighted by Code2HTML, v. 0.9.1