/*
* user.c - user interface for makerom bootrom configuration utility
*
* Copyright (C) 1995-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: user.c,v 1.8 2003/03/09 00:43:08 gkminix Exp $
*/
#include <common.h>
#include <nblib.h>
#include "makerom.h"
#include "doconfig.h"
#include "protini.h"
#include "console.h"
/*
* Local declarations
*/
#define DEFAULTINT 0x62 /* default packet driver interrupt */
#define MAXEXECSIZE (128L * 1024L) /* maximum size of DOS program */
#define PKTWATCHSIZE 2048L /* stack size for pktwatch */
/*
* Variables local to this module
*/
static struct bootdef bootd;
static int is86 = FALSE;
/*
**************************************************************************
*
* Ask user about parts of bootrom
*
**************************************************************************
*/
/*
* Let the user select a bootrom kernel.
*/
static void getkernel()
{
int havemenu = FALSE;
int usemenu = FALSE;
int useint18 = FALSE;
int bootask = FALSE;
int asktime = 0;
/* Initialize boot definition structure */
memset(&bootd, 0, sizeof(bootd));
/* Ask user about bootrom kernel options */
is86 = getyn("Build bootrom for a processor older than 386", FALSE);
havemenu = ((is86 ? config.files[FILE_KERNELM].filename16 :
config.files[FILE_KERNELM].filename32) != NULL);
if (havemenu)
usemenu = getyn("Include support for old-style menus (not recommended)", usemenu);
useint18 = getyn("Do you want the BIOS to look for boot disks", useint18);
if (!useint18) {
bootask = getyn("Do you want the bootrom to ask before booting from network", bootask);
if (bootask)
asktime = getsel("How many seconds should the bootrom wait asking (0 = forever)",
0, 31, asktime);
}
printf("\n\n");
/* Generate bootrom definition */
if (is86) {
copystr(&bootd.kernelname, (usemenu ?
config.files[FILE_KERNELM].filename16 :
config.files[FILE_KERNEL].filename16));
copystr(&bootd.loaders[0].name, config.files[FILE_ROM].filename16);
copystr(&bootd.loaders[1].name, config.files[FILE_FLOPPY].filename16);
} else {
copystr(&bootd.kernelname, (usemenu ?
config.files[FILE_KERNELM].filename32 :
config.files[FILE_KERNEL].filename32));
copystr(&bootd.loaders[0].name, config.files[FILE_ROM].filename32);
copystr(&bootd.loaders[1].name, config.files[FILE_FLOPPY].filename32);
}
bootd.loadernum = 2;
bootd.canflash = FALSE;
bootd.loaders[0].outname = NULL; /* set later */
bootd.loaders[0].outtype = OUT_NONE; /* set later */
bootd.loaders[0].outsize = 0;
bootd.loaders[0].useint18 = useint18;
bootd.loaders[0].cardinst = TRUE; /* eventually modified later */
bootd.loaders[0].bootask = bootask;
bootd.loaders[0].asktime = asktime;
bootd.loaders[1].outname = NULL; /* set later */
bootd.loaders[1].outtype = OUT_NONE; /* set later */
bootd.loaders[1].outsize = 0;
bootd.loaders[1].useint18 = TRUE;
bootd.loaders[1].cardinst = FALSE;
bootd.loaders[1].bootask = FALSE;
bootd.loaders[1].asktime = 0;
/* Check that all files are accessible */
if (bootd.kernelname == NULL) {
prnerr0("unable to access bootrom kernel file");
exit(EXIT_ACCESS);
}
if (bootd.loaders[0].name == NULL) {
prnerr0("unable to access rom loader file");
exit(EXIT_ACCESS);
}
if (bootd.loaders[1].name == NULL) {
prnerr0("unable to access floppy loader file");
exit(EXIT_ACCESS);
}
}
/*
* Get type of output file
*/
static void getouttype()
{
static char *outdesc[OUT_MAX - OUT_MIN + 1] = {
"Raw binary",
"Intel hex",
"Motorola hex",
"Tektronix hex",
"Image for programming a FlashCard across the network",
"Image for programming a flash EPROM accross the network"
};
int outtype, i;
/* Ask user about output type */
printf("Available output file types for rom image:\n");
for (i = OUT_MIN; i <= OUT_MAX; i++) {
if (!bootd.canflash && i == OUT_FLASH)
break;
printf("(%d)\t%s\n", i, outdesc[i - OUT_MIN]);
}
assert(i >= OUT_MAX); /* this requires OUT_MAX == OUT_FLASH */
outtype = getsel("Select the format you wish to use", OUT_MIN,
i - 1, OUT_DEF);
printf("\n\n");
/* Set values in boot definition structure */
bootd.loaders[0].outtype = outtype;
switch (outtype) {
case OUT_FLASH:
copystr(&(bootd.loaders[0].outname), "image.flash");
bootd.loaders[0].cardinst = TRUE;
break;
case OUT_FC:
copystr(&(bootd.loaders[0].outname), "image.flash");
bootd.loaders[0].cardinst = FALSE;
break;
case OUT_IHEX:
case OUT_MHEX:
case OUT_THEX:
copystr(&(bootd.loaders[0].outname), "image.hex");
bootd.loaders[0].cardinst = TRUE;
break;
case OUT_BINARY:
default:
copystr(&(bootd.loaders[0].outname), "image.rom");
bootd.loaders[0].cardinst = TRUE;
break;
}
copystr(&(bootd.loaders[1].outname), "image.flo");
bootd.loaders[1].cardinst = FALSE;
bootd.loaders[1].outtype = OUT_BINARY;
}
/*
**************************************************************************
*
* General routines for sorting description strings
*
**************************************************************************
*/
/* Structure holding description information */
struct netdesc {
struct netdesc *next;
union {
struct filedesc *fdesc;
struct drvdesc *ddesc;
} desc;
char *descstr;
};
/*
* Compare a description table entry for qsort routine
*/
static int netdescmp(entry1, entry2)
const voidstar entry1;
const voidstar entry2;
{
struct netdesc *dp1 = *((struct netdesc **)entry1);
struct netdesc *dp2 = *((struct netdesc **)entry2);
assert(dp1 != NULL && dp2 != NULL &&
dp1->descstr != NULL && dp2->descstr != NULL);
return(strcmp(dp1->descstr, dp2->descstr));
}
/*
* Generate an array of description records and sort it
*/
static struct netdesc **sortdesclist(desclist, descnum)
struct netdesc *desclist;
int descnum;
{
struct netdesc *dp;
struct netdesc **descarray;
int i;
/* Check that we have anything to process */
if (desclist == NULL || descnum == 0)
return(NULL);
/* Generate array of linked list */
descarray = (struct netdesc **)nbmalloc((descnum + 1) * sizeof(struct netdesc *));
i = 0;
dp = desclist;
while (dp != NULL) {
descarray[i] = dp;
dp = dp->next;
descarray[i]->next = NULL;
i++;
}
assert(i == descnum);
descarray[i] = NULL;
/* Sort the array */
qsort(descarray, descnum, sizeof(struct netdesc *), &netdescmp);
return(descarray);
}
/*
* Delete the description array
*/
static void deldescarray(descarray)
struct netdesc **descarray;
{
int i = 0;
while(descarray[i] != NULL)
free(descarray[i++]);
free(descarray);
}
/*
**************************************************************************
*
* Selection of network card
*
**************************************************************************
*/
/*
* Generate sorted array of selectable network card descriptions
*/
static struct netdesc **gencarddescarray()
{
struct filedesc *fp;
struct drvdesc *drvp;
struct descstr *sp;
struct netdesc *dp;
struct netdesc *desclist = NULL;
int havedriver[NETDRV_NUM];
int i, descnum;
/* Check which network driver interfaces are available */
for (i = DRVTYPE_MIN; i <= DRVTYPE_MAX; i++) {
if (is86)
havedriver[i] = (config.netdrv[i].filename16 != NULL);
else
havedriver[i] = (config.netdrv[i].filename32 != NULL);
}
/* Scan through list of available network cards */
descnum = 0;
fp = config.drvdesc;
while (fp != NULL) {
i = 0;
drvp = fp->drvlist;
while (drvp != NULL) {
if (havedriver[drvp->type])
i++;
drvp = drvp->next;
}
if (i > 0) {
sp = fp->descript;
if (sp == NULL) {
dp = (struct netdesc *)nbmalloc(sizeof(struct netdesc));
dp->desc.fdesc = fp;
dp->descstr = fp->name;
dp->next = desclist;
desclist = dp;
descnum++;
} else while (sp != NULL) {
dp = (struct netdesc *)nbmalloc(sizeof(struct netdesc));
dp->desc.fdesc = fp;
dp->descstr = sp->descript;
dp->next = desclist;
desclist = dp;
sp = sp->next;
descnum++;
}
}
fp = fp->next;
}
/* Sort description list */
return(sortdesclist(desclist, descnum));
}
/*
* Print list of network card descriptions
*/
static int printcarddescarray(descarray)
struct netdesc **descarray;
{
int i = 0;
int line = 0;
while (descarray[i] != NULL) {
printf("(%d)\t%s\n", i + 1, descarray[i]->descstr);
i++;
line++;
if (line >= LISTLINES && descarray[i] != NULL) {
printf("\nPress <ENTER> to continue listing ");
(void)getstring(NULL);
printf("\n");
line = 0;
}
}
printf("\n");
return(i);
}
/*
* Let the user select the bus type
*/
static int getbustype(fp)
struct filedesc *fp;
{
/* If we have a bus type already, don't need to ask */
if (fp != NULL && fp->bustype != BUSTYPE_NONE)
return(fp->bustype);
/* Otherwise print a list of bus types and let the user select */
printf("\n\nKnown network card bus types:\n");
printf("(%d)\tISA bus (including PnP)\n", BUSTYPE_ISA);
printf("(%d)\tEISA bus\n", BUSTYPE_EISA);
printf("(%d)\tMCA bus\n", BUSTYPE_MCA);
printf("(%d)\tPCI bus\n", BUSTYPE_PCI);
return(getsel("Select the bus type of your network card",
BUSTYPE_MIN, BUSTYPE_MAX, BUSTYPE_ISA));
}
/*
* Let the user select a network card
*/
static void getnetcard(fdp)
struct filedesc **fdp;
{
struct filedesc *fp = NULL;
struct netdesc **descarray;
char *pnpdevid;
int descnum, sel = -1;
int bustype;
/* Print list of known network cards and let the user decide */
if ((descarray = gencarddescarray()) != NULL) {
do {
printf("List of known network cards:\n");
printf("(0)\tunknown card with user supplied driver\n");
descnum = printcarddescarray(descarray);
sel = getsel("Select a network card (-1 to review the list)",
-1, descnum, -1);
} while (sel < 0);
if (sel > 0) {
printf("\nYou selected: %s\n", descarray[sel - 1]->descstr);
fp = descarray[sel - 1]->desc.fdesc;
}
deldescarray(descarray);
}
/* Get the bus type and PCI/PnP vendor/device ID for the network card */
bustype = getbustype(fp);
if (bustype == BUSTYPE_PCI) {
if (fp == NULL || fp->pci_vendid == 0)
bootd.pci_vendid = getnum("Enter PCI vendor ID", 0, 0xffff, TRUE);
else
bootd.pci_vendid = fp->pci_vendid;
if (fp == NULL || fp->pci_devid == 0)
bootd.pci_devid = getnum("Enter PCI device ID", 0, 0xffff, TRUE);
else
bootd.pci_devid = fp->pci_devid;
} else if (fp == NULL || fp->pnp_devid == NULL) {
while (TRUE) {
pnpdevid = getstring("Enter PnP device ID string (maybe empty)");
if (pnpdevid == NULL || strlen(pnpdevid) == 0) {
pnpdevid = NULL;
break;
}
if (strlen(pnpdevid) != PNPIDLEN ||
!isalpha(pnpdevid[0]) ||
!isalpha(pnpdevid[1]) ||
!isalpha(pnpdevid[2]) ||
!isxdigit(pnpdevid[3]) ||
!isxdigit(pnpdevid[4]) ||
!isxdigit(pnpdevid[5]) ||
!isxdigit(pnpdevid[6]))
printf(" Invalid ID string, it has to look like: ABC1234\n");
else
break;
pnpdevid[0] = toupper(pnpdevid[0]);
pnpdevid[1] = toupper(pnpdevid[1]);
pnpdevid[2] = toupper(pnpdevid[2]);
}
if (pnpdevid != NULL)
copystr(&(bootd.pnp_devid), pnpdevid);
} else
copystr(&(bootd.pnp_devid), fp->pnp_devid);
bootd.bus_type = bustype;
/* Check if we can offer the flash EPROM option to the user */
bootd.canflash = checkflash(&bootd);
/* Prepare return value */
*fdp = fp;
printf("\n\n");
}
/*
**************************************************************************
*
* Selection of network driver
*
**************************************************************************
*/
/*
* Generate sorted array of selectable network drivers
*/
static struct netdesc **gendrvdescarray(fp)
struct filedesc *fp;
{
struct drvdesc *drvp;
struct netdesc *dp;
struct netdesc *desclist = NULL;
int havedriver[NETDRV_NUM];
int i, descnum;
/* Check if we have any drivers at all */
if (fp == NULL || fp->drvlist == NULL)
return(NULL);
/* Check which network driver interfaces are available */
for (i = DRVTYPE_MIN; i <= DRVTYPE_MAX; i++) {
if (is86)
havedriver[i] = (config.netdrv[i].filename16 != NULL);
else
havedriver[i] = (config.netdrv[i].filename32 != NULL);
}
/* Scan through list of available network drivers */
descnum = 0;
drvp = fp->drvlist;
while (drvp != NULL) {
if (havedriver[drvp->type]) {
if (drvp->descript == NULL) {
if (drvp->filename != NULL) {
dp = (struct netdesc *)nbmalloc(sizeof(struct netdesc));
dp->desc.ddesc = drvp;
dp->descstr = drvp->filename;
dp->next = desclist;
desclist = dp;
descnum++;
}
} else {
dp = (struct netdesc *)nbmalloc(sizeof(struct netdesc));
dp->desc.ddesc = drvp;
dp->descstr = drvp->descript;
dp->next = desclist;
desclist = dp;
descnum++;
}
}
drvp = drvp->next;
}
/* Sort description list */
return(sortdesclist(desclist, descnum));
}
/*
* Print list of network driver descriptions
*/
static int printdrvdescarray(descarray)
struct netdesc **descarray;
{
static char *dtypes[] = {
"packet driver", "NDIS driver", "UNDI driver"
};
int i = 0;
int line = 0;
while (descarray[i] != NULL) {
printf("(%d)\t%s\t%s\n", i + 1,
dtypes[descarray[i]->desc.ddesc->type - 1],
descarray[i]->descstr);
i++;
line++;
if (line >= LISTLINES && descarray[i] != NULL) {
printf("\nPress <ENTER> to continue listing ");
(void)getstring(NULL);
printf("\n");
line = 0;
}
}
printf("\n");
return(i);
}
/*
* Scan through the network driver array and determine the number of
* bits in the options field. Then select the interface with the least
* number of bits, e.g. that one with the least number of options to
* be entered by the user.
*/
static int checkdefdrv(descarray)
struct netdesc **descarray;
{
struct drvdesc *dp;
int def, bitnum;
int i, j, k;
i = 0;
def = 0;
bitnum = 16;
while (descarray[i] != NULL) {
dp = descarray[i]->desc.ddesc;
k = 0;
switch (dp->type) {
case DRVTYPE_PD:
k = dp->drv.pd.options;
break;
case DRVTYPE_NDIS:
k = dp->drv.ndis.options;
break;
case DRVTYPE_UNDI:
/* there is no options value for UNDI drivers */
k = 0;
break;
default:
/* should never happen */
k = 16;
break;
}
j = 0;
while (k > 0) {
if ((k & 1) != 0)
j++;
k >>= 1;
}
if (j <= bitnum) {
bitnum = j;
def = i;
}
i++;
}
return(def);
}
/*
* Let the user select a network driver for the interface card selected. If
* none has been selected just ask for the network driver interface type.
*/
static struct drvdesc *getnetdrv(fp)
struct filedesc *fp;
{
struct netdesc **descarray;
struct drvdesc *dp;
static struct drvdesc ddesc;
int drvtypelist[NETDRV_NUM];
int descnum, sel;
int i, j, def;
char *cp;
/* If we have preselected a network card, print a list of available drivers */
if (fp != NULL) {
if ((descarray = gendrvdescarray(fp)) != NULL) {
assert(descarray[0] != NULL);
if (descarray[1] == NULL) {
/* We have just one network driver available */
dp = descarray[0]->desc.ddesc;
} else {
/* There is more than one driver available */
printf("List of drivers for the selected network card:\n");
descnum = printdrvdescarray(descarray);
def = checkdefdrv(descarray);
sel = getsel("Select a driver", 1, descnum, def + 1);
dp = descarray[sel - 1]->desc.ddesc;
}
deldescarray(descarray);
return(dp);
}
}
/*
* If we got here a network card has not been selected or there are no
* suitable network drivers available. We therefore ask about the type of
* network driver interface and then return an empty static driver description
* record.
*/
/* Determine the interface types which are available */
j = 0;
for (i = DRVTYPE_MIN; i <= DRVTYPE_MAX; i++) {
if (is86)
cp = config.netdrv[i].filename16;
else
cp = config.netdrv[i].filename32;
if (cp != NULL)
drvtypelist[j++] = i;
}
/* There should be at least one interface available */
if (j == 0) {
prnerr0("no network driver interfaces available");
exit(EXIT_MAKEROM_IFFND);
}
/* Let the user select the network driver interface type */
sel = 1;
if (j > 1) {
printf("The following network driver interfaces are available:\n");
for (i = 0; i < j; i++) {
cp = config.netdrv[drvtypelist[i]].descript;
if (cp == NULL) switch(drvtypelist[i]) {
case DRVTYPE_PD:
cp = "packet driver interface";
break;
case DRVTYPE_NDIS:
cp = "NDIS driver interface";
break;
case DRVTYPE_UNDI:
cp = "generic UNDI driver interface";
break;
}
assert(cp != NULL);
printf("(%d)\t%s\n", i + 1, cp);
}
sel = getsel("Select the interface you wish to use", 1, j,
drvtypelist[0]);
}
memset(&ddesc, 0, sizeof(ddesc));
ddesc.type = drvtypelist[sel - 1];
switch (ddesc.type) {
case DRVTYPE_PD:
ddesc.drv.pd.minsize = -2L;
ddesc.drv.pd.maxsize = -2L;
break;
case DRVTYPE_NDIS:
ddesc.drv.ndis.minsize = -2L;
ddesc.drv.ndis.maxsize = -2L;
break;
case DRVTYPE_UNDI:
default:
break;
}
return(&ddesc);
}
/*
* Get network driver options
*/
static char *getnetopt(str, opt)
char *str;
int opt;
{
long hwirq = 0L;
long ioaddr = 0L;
long basemem = 0L;
long dmanum = 0L;
long auitype = 0L;
int retbuflen, retbufsize;
char *cp, *retbuf, buf[128], c;
size_t len;
/* Ask the user for required driver values */
if (opt) {
printf("Enter network driver options:\n");
if (opt & HW_IRQ)
hwirq = getnum(" Hardware IRQ number", 2, 15, FALSE);
if (opt & IO_ADDR)
ioaddr = getnum(" I/O address", 0, 0xffff, TRUE);
if (opt & BASE_MEM)
basemem = getnum(" Shared memory address", 0, 0xffff, TRUE);
if (opt & DMA_NUM)
dmanum = getnum(" DMA number", 0, 7, FALSE);
if (opt & AUI_TYPE)
auitype = getnum(" AUI type (-1 for default)", -1, 1, FALSE);
}
if (auitype < 0L)
auitype = 65535L;
/* Generate return string */
retbuf = NULL;
retbuflen = retbufsize = 0;
while (*str) {
if (*str != '%') {
buf[0] = *str;
buf[1] = '\0';
} else {
if (!(c = *(++str)))
break;
switch (c) {
case 'S':
sprintf(buf, "%x", DEFAULTINT);
break;
case 's':
sprintf(buf, "%d", DEFAULTINT);
break;
case 'H':
sprintf(buf, "%lx", hwirq);
break;
case 'h':
sprintf(buf, "%ld", hwirq);
break;
case 'A':
sprintf(buf, "%lx", ioaddr);
break;
case 'a':
sprintf(buf, "%ld", ioaddr);
break;
case 'M':
sprintf(buf, "%lx", basemem);
break;
case 'm':
sprintf(buf, "%ld", basemem);
break;
case 'D':
sprintf(buf, "%lx", dmanum);
break;
case 'd':
sprintf(buf, "%ld", dmanum);
break;
case 't':
if (auitype > 0)
sprintf(buf, "%ld", auitype);
break;
default:
buf[0] = c;
buf[1] = '\0';
break;
}
}
str++;
len = (((retbuflen + strlen(buf) + 1) / 32) + 1) * 32;
if (retbufsize < len) {
cp = (char *)nbmalloc(len);
if (retbuf != NULL) {
strcpy(cp, retbuf);
free(retbuf);
}
retbuf = cp;
retbufsize = len;
}
cp = &retbuf[retbuflen];
strcpy(cp, buf);
retbuflen += strlen(buf);
}
return(retbuf);
}
/*
* Ask the user about DOS program execution sizes
*/
static void getsizes(minsize, maxsize, needmin)
long *minsize;
long *maxsize;
int needmin;
{
long smin, smax;
while (TRUE) {
/*
* The sizes are defined as follows:
*
* minimum size - Size of the program after becoming resident.
* If the program doesn't get resident this
* number should be zero. The default is that
* the program becomes resident, and it's size
* resident size is the same as the load size.
*
* maximum size - Size of the program when it gets loaded and
* before it gets started. The default is deter-
* mined lateron by the binary patch routines.
* For EXE programs, the size is in the EXE
* header. COM programs always get 64kB.
*/
smin = getnum("Enter minimum execution size in bytes (-1 = default)",
-1L, MAXEXECSIZE, FALSE);
smax = getnum("Enter maximum execution size in bytes (-1 = default)",
-1L, MAXEXECSIZE, FALSE);
if (smax == 0L)
printf("Maximum size is not allowed to be zero\n");
else if (needmin && smin == 0L)
printf("Minimum size is not allowed to be zero\n");
else if (smin > 0L && smax > 0L && smin > smax)
printf("Minimum size is larger than maximum size\n");
else
break;
}
*minsize = smin;
*maxsize = smax;
}
/*
* Ask the user about additional DOS programs to execute
*/
static int getuserprog(pdp)
struct progdef *pdp;
{
int i;
int drvindex = 0;
char *pathname = NULL;
char *cmdline = NULL;
char *pattern = NULL;
char *buf;
long minsize, maxsize;
copystr(&pattern, "*.com:*.exe");
while(getyn("Do you want to specify an additional program", FALSE)) {
pathname = getfilename("Enter path name of the program",
config.utilsdir, pattern);
buf = getstring("Enter command line for the program");
if (*buf)
copystr(&cmdline, buf);
getsizes(&minsize, &maxsize, FALSE);
if (getyn("Should the program run before the network driver", FALSE)) {
for (i = pdp->prognum; i > drvindex; i--) {
pdp->prognames[i] = pdp->prognames[i - 1];
pdp->progargs[i] = pdp->progargs[i - 1];
pdp->minsizes[i] = pdp->minsizes[i - 1];
pdp->maxsizes[i] = pdp->maxsizes[i - 1];
}
drvindex++;
} else
i = pdp->prognum;
pdp->prognames[i] = pathname;
pdp->progargs[i] = cmdline;
pdp->minsizes[i] = minsize;
pdp->maxsizes[i] = maxsize;
pdp->prognum++;
}
free(pattern);
return(drvindex);
}
/*
* Ask the user about relevant information for packet drivers
*/
static void getpktdrvinfo(dp)
struct drvdesc *dp;
{
struct pktdrvdef *defp = &bootd.netdrv.driverdefs.pd;
int options = 0;
long minsize = -2L;
long maxsize = -2L;
char *filename = NULL;
char *cmdline = NULL;
/* Get info from description record */
assert(dp != NULL);
filename = dp->filename;
cmdline = dp->drv.pd.cmdline;
options = dp->drv.pd.options;
minsize = dp->drv.pd.minsize;
maxsize = dp->drv.pd.maxsize;
/* Get filename of packet driver binary */
if (filename == NULL)
defp->progs.prognames[0] = getfilename("Enter path of packet driver",
config.netdrv[DRVTYPE_PD].searchdir,
config.netdrv[DRVTYPE_PD].patlist);
else
defp->progs.prognames[0] = filename;
defp->progs.prognum = 1;
/* Ask user for command line options */
if (cmdline == NULL) {
cmdline = getstring("Enter command line for packet driver [0x%S]");
if (!*cmdline)
cmdline = "0x%S";
}
defp->progs.progargs[0] = getnetopt(cmdline, options);
/* Ask user about execution sizes */
if (minsize < -1L || maxsize < -1L || maxsize == 0)
getsizes(&minsize, &maxsize, TRUE);
defp->progs.minsizes[0] = minsize;
defp->progs.maxsizes[0] = maxsize;
/* Ask the user if to include the packet driver debugger program */
filename = NULL;
copystr(&filename, "pktwatch.com");
checkaccess(&filename, config.utilsdir);
if (filename != NULL &&
getyn("Do you want to use the packet driver debugger", FALSE)) {
defp->progs.prognames[defp->progs.prognum] = filename;
defp->progs.progargs[defp->progs.prognum] = NULL;
defp->progs.minsizes[defp->progs.prognum] = filesize(filename);
defp->progs.maxsizes[defp->progs.prognum] =
defp->progs.minsizes[defp->progs.prognum] + PKTWATCHSIZE;
defp->progs.prognum++;
}
/* Ask the user to include additional programs */
defp->drvindex = getuserprog(&(defp->progs));
}
/*
* Ask the user about relevant information for NDIS drivers
*/
static void getndisinfo(dp)
struct drvdesc *dp;
{
struct ndisdef *defp = &bootd.netdrv.driverdefs.ndis;
int options = 0;
long minsize = -2L;
long maxsize = -2L;
char *filename = NULL;
char *protini = NULL;
char *cp;
/* Get info from description record */
assert(dp != NULL);
filename = dp->filename;
protini = dp->drv.ndis.protini;
options = dp->drv.ndis.options;
minsize = dp->drv.ndis.minsize;
maxsize = dp->drv.ndis.maxsize;
/* Get filename of NDIS driver binary */
if (filename == NULL)
defp->progs.prognames[0] = getfilename("Enter path of NDIS driver",
config.netdrv[DRVTYPE_NDIS].searchdir,
config.netdrv[DRVTYPE_NDIS].patlist);
else
defp->progs.prognames[0] = filename;
defp->progs.progargs[0] = NULL;
defp->progs.prognum = 1;
/* Ask user about execution sizes */
if (minsize < -1L || maxsize < -1L || maxsize == 0)
getsizes(&minsize, &maxsize, TRUE);
defp->progs.minsizes[0] = minsize;
defp->progs.maxsizes[0] = maxsize;
/* Ask for protocol.ini file and driver options and normalize protocol.ini */
filename = NULL;
if (protini != NULL && !strncmp(protini, "file:", 5))
copystr(&filename, &(protini[5]));
if (protini == NULL || (filename != NULL && !*filename))
filename = getfilename("Enter path name of PROTOCOL.INI file",
config.netdrvdir, "*.ini");
if (filename != NULL) {
cp = readprotini(filename);
protini = getnetopt(cp, options);
free(filename);
free(cp);
} else {
protini = getnetopt(protini, options);
}
parseprotini(protini, &(defp->protocolini), &(defp->protinisize));
free(protini);
/* Ask the user to include additional program */
defp->drvindex = getuserprog(&(defp->progs));
}
/*
* Ask the user about relevant information for UNDI drivers
*/
static void getundiinfo(dp)
struct drvdesc *dp;
{
struct undidef *defp = &bootd.netdrv.driverdefs.undi;
char *filename = NULL;
/* Get info from description record */
assert(dp != NULL);
filename = dp->filename;
/* Get filename of UNDI driver binary */
if (filename == NULL)
defp->name = getfilename("Enter path name of UNDI driver",
config.netdrv[DRVTYPE_UNDI].searchdir,
config.netdrv[DRVTYPE_UNDI].patlist);
else
defp->name = filename;
}
/*
* Let the user select a network driver and get all relevant information for
* the network driver.
*/
static void getdrvinfo(fp)
struct filedesc *fp;
{
struct drvdesc *dp;
/* Let the user select the network driver */
dp = getnetdrv(fp);
assert(dp != NULL && dp->type >= DRVTYPE_MIN && dp->type <= DRVTYPE_MAX);
if (is86)
copystr(&bootd.netdrv.name, config.netdrv[dp->type].filename16);
else
copystr(&bootd.netdrv.name, config.netdrv[dp->type].filename32);
bootd.netdrv.drivertype = dp->type;
/* Let the user enter all relevant information for the network driver */
switch (dp->type) {
case DRVTYPE_PD:
getpktdrvinfo(dp);
break;
case DRVTYPE_NDIS:
getndisinfo(dp);
break;
case DRVTYPE_UNDI:
getundiinfo(dp);
break;
}
printf("\n\n");
}
/*
**************************************************************************
*
* Main routine
*
**************************************************************************
*/
/*
* Main routine which handles all user input
*/
struct bootdef *getuser()
{
struct filedesc *fp;
getkernel();
getnetcard(&fp);
getdrvinfo(fp);
getouttype();
return(&bootd);
}
syntax highlighted by Code2HTML, v. 0.9.1