diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2006-11-06 19:05:32 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2006-11-06 19:05:32 +0000 |
commit | 8c92fcb53796e5848fe78d46340dabf9e8f9dddd (patch) | |
tree | 62108eb51d5bf81113501f499dcb002f835a7e4f /sys/arch | |
parent | dd7fd97f3aa3699738db029e84db57619bbfe745 (diff) |
Root device machinery. Boot device is still not known yet.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/landisk/landisk/autoconf.c | 412 |
1 files changed, 285 insertions, 127 deletions
diff --git a/sys/arch/landisk/landisk/autoconf.c b/sys/arch/landisk/landisk/autoconf.c index 09eaa6d5ef2..d9dac0ac8bf 100644 --- a/sys/arch/landisk/landisk/autoconf.c +++ b/sys/arch/landisk/landisk/autoconf.c @@ -1,3 +1,4 @@ +/* $OpenBSD: autoconf.c,v 1.3 2006/11/06 19:05:31 miod Exp $ */ /* $NetBSD: autoconf.c,v 1.1 2006/09/01 21:26:18 uwe Exp $ */ /*- @@ -38,23 +39,26 @@ #include <sys/device.h> #include <sys/disklabel.h> #include <sys/conf.h> -#include <sys/malloc.h> -#include <sys/vnode.h> -#include <sys/fcntl.h> -#include <sys/disk.h> -#include <sys/dkio.h> -#include <sys/proc.h> - -#include <machine/bootinfo.h> +#include <sys/reboot.h> + +#include <dev/cons.h> + #include <machine/intr.h> int cold = 1; + struct device *booted_device; -int booted_partition; +struct device *root_device; -void findroot(void); -int is_valid_disk(struct device *dv); -int match_bootdisk(struct device *dv, struct btinfo_bootdisk *bid); +void diskconf(void); +#ifdef notyet +void dumpconf(void); +#endif +struct device *parsedisk(char *, int, int, dev_t *); +void setroot(void); +int findblkmajor(struct device *); +char *findblkname(int); +struct device *getdisk(char *, int, int, dev_t *); void cpu_configure(void) @@ -67,157 +71,311 @@ cpu_configure(void) if (config_rootfound("mainbus", NULL) == NULL) panic("no mainbus found"); + md_diskconf = diskconf; + /* Configuration is finished, turn on interrupts. */ spl0(); cold = 0; } -int -is_valid_disk(struct device *dv) +void +diskconf(void) { - const char *name; + printf("boot device: %s\n", + booted_device ? booted_device->dv_xname : "<unknown>"); + setroot(); +#ifdef notyet + dumpconf(); +#endif +} - if (dv->dv_class != DV_DISK) - return (0); - - name = dv->dv_cfdata->cf_driver->cd_name; +static struct nam2blk { + char *name; + int maj; +} nam2blk[] = { + { "wd", 16 }, + { "rd", 18 }, + { "sd", 24 } +}; - return (strcmp(name, "sd") == 0 || strcmp(name, "wd") == 0); +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)) == + 0) + return (nam2blk[i].maj); + return (-1); } -/* - * Helper function for findroot(): - * Return non-zero if disk device matches bootinfo. - */ -int -match_bootdisk(struct device *dv, struct btinfo_bootdisk *bid) +char * +findblkname(int maj) { - struct vnode *tmpvn; - int error; - struct disklabel label; - int found = 0; - int bmajor; + int i; - /* - * A disklabel is required here. The boot loader doesn't refuse - * to boot from a disk without a label, but this is normally not - * wanted. - */ - if (bid->labelsector == -1) - return (0); + for (i = 0; i < sizeof(nam2blk)/sizeof(nam2blk[0]); i++) + if (nam2blk[i].maj == maj) + return (nam2blk[i].name); + return (NULL); +} -#if 0 - /* - * Lookup major number for disk block device. - */ - bmajor = devsw_name2blk(dv->dv_xname, NULL, 0); - if (bmajor == -1) - return (0); /* XXX panic ??? */ -#endif +struct device * +getdisk(char *str, int len, int defpart, dev_t *devp) +{ + struct device *dv; - /* - * Fake a temporary vnode for the disk, open it, and read - * the disklabel for comparison. - */ - if (bdevvp(MAKEDISKDEV(bmajor, dv->dv_unit, RAW_PART), &tmpvn)) - panic("match_bootdisk: can't alloc vnode"); - error = VOP_OPEN(tmpvn, FREAD, NOCRED, 0); - if (error) { -#ifndef DEBUG - /* - * Ignore errors caused by missing device, partition, - * or medium. - */ - if (error != ENXIO && error != ENODEV) + if ((dv = parsedisk(str, len, defpart, devp)) == NULL) { + printf("use one of:"); + 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("match_bootdisk: can't open dev %s (%d)\n", - dv->dv_xname, error); - vput(tmpvn); - return (0); - } - error = VOP_IOCTL(tmpvn, DIOCGDINFO, &label, FREAD, NOCRED, 0); - if (error) { - /* - * XXX Can't happen -- open() would have errored out - * or faked one up. - */ - printf("match_bootdisk: can't get label for dev %s (%d)\n", - dv->dv_xname, error); - goto closeout; + } + printf(" halt\n"); } + return (dv); +} + +struct device * +parsedisk(char *str, int len, int defpart, dev_t *devp) +{ + struct device *dv; + char *cp, c; + int majdev, part; + + if (len == 0) + return (NULL); + + if (len == 4 && strcmp(str, "halt") == 0) + boot(RB_HALT); - /* Compare with our data. */ - if (label.d_type == bid->label.type && - label.d_checksum == bid->label.checksum && - strncmp(label.d_packname, bid->label.packname, 16) == 0) - found = 1; + cp = str + len - 1; + c = *cp; + if (c >= 'a' && (c - 'a') < MAXPARTITIONS) { + part = c - 'a'; + *cp = '\0'; + } else + part = defpart; + + TAILQ_FOREACH(dv, &alldevs, dv_list) { + if (dv->dv_class == DV_DISK && + strcmp(str, dv->dv_xname) == 0) { + majdev = findblkmajor(dv); + if (majdev < 0) { + printf("%s is not a valid boot device\n", str); + dv = NULL; + break; + } + *devp = MAKEDISKDEV(majdev, dv->dv_unit, part); + break; + } +#ifdef NFSCLIENT + if (dv->dv_class == DV_IFNET && + strcmp(str, dv->dv_xname) == 0) { + *devp = NODEV; + break; + } +#endif + } -closeout: - VOP_CLOSE(tmpvn, FREAD, NOCRED, 0); - vput(tmpvn); - return (found); + *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. + * 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. */ void -findroot(void) +setroot() { - struct btinfo_bootdisk *bid; + int majdev, mindev, unit, part, len; + dev_t temp; + struct swdevt *swp; struct device *dv; + dev_t nrootdev, nswapdev = NODEV; + char buf[128]; + int s; - if (booted_device) - return; +#if defined(NFSCLIENT) + extern char *nfsbootdevname; +#endif + + if (boothowto & RB_DFLTROOT) + return; /* Boot compiled in */ + + if (booted_device == NULL) { + boothowto |= RB_ASKNAME; /* Don't Panic :-) */ + /* boothowto |= RB_SINGLE; */ + } + + if (boothowto & RB_ASKNAME) { + for (;;) { + printf("root device"); + if (booted_device != NULL) { + printf(" (default %s", + booted_device->dv_xname); + if (booted_device->dv_class == DV_DISK) + printf("a"); + printf(")"); + } + printf(": "); + s = splhigh(); + cnpollc(1); + len = getsn(buf, sizeof(buf)); + cnpollc(0); + splx(s); + if (len == 0 && booted_device != NULL) { + strlcpy(buf, booted_device->dv_xname, + sizeof buf); + len = strlen(buf); + } + if (len > 0 && buf[len - 1] == '*') { + buf[--len] = '\0'; + dv = getdisk(buf, len, 1, &nrootdev); + if (dv != NULL) { + booted_device = dv; + nswapdev = nrootdev; + goto gotswap; + } + } + dv = getdisk(buf, len, 0, &nrootdev); + if (dv != NULL) { + booted_device = dv; + break; + } + } - if ((bid = lookup_bootinfo(BTINFO_BOOTDISK)) != NULL) { /* - * Scan all disk devices for ones that match the passed data. - * Don't break if one is found, to get possible multiple - * matches - for problem tracking. Use the first match anyway - * because lower device numbers are more likely to be the - * boot device. + * because swap must be on same device as root, for + * network devices this is easy. */ - for (dv = TAILQ_FIRST(&alldevs); dv != NULL; - dv = TAILQ_NEXT(dv, dv_list)) { - if (dv->dv_class != DV_DISK) - continue; - - if (is_valid_disk(dv)) { - if (match_bootdisk(dv, bid) == 0) - continue; - goto bootdisk_found; + if (booted_device->dv_class == DV_IFNET) + goto gotswap; + + for (;;) { + printf("swap device"); + if (booted_device != NULL) { + printf(" (default %s", + booted_device->dv_xname); + if (booted_device->dv_class == DV_DISK) + printf("b"); + printf(")"); } - continue; - -bootdisk_found: - if (booted_device) { - printf("WARNING: double match for boot " - "device (%s, %s)\n", - booted_device->dv_xname, dv->dv_xname); - continue; + printf(": "); + s = splhigh(); + cnpollc(1); + len = getsn(buf, sizeof(buf)); + cnpollc(0); + splx(s); + if (len == 0 && booted_device != NULL) { + switch (booted_device->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; } - booted_device = dv; - booted_partition = bid->partition; } - if (booted_device) - return; +gotswap: + rootdev = nrootdev; + dumpdev = nswapdev; + swdevt[0].sw_dev = nswapdev; + swdevt[1].sw_dev = NODEV; + } + else if(mountroot == NULL) { + /* + * `swap generic' + */ + majdev = findblkmajor(booted_device); + if (majdev >= 0) { + /* + * Root and Swap are on disk. + * Boot is always from partition 0. + */ + rootdev = MAKEDISKDEV(majdev, booted_device->dv_unit, 0); + nswapdev = dumpdev = + MAKEDISKDEV(majdev, booted_device->dv_unit, 1); + } else { + /* + * Root and Swap are on 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. + */ + return; } -} -#if 0 -void -cpu_rootconf(void) -{ + switch (booted_device->dv_class) { +#if defined(NFSCLIENT) + case DV_IFNET: + mountroot = nfs_mountroot; + nfsbootdevname = booted_device->dv_xname; + return; +#endif + case DV_DISK: + mountroot = dk_mountroot; + majdev = major(rootdev); + mindev = minor(rootdev); + unit = DISKUNIT(rootdev); + part = DISKPART(rootdev); + printf("root on %s%c\n", booted_device->dv_xname, part + 'a'); + break; + default: + printf("can't figure root, hope your kernel is right\n"); + return; + } - findroot(); + /* + * 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) + return; - printf("boot device: %s\n", - booted_device ? booted_device->dv_xname : "<unknown>"); - /* setroot(booted_device, booted_partition); */ + /* + * 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 |