📄 autoconf.c
字号:
node = firstchild(findroot()); while ((node = findnode(node, "zs")) != 0) { if (getpropint(node, "slave", -1) == zs) { if ((addr = getpropint(node, "address", 0)) == 0) panic("findzs: zs%d not mapped by PROM", zs); return ((void *)addr); } node = nextsibling(node); } panic("findzs: cannot find zs%d", zs); /* NOTREACHED */}intmakememarr(ap, max, which) register struct memarr *ap; int max, which;{ struct v2rmi { int zero; int addr; int len; } v2rmi[200]; /* version 2 rom meminfo layout */#define MAXMEMINFO (sizeof(v2rmi) / sizeof(*v2rmi)) register struct v0mlist *mp; register int i, node, len; char *prop; switch (i = promvec->pv_romvec_vers) { case 0: /* * Version 0 PROMs use a linked list to describe these * guys. */ switch (which) { case MEMARR_AVAILPHYS: mp = *promvec->pv_v0mem.v0_physavail; break; case MEMARR_TOTALPHYS: mp = *promvec->pv_v0mem.v0_phystot; break; default: panic("makememarr"); } for (i = 0; mp != NULL; mp = mp->next, i++) { if (i >= max) goto overflow; ap->addr = (u_int)mp->addr; ap->len = mp->nbytes; ap++; } break; default: printf("makememarr: hope version %d PROM is like version 2\n", i); /* FALLTHROUGH */ case 2: /* * Version 2 PROMs use a property array to describe them. */ if (max > MAXMEMINFO) { printf("makememarr: limited to %d\n", MAXMEMINFO); max = MAXMEMINFO; } if ((node = findnode(firstchild(findroot()), "memory")) == 0) panic("makememarr: cannot find \"memory\" node"); switch (which) { case MEMARR_AVAILPHYS: prop = "available"; break; case MEMARR_TOTALPHYS: prop = "reg"; break; default: panic("makememarr"); } len = getprop(node, prop, (void *)v2rmi, sizeof v2rmi) / sizeof(struct v2rmi); for (i = 0; i < len; i++) { if (i >= max) goto overflow; ap->addr = v2rmi[i].addr; ap->len = v2rmi[i].len; ap++; } break; } /* * Success! (Hooray) */ if (i == 0) panic("makememarr: no memory found"); return (i);overflow: /* * Oops, there are more things in the PROM than our caller * provided space for. Truncate any extras. */ printf("makememarr: WARNING: lost some memory\n"); return (i);}/* * Internal form of getprop(). Returns the actual length. */intgetprop(node, name, buf, bufsiz) int node; char *name; void *buf; register int bufsiz;{ register struct nodeops *no; register int len; no = promvec->pv_nodeops; len = no->no_proplen(node, name); if (len > bufsiz) { printf("node %x property %s length %d > %d\n", node, name, len, bufsiz);#ifdef DEBUG panic("getprop");#else return (0);#endif } no->no_getprop(node, name, buf); return (len);}/* * Return a string property. There is a (small) limit on the length; * the string is fetched into a static buffer which is overwritten on * subsequent calls. */char *getpropstring(node, name) int node; char *name;{ register int len; static char stringbuf[32]; len = getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1); stringbuf[len] = '\0'; /* usually unnecessary */ return (stringbuf);}/* * Fetch an integer (or pointer) property. * The return value is the property, or the default if there was none. */intgetpropint(node, name, deflt) int node; char *name; int deflt;{ register int len; char intbuf[16]; len = getprop(node, name, (void *)intbuf, sizeof intbuf); if (len != 4) return (deflt); return (*(int *)intbuf);}/* * OPENPROM functions. These are here mainly to hide the OPENPROM interface * from the rest of the kernel. */intfirstchild(node) int node;{ return (promvec->pv_nodeops->no_child(node));}intnextsibling(node) int node;{ return (promvec->pv_nodeops->no_nextnode(node));}#ifdef RCONSOLE/* Pass a string to the FORTH PROM to be interpreted */voidrominterpret(s) register char *s;{ if (promvec->pv_romvec_vers < 2) promvec->pv_fortheval.v0_eval(strlen(s), s); else promvec->pv_fortheval.v2_eval(s);}/* * Try to figure out where the PROM stores the cursor row & column * variables. Returns nonzero on error. */intromgetcursoraddr(rowp, colp) register int **rowp, **colp;{ char buf[100]; /* * line# and column# are global in older proms (rom vector < 2) * and in some newer proms. They are local in version 2.9. The * correct cutoff point is unknown, as yet; we use 2.9 here. */ if (promvec->pv_romvec_vers < 2 || promvec->pv_printrev < 0x00020009) sprintf(buf, "' line# >body >user %x ! ' column# >body >user %x !", rowp, colp); else sprintf(buf, "stdout @ is my-self addr line# %x ! addr column# %x !", rowp, colp); *rowp = *colp = NULL; rominterpret(buf); return (*rowp == NULL || *colp == NULL);}#endifvolatile voidromhalt(){ promvec->pv_halt(); panic("PROM exit failed");}volatile voidromboot(str) char *str;{ promvec->pv_reboot(str); panic("PROM boot failed");}callrom(){#ifdef notdef /* sun4c FORTH PROMs do this for us */ fb_unblank();#endif promvec->pv_abort();}/* * Configure swap space and related parameters. */swapconf(){ register struct swdevt *swp; register int nblks; for (swp = swdevt; swp->sw_dev != NODEV; swp++) if (bdevsw[major(swp->sw_dev)].d_psize) { nblks = (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev); if (nblks != -1 && (swp->sw_nblks == 0 || swp->sw_nblks > nblks)) swp->sw_nblks = nblks; }}#define DOSWAP /* Change swdevt and dumpdev too */u_long bootdev; /* should be dev_t, but not until 32 bits */#define PARTITIONMASK 0x7#define PARTITIONSHIFT 3static intfindblkmajor(dv) register struct dkdevice *dv;{ register int i; for (i = 0; i < nblkdev; ++i) if ((void (*)(struct buf *))bdevsw[i].d_strategy == dv->dk_driver->d_strategy) return (i); return (-1);}static struct device *getdisk(str, len, defpart, devp) char *str; int len, defpart; dev_t *devp;{ register struct device *dv; if ((dv = parsedisk(str, len, defpart, devp)) == NULL) { printf("use one of:"); for (dv = alldevs; dv != NULL; dv = dv->dv_next) if (dv->dv_class == DV_DISK) printf(" %s[a-h]", dv->dv_xname); printf("\n"); } return (dv);}struct device *parsedisk(str, len, defpart, devp) char *str; int len, defpart; dev_t *devp;{ register struct device *dv; register char *cp, c; int majdev, mindev, part; if (len == 0) return (NULL); cp = str + len - 1; c = *cp; if (c >= 'a' && c <= 'h') { part = c - 'a'; *cp = '\0'; } else part = defpart; for (dv = alldevs; dv != NULL; dv = dv->dv_next) { if (dv->dv_class == DV_DISK && strcmp(str, dv->dv_xname) == 0) { majdev = findblkmajor((struct dkdevice *)dv); if (majdev < 0) panic("parsedisk"); mindev = (dv->dv_unit << PARTITIONSHIFT) + part; *devp = makedev(majdev, mindev); break; } } *cp = c; return (dv);}/* * Attempt to find the device from which we were booted. * If we can do so, and not instructed not to do so, * change rootdev to correspond to the load device. */voidsetroot(){ register struct swdevt *swp; register struct device *dv; register int len, majdev, mindev, part; dev_t nrootdev, nswapdev; char buf[128];#ifdef DOSWAP dev_t temp;#endif#ifdef NFS extern int (*mountroot)(), nfs_mountroot();#endif if (boothowto & RB_ASKNAME) { for (;;) { printf("root device? "); len = getstr(buf, sizeof(buf));#ifdef GENERIC if (len > 0 && buf[len - 1] == '*') { buf[--len] = '\0'; dv = getdisk(buf, len, 1, &nrootdev); if (dv != NULL) { bootdv = dv; nswapdev = nrootdev; goto gotswap; } }#endif dv = getdisk(buf, len, 0, &nrootdev); if (dv != NULL) { bootdv = dv; break; } } for (;;) { printf("swap device (default %sb)? ", bootdv->dv_xname); len = getstr(buf, sizeof(buf)); if (len == 0) { nswapdev = makedev(major(nrootdev), (minor(nrootdev) & ~ PARTITIONMASK) | 1); break; } if (getdisk(buf, len, 1, &nswapdev) != NULL) break; }#ifdef GENERICgotswap:#endif rootdev = nrootdev; swapdev = nswapdev; dumpdev = nswapdev; /* ??? */ swdevt[0].sw_dev = nswapdev; swdevt[1].sw_dev = NODEV; return; } /* XXX currently there's no way to set RB_DFLTROOT... */ if (boothowto & RB_DFLTROOT || bootdv == NULL) return; switch (bootdv->dv_class) {#ifdef NFS case DV_IFNET: mountroot = nfs_mountroot; return;#endif#if defined(FFS) || defined(LFS) case DV_DISK: majdev = findblkmajor((struct dkdevice *)bootdv); if (majdev < 0) return; part = 0; mindev = (bootdv->dv_unit << PARTITIONSHIFT) + part; break;#endif default: printf("can't figure root, hope your kernel is right\n"); return; } /* * Form a new rootdev */ nrootdev = makedev(majdev, mindev); /* * If the original rootdev is the same as the one * just calculated, don't need to adjust the swap configuration. */ if (rootdev == nrootdev) return; rootdev = nrootdev; printf("Changing root device to %s%c\n", bootdv->dv_xname, part + 'a');#ifdef DOSWAP mindev &= ~PARTITIONMASK; temp = NODEV; for (swp = swdevt; swp->sw_dev != NODEV; swp++) { if (majdev == major(swp->sw_dev) && mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) { temp = swdevt[0].sw_dev; swdevt[0].sw_dev = swp->sw_dev; swp->sw_dev = temp; break; } } if (swp->sw_dev == NODEV) return; /* * If dumpdev was the same as the old primary swap device, move * it to the new primary swap device. */ if (temp == dumpdev) dumpdev = swdevt[0].sw_dev;#endif}static intgetstr(cp, size) register char *cp; register int size;{ register char *lp; register int c; register int len; lp = cp; len = 0; for (;;) { c = cngetc(); switch (c) { case '\n': case '\r': printf("\n"); *lp++ = '\0'; return (len); case '\b': case '\177': case '#': if (len) { --len; --lp; printf(" \b "); } continue; case '@': case 'u'&037: len = 0; lp = cp; printf("\n"); continue; default: if (len + 1 >= size || c < ' ') { printf("\007"); continue; } printf("%c", c); ++len; *lp++ = c; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -