/* * user.c - user interface for makerom bootrom configuration utility * * Copyright (C) 1995-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: user.c,v 1.8 2003/03/09 00:43:08 gkminix Exp $ */ #include #include #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 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 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); }