summaryrefslogtreecommitdiff
path: root/release/picobsd/tinyware/kget/uc_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'release/picobsd/tinyware/kget/uc_main.c')
-rw-r--r--release/picobsd/tinyware/kget/uc_main.c475
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);
+}