diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-05-04 03:44:46 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-05-04 03:44:46 +0000 |
commit | ec952e9183677d6369513031c05b09bd06afbea5 (patch) | |
tree | c876489f480abe0543e72709f1f25e73f920e72a /sys/arch/sparc | |
parent | af9c38d3cda06154a0cbd5dbfa54d94871c5bd39 (diff) |
setroot() was a ugly mix of MI and MD code, with different bugs on different
machines. Instead -- build one solid clean MI version, and thenchange all
the architectures to use it. ok various people, tested on almost all cases.
(it is a 10094 line diff..)
Diffstat (limited to 'sys/arch/sparc')
-rw-r--r-- | sys/arch/sparc/include/autoconf.h | 5 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/autoconf.c | 506 |
2 files changed, 75 insertions, 436 deletions
diff --git a/sys/arch/sparc/include/autoconf.h b/sys/arch/sparc/include/autoconf.h index a7aefd81e28..7e2a690d1af 100644 --- a/sys/arch/sparc/include/autoconf.h +++ b/sys/arch/sparc/include/autoconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.h,v 1.15 2005/07/08 12:42:57 miod Exp $ */ +/* $OpenBSD: autoconf.h,v 1.16 2007/05/04 03:44:44 deraadt Exp $ */ /* $NetBSD: autoconf.h,v 1.20 1997/05/24 20:03:03 pk Exp $ */ /* @@ -190,9 +190,6 @@ struct bootpath { struct bootpath *bootpath_store(int, struct bootpath *); int sd_crazymap(int); -/* Parse a disk string into a dev_t, return device struct pointer */ -struct device *parsedisk(char *, int, int, dev_t *); - void bootstrap(void); int firstchild(int); int nextsibling(int); diff --git a/sys/arch/sparc/sparc/autoconf.c b/sys/arch/sparc/sparc/autoconf.c index 5e1b2c5b2e8..f21afa87351 100644 --- a/sys/arch/sparc/sparc/autoconf.c +++ b/sys/arch/sparc/sparc/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.76 2007/04/30 18:37:00 deraadt Exp $ */ +/* $OpenBSD: autoconf.c,v 1.77 2007/05/04 03:44:44 deraadt Exp $ */ /* $NetBSD: autoconf.c,v 1.73 1997/07/29 09:41:53 fair Exp $ */ /* @@ -102,12 +102,7 @@ extern int kgdb_debug_panic; #endif static int rootnode; -void setroot(void); static char *str2hex(char *, int *); -static int getstr(char *, int); -int findblkmajor(struct device *); -char *findblkname(int); -static struct device *getdisk(char *, int, int, dev_t *); static int mbprint(void *, const char *); static void crazymap(char *, int *); void sync_crash(void); @@ -122,10 +117,6 @@ static void bootpath_print(struct bootpath *); int search_prom(int, char *); char mainbus_model[30]; -#ifdef RAMDISK_HOOKS -static struct device fakerdrootdev = { DV_DISK, {}, NULL, 0, "rd0", NULL }; -#endif - /* Translate SBus interrupt level to processor IPL */ int intr_sbus2ipl_4c[] = { 0, 1, 2, 3, 5, 7, 8, 9 @@ -372,8 +363,6 @@ bootpath_build() if (cp != NULL) bootpath_fake(bp, cp); - bootpath_print(bootpath); - /* Setup pointer to boot flags */ cp = (*promvec->pv_v0bootargs)->ba_argv[1]; if (cp == NULL || *cp != '-') @@ -418,8 +407,6 @@ bootpath_build() } bp->name[0] = 0; - bootpath_print(bootpath); - /* Setup pointer to boot flags */ cp = *promvec->pv_v2bootargs.v2_bootargs; if (cp == NULL) @@ -762,6 +749,8 @@ cpu_configure() struct confargs oca; register int node = 0; register char *cp; + struct bootpath *bp; + struct device *bootdv; int s; extern struct user *proc0paddr; @@ -852,7 +841,12 @@ cpu_configure() * Configure swap area and related system * parameter based on device(s) used. */ - setroot(); + bootpath_print(bootpath); + + bp = nbootpath == 0 ? NULL : &bootpath[nbootpath-1]; + bootdv = (bp == NULL) ? NULL : bp->dev; + + setroot(bootdv, bp->val[2], RB_USERREQ | RB_HALT); dumpconf(); cold = 0; @@ -1743,423 +1737,6 @@ callrom() promvec->pv_abort(); } -#if 0 /* Unused */ -dev_t bootdev; -#endif - -struct nam2blk { - char *name; - int maj; -} nam2blk[] = { - { "xy", 3 }, - { "sd", 7 }, - { "xd", 10 }, - { "st", 11 }, - { "fd", 16 }, - { "rd", 17 }, - { "cd", 18 }, - { "raid", 25 }, -}; - -int -findblkmajor(dv) - struct device *dv; -{ - char *name = dv->dv_xname; - int i; - - for (i = 0; i < sizeof(nam2blk)/sizeof(nam2blk[0]); ++i) - if (strncmp(name, nam2blk[i].name, strlen(nam2blk[i].name)) == 0) - return (nam2blk[i].maj); - return (-1); -} - -char * -findblkname(maj) - int maj; -{ - int i; - - for (i = 0; i < sizeof(nam2blk)/sizeof(nam2blk[0]); ++i) - if (nam2blk[i].maj == maj) - return (nam2blk[i].name); - return (NULL); -} - -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: exit"); -#ifdef RAMDISK_HOOKS - printf(" %s[a-p]", fakerdrootdev.dv_xname); -#endif - TAILQ_FOREACH(dv, &alldevs, dv_list) { - if (dv->dv_class == DV_DISK) - printf(" %s[a-p]", dv->dv_xname); -#ifdef NFSCLIENT - if (dv->dv_class == DV_IFNET) - printf(" %s", dv->dv_xname); -#endif - } - 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, unit, part; - - if (len == 0) - return (NULL); - cp = str + len - 1; - c = *cp; - if (c >= 'a' && (c - 'a') < MAXPARTITIONS) { - part = c - 'a'; - *cp = '\0'; - } else - part = defpart; - -#ifdef RAMDISK_HOOKS - if (strcmp(str, fakerdrootdev.dv_xname) == 0) { - dv = &fakerdrootdev; - goto gotdisk; - } -#endif - - TAILQ_FOREACH(dv, &alldevs, dv_list) { - if (dv->dv_class == DV_DISK && - strcmp(str, dv->dv_xname) == 0) { -#ifdef RAMDISK_HOOKS -gotdisk: -#endif - majdev = findblkmajor(dv); - unit = dv->dv_unit; - if (majdev < 0) - panic("parsedisk"); - *devp = MAKEDISKDEV(majdev, unit, part); - break; - } -#ifdef NFSCLIENT - if (dv->dv_class == DV_IFNET && - strcmp(str, dv->dv_xname) == 0) { - *devp = NODEV; - break; - } -#endif - } - - *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. - * - * XXX Actually, swap and root must be on the same type of device, - * (ie. DV_DISK or DV_IFNET) because of how (*mountroot) is written. - * That should be fixed. - */ -void -setroot() -{ - register struct swdevt *swp; - register struct device *dv; - register int len, majdev, unit, part; - dev_t nrootdev, nswapdev = NODEV; - char buf[128]; - dev_t temp; - struct device *bootdv; - struct bootpath *bp; -#if defined(NFSCLIENT) - extern char *nfsbootdevname; -#endif - - bp = nbootpath == 0 ? NULL : &bootpath[nbootpath-1]; -#ifdef RAMDISK_HOOKS - bootdv = &fakerdrootdev; -#else - bootdv = (bp == NULL) ? NULL : bp->dev; -#endif - - /* - * (raid) device auto-configuration could have returned - * the root device's id in rootdev. Check this case. - */ - if (rootdev != NODEV) { - majdev = major(rootdev); - unit = DISKUNIT(rootdev); - part = DISKPART(rootdev); - - len = snprintf(buf, sizeof buf, "%s%d", findblkname(majdev), - unit); - if (len == -1 || len >= sizeof(buf)) - panic("setroot: device name too long"); - - if (len == 4 && strncmp(buf, "exit", 4) == 0) - boot(RB_USERREQ | RB_HALT); - bootdv = getdisk(buf, len, part, &rootdev); - } - - /* - * If `swap generic' and we couldn't determine boot device, - * ask the user. - */ - if (mountroot == NULL && bootdv == NULL) - boothowto |= RB_ASKNAME; - - if (boothowto & RB_ASKNAME) { - for (;;) { - printf("root device "); - if (bootdv != NULL) - printf("(default %s%c)", - bootdv->dv_xname, - bootdv->dv_class == DV_DISK - ? bp->val[2]+'a' : ' '); - printf(": "); - len = getstr(buf, sizeof(buf)); - if (len == 0 && bootdv != NULL) { - strlcpy(buf, bootdv->dv_xname, sizeof buf); - len = strlen(buf); - } - if (len == 4 && strncmp(buf, "exit", 4) == 0) - boot(RB_USERREQ | RB_HALT); - if (len > 0 && buf[len - 1] == '*') { - buf[--len] = '\0'; - dv = getdisk(buf, len, 1, &nrootdev); - if (dv != NULL) { - bootdv = dv; - nswapdev = nrootdev; - goto gotswap; - } - } - dv = getdisk(buf, len, bp?bp->val[2]:0, &nrootdev); - if (dv != NULL) { - bootdv = dv; - break; - } - } - - /* - * because swap must be on same device as root, for - * network devices this is easy. - */ - if (bootdv->dv_class == DV_IFNET) { - goto gotswap; - } - for (;;) { - printf("swap device "); - if (bootdv != NULL) - printf("(default %s%c)", - bootdv->dv_xname, - bootdv->dv_class == DV_DISK?'b':' '); - printf(": "); - len = getstr(buf, sizeof(buf)); - if (len == 4 && strncmp(buf, "exit", 4) == 0) - boot(RB_USERREQ | RB_HALT); - if (len == 0 && bootdv != NULL) { - switch (bootdv->dv_class) { - case DV_IFNET: - nswapdev = NODEV; - break; - case DV_DISK: - nswapdev = MAKEDISKDEV(major(nrootdev), - DISKUNIT(nrootdev), 1); - break; - case DV_TAPE: - case DV_TTY: - case DV_DULL: - case DV_CPU: - break; - } - break; - } - dv = getdisk(buf, len, 1, &nswapdev); - if (dv) { - if (dv->dv_class == DV_IFNET) - nswapdev = NODEV; - break; - } - } -gotswap: - rootdev = nrootdev; - dumpdev = nswapdev; - swdevt[0].sw_dev = nswapdev; - /* swdevt[1].sw_dev = NODEV; */ - - } else if (mountroot == NULL) { - - /* - * `swap generic': Use the device the ROM told us to use. - */ - majdev = findblkmajor(bootdv); - if (majdev >= 0) { - /* - * Root and swap are on a disk. - * val[2] of the boot device is the partition number. - * Assume swap is on partition b. - */ - part = bp->val[2]; - unit = bootdv->dv_unit; - rootdev = MAKEDISKDEV(majdev, unit, part); - nswapdev = dumpdev = MAKEDISKDEV(major(rootdev), - DISKUNIT(rootdev), 1); - } else { - /* - * Root and swap are on a net. - */ - nswapdev = dumpdev = NODEV; - } - swdevt[0].sw_dev = nswapdev; - /* swdevt[1].sw_dev = NODEV; */ - - } else { - - /* - * `root DEV swap DEV': honour rootdev/swdevt. - * rootdev/swdevt/mountroot already properly set. - */ - if (bootdv->dv_class == DV_DISK) - printf("root on %s%c\n", bootdv->dv_xname, - part + 'a'); - majdev = major(rootdev); - unit = DISKUNIT(rootdev); - part = DISKPART(rootdev); - return; - } - - switch (bootdv->dv_class) { -#if defined(NFSCLIENT) - case DV_IFNET: - mountroot = nfs_mountroot; - nfsbootdevname = bootdv->dv_xname; - return; -#endif - case DV_DISK: - mountroot = dk_mountroot; - majdev = major(rootdev); - unit = DISKUNIT(rootdev); - part = DISKPART(rootdev); - printf("root on %s%c\n", bootdv->dv_xname, - part + 'a'); - break; - default: - printf("can't figure root, hope your kernel is right\n"); - return; - } - - /* - * Make the swap partition on the root drive the primary swap. - */ - temp = NODEV; - for (swp = swdevt; swp->sw_dev != NODEV; swp++) { - if (majdev == major(swp->sw_dev) && - unit == DISKUNIT(swp->sw_dev)) { - temp = swdevt[0].sw_dev; - swdevt[0].sw_dev = swp->sw_dev; - swp->sw_dev = temp; - break; - } - } - if (swp->sw_dev != NODEV) { - /* - * 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; - } -} - -static int -getstr(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 \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; - } - } -} - - -/* - * find a device matching "name" and unit number - */ -struct device * -getdevunit(name, unit) - char *name; - int unit; -{ - struct device *dev = TAILQ_FIRST(&alldevs); - char num[10], fullname[16]; - int lunit; - - /* compute length of name and decimal expansion of unit number */ - snprintf(num, sizeof num, "%d", unit); - lunit = strlen(num); - if (strlen(name) + lunit >= sizeof(fullname) - 1) - panic("config_attach: device name too long"); - - strlcpy(fullname, name, sizeof fullname); - strlcat(fullname, num, sizeof fullname); - - while (strcmp(dev->dv_xname, fullname) != 0) { - if ((dev = TAILQ_NEXT(dev, dv_list)) == NULL) - return NULL; - } - return dev; -} - /* * find the boot device (if it was a disk). we must check to see if * unit info in saved bootpath structure matches unit info in our softc. @@ -2224,3 +1801,68 @@ device_register(struct device *dev, void *aux) } } } + +/* + * find a device matching "name" and unit number + */ +struct device * +getdevunit(name, unit) + char *name; + int unit; +{ + struct device *dev = TAILQ_FIRST(&alldevs); + char num[10], fullname[16]; + int lunit; + + /* compute length of name and decimal expansion of unit number */ + snprintf(num, sizeof num, "%d", unit); + lunit = strlen(num); + if (strlen(name) + lunit >= sizeof(fullname) - 1) + panic("config_attach: device name too long"); + + strlcpy(fullname, name, sizeof fullname); + strlcat(fullname, num, sizeof fullname); + + while (strcmp(dev->dv_xname, fullname) != 0) { + if ((dev = TAILQ_NEXT(dev, dv_list)) == NULL) + return NULL; + } + return dev; +} + +static struct { + char *name; + int maj; +} nam2blk[] = { + { "xy", 3 }, + { "sd", 7 }, + { "xd", 10 }, + { "st", 11 }, + { "fd", 16 }, + { "rd", 17 }, + { "cd", 18 }, + { "raid", 25 } +}; + +int +findblkmajor(struct device *dv) +{ + char *name = dv->dv_xname; + int i; + + for (i = 0; i < sizeof(nam2blk)/sizeof(nam2blk[0]); i++) + if (!strncmp(name, nam2blk[i].name, strlen(nam2blk[i].name))) + return (nam2blk[i].maj); + return (-1); +} + +char * +findblkname(int maj) +{ + int i; + + for (i = 0; i < sizeof(nam2blk)/sizeof(nam2blk[0]); i++) + if (nam2blk[i].maj == maj) + return (nam2blk[i].name); + return (NULL); +} |