diff options
Diffstat (limited to 'release/picobsd/tinyware/kget/uc_main.c')
| -rw-r--r-- | release/picobsd/tinyware/kget/uc_main.c | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/release/picobsd/tinyware/kget/uc_main.c b/release/picobsd/tinyware/kget/uc_main.c new file mode 100644 index 0000000000000..2f39a11a1a96b --- /dev/null +++ b/release/picobsd/tinyware/kget/uc_main.c @@ -0,0 +1,475 @@ +/*************************************************** + * file: userconfig/uc_main.c + * + * Copyright (c) 1996 Eric L. Hernes (erich@rrnet.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * library functions for userconfig library + * + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <signal.h> +#include <paths.h> +#include <sys/mman.h> +#include <nlist.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "uc_main.h" +#include "kget.h" + +FILE *f_out; + +static struct nlist _nl[] = { + {"_isa_devtab_bio"}, + {"_isa_devtab_tty"}, + {"_isa_devtab_cam"}, + {"_isa_devtab_net"}, + {"_isa_devtab_null"}, + {"_isa_biotab_wdc"}, + {"_isa_biotab_fdc"}, + {"_eisadriver_set"}, + {"_eisa_dev_list"}, + {"_pcidevice_set"}, + {"_device_list"}, + {"_scbusses"}, +#ifdef USE_SCSI + {"_scsi_cinit"}, + {"_scsi_dinit"}, + {"_scsi_tinit"}, +#endif + {""}, +}; + +int +isDebug() { + return(0); +} + +struct list * +vc_getdev(char *vanilla) +{ + FILE *fd; + struct list *dl; + char buf[100]; + + fd=fopen(vanilla,"r"); + if(fd==NULL) { + printf("no such file: %s\n",vanilla); + exit(2); + } + dl=list_new(); + while(!feof(fd)) { + buf[0]='\0'; + if(fgets(buf,99,fd)==NULL) continue; + buf[strlen(buf)-1]='\0'; + list_append(dl,buf); + } + fclose(fd); + return(dl); +} + +void +process(struct list *d, struct list *v, int flag) +{ + int i,idx,found; + int len; + char *tok,*sep=" "; + char *parm[]= {"<devname>", + "port", + "irq", + "drq", + "iomem", + "iosize", + "flags", + "<alive>", + "<enabled>", + "<modified>"}; + + if(!flag) { + fprintf(f_out,"%s",d->av[0]); + for(i=1;i<d->ac;i++) { + fprintf(f_out," %s",d->av[i]); + } + fprintf(f_out,"\n"); + return; + } + found=0; + for(i=0;i<v->ac;i++) { + if(strncmp(d->av[0],v->av[i],strlen(d->av[0]))!=0) continue; + found++; + break; + } + if(!found) { + printf("\nWhoa!\n"); + printf("Couldn't find device %s in 'vanilla' list!\n", + d->av[0]); + printf("It seems that kernel image and 'vanilla' list are out of sync...\n"); + exit(2); + } + idx=i; + if(strcmp(d->av[8],"0")==0) { /* disable and return */ + fprintf(f_out,"disable %s\n",d->av[0]); + return; + } + tok=strtok(v->av[idx],sep); /* discard <name> */ + for(i=1;i<d->ac;i++) { + tok=strtok(NULL,sep); /* get next param from string */ + if(tok==NULL) { + fprintf(stderr,"Hmmm... strange error, please report!\n"); + fprintf(stderr,"Include the 'kget -incore' output and the device name (%s)\n",d->av[0]); + exit(10); + } + if(strcmp(d->av[i],tok)!=0) { /* changed */ + switch(i) { + case 7: /* alive */ + break; + case 8: /* enable/disable */ + if(strcmp(d->av[i],"0")==0) { /* disable */ + fprintf(f_out,"disable %s\n",d->av[0]); + return; + } else { + fprintf(f_out,"enable %s\n",d->av[0]); + } + break; + case 2: /* special case for npx */ + if(strcmp(d->av[0],"npx0")==0) continue; + /* FALLTHROUGH */ + default: + fprintf(f_out,"%s %s %s\n",parm[i],d->av[0],d->av[i]); + break; + } + } + } + return; +} + +int main(int argc, char *argv[]) +{ + struct kernel *core; + struct list *c_isa, *c_dev,*v_isa; + int d,j,cnt=0; + int diff=0; + char buf[100]; + + if(argc<3) { + printf("Usage: %s name|-incore -|filename [vanilla]\n",argv[0]); + exit(1); + } + if(argc>3) { + v_isa=vc_getdev(argv[3]); + diff++; + } + core=uc_open(argv[1]); + c_isa=uc_getdev(core,"-isa"); + if(c_isa==NULL) { + printf("no symbols in kernel?\n"); + exit(2); + } + if(strcmp(argv[2],"-")==NULL) { + f_out=stdout; + } else { + f_out=fopen(argv[2],"w"); + if(f_out==NULL) f_out=stdout; + } + if(diff) fprintf(f_out,"USERCONFIG\n"); + for(d=0;d<c_isa->ac;d++) { + c_dev=uc_getdev(core,c_isa->av[d]); + process(c_dev,v_isa,diff); + } + if(diff) fprintf(f_out,"quit\n"); + uc_close(core,0); + exit(0); +} + +struct kernel * +uc_open(char *name){ + int kd, flags, incore; + struct kernel *kern; + struct stat sb; + char kname[80]; + int size, i = 0; + struct nlist *nl = _nl; + + if (strcmp(name, "-incore") == 0) + incore = 1; + else + incore = 0; + + if (incore || (strcmp(name,"-bootfile") == 0)) + SAFE_STRCPY(kname, getbootfile()); + else + SAFE_STRCPY(kname, name); + + if (isDebug()) + msgDebug("uc_open: kernel name is %s, incore = %d\n", kname, incore); + kern = (struct kernel *)malloc(sizeof(struct kernel)); + +#ifdef KERN_NO_SYMBOLS + if (incore) { + FILE *fp; + + fp = fopen("/stand/symbols", "r"); + if (!fp) { + msgDebug("Couldn't open /stand/symbols file! Punting.\n"); + free(kern); + return NULL; + } + if (fscanf(fp, "%d\n", &size) != 1) { + msgDebug("Unable to get # of name list entries from symbol file.\n"); + free(kern); + return NULL; + } + else if (isDebug()) + msgDebug("uc_open: opened /stand/symbols file, reading %d entries.\n", size); + + + kern->nl = nl = (struct nlist *)malloc((size + 1) * sizeof(struct nlist)); + bzero(nl, (size + 1) * sizeof(struct nlist)); + for (i = 0; i < size; i++) { + char *cp, name[255]; + int c1; + unsigned int uc1; + short d1; + unsigned long v1; + + if (fgets(name, 255, fp) == NULL) { + msgDebug("Can't get name field for entry %d\n", i); + free(kern); + return NULL; + } + if ((cp = index(name, '\n')) != NULL) + *cp = '\0'; + nl[i].n_name = strdup(name); + if (fscanf(fp, "%u %d %hd %ld\n", &uc1, &c1, &d1, &v1) == 4) { + nl[i].n_type = (unsigned char)uc1; + nl[i].n_other = (char)c1; + nl[i].n_desc = d1; + nl[i].n_value = v1; + if (isDebug()) + msgDebug("uc_open: for entry %d, decoded: \"%s\", %u %d %hd %ld\n", i, nl[i].n_name, nl[i].n_type, nl[i].n_other, nl[i].n_desc, nl[i].n_value); + } + } + nl[i].n_name = ""; + fclose(fp); + i = 0; + } + else +#endif + i = nlist(kname, nl); + if (i == -1) { + msgDebug("uc_open: kernel %s does not contain symbols.\n", kname); + free(kern); + return NULL; + } +#ifdef KERN_NO_SYMBOLS + if (!incore) { +#else + { +#endif + kern->nl=(struct nlist *)malloc(sizeof(_nl)); + bcopy(_nl, kern->nl, sizeof(_nl)); + } + + if (incore) { + if (isDebug()) + msgDebug("uc_open: attempting to open /dev/kmem for incore.\n"); + if ((kd = open("/dev/kmem", O_RDONLY)) < 0) { + free(kern); + msgDebug("uc_open: Unable to open /dev/kmem.\n"); + return NULL; + } + kern->core = (caddr_t)NULL; + kern->incore = 1; + kern->size = 0; + } + else { + if (stat(kname, &sb) < 0) { + free(kern); + msgDebug("uc_open: Unable to stat %s.\n", kname); + return NULL; + } + kern->size = sb.st_size; + flags = sb.st_flags; + + if (chflags(kname, 0) < 0) { + free(kern); + msgDebug("uc_open: Unable to chflags %s.\n", kname); + return NULL; + } + + if (isDebug()) + msgDebug("uc_open: attempting to open %s\n", kname); + if ((kd = open(kname, O_RDWR, 0644)) < 0) { + free(kern); + msgDebug("uc_open: Unable to open %s.\n", kname); + return NULL; + } + + fchflags(kd, flags); + + if (isDebug()) + msgDebug("uc_open: attempting to mmap %d bytes\n", sb.st_size); + kern->core = mmap((caddr_t)0, sb.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, kd, 0); + kern->incore = 0; + if (kern->core == MAP_FAILED) { + free(kern); + msgDebug("uc_open: Unable to mmap from %s.\n", kname); + return NULL; + } + } + + kern->fd = kd; + get_isa_info(kern); + if (isDebug()) + msgDebug("uc_open: got isa information\n"); + + get_pci_info(kern); + if (isDebug()) + msgDebug("uc_open: got pci information\n"); + + get_eisa_info(kern); + if (isDebug()) + msgDebug("uc_open: got eisa information\n"); +#ifdef USE_SCSI + get_scsi_info(kern); + if (isDebug()) + msgDebug("uc_open: got scsi information\n"); +#else + kern->scsi_devp=(struct uc_scsi*)NULL; + kern->scsibus_devp=(struct uc_scsibus*)NULL; +#endif + return kern; +} + +int +uc_close(struct kernel *kern, int writeback) +{ + if (kern->isa_devp) + isa_free(kern, writeback); + + if (kern->eisa_devp) + eisa_free(kern, writeback); /* `writeback' isn't really useful here */ + + if (kern->pci_devp) + pci_free(kern, writeback); /* or here */ + +#ifdef USE_SCSI + if (kern->scsi_devp) + scsi_free(kern, writeback); +#endif + + if (!kern->incore) + munmap(kern->core, kern->size); + + close(kern->fd); + free(kern->nl); + free(kern); + + return 0; +} + +struct list * +uc_getdev(struct kernel *kern, char *dev) +{ + struct list *list = (struct list *)0; + + if (*dev == '-') { /* asked for -isa, -eisa, -pci, -scsi, -all */ + if (strcmp(dev, "-all") == 0) { + list = list_new(); + if (kern->isa_devp) + list_append(list, "isa"); + + if (kern->eisa_devp) + list_append(list, "eisa"); + + if (kern->pci_devp) + list_append(list, "pci"); + + if (kern->scsi_devp) + list_append(list, "scsi"); + + } + else if (strcmp(dev, "-isa") == 0) + list = get_isa_devlist(kern); + else if (strcmp(dev, "-eisa") == 0) + list = get_eisa_devlist(kern); + else if (strcmp(dev, "-pci") == 0) + list = get_pci_devlist(kern); +#ifdef USE_SCSI + else if (strcmp(dev, "-scsi") == 0) + list = get_scsi_devlist(kern); +#endif + } + else { + /* we gotta figure out which real device to report */ + struct uc_isa *ip; + struct uc_scsi *sp; + struct uc_pci *pp; + struct uc_eisa *ep; + + if (kern->isa_devp) { + for (ip = kern->isa_devp; ip->device; ip++) { + if (strcmp(dev, ip->device) == 0) { + list = get_isa_device(ip); + goto end; + } + } + } + +#ifdef USE_SCSI + if (kern->scsi_devp) { + for (sp = kern->scsi_devp; sp->device; sp++) { + if (strcmp(dev, sp->device) == 0) { + list = get_scsi_device(sp); + goto end; + } + } + } +#endif + + if (kern->pci_devp) { + for(pp = kern->pci_devp; pp->device; pp++) { + if (strcmp(dev, pp->device) == 0) { + list = get_pci_device(pp); + goto end; + } + } + } + + if (kern->eisa_devp) { + for (ep = kern->eisa_devp; ep->device; ep++) { + if (strcmp(dev, ep->device) == 0) { + list = get_eisa_device(ep); + goto end; + } + } + } + } +end: + return(list); +} |
