summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2006-11-06 19:05:32 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2006-11-06 19:05:32 +0000
commit8c92fcb53796e5848fe78d46340dabf9e8f9dddd (patch)
tree62108eb51d5bf81113501f499dcb002f835a7e4f /sys/arch
parentdd7fd97f3aa3699738db029e84db57619bbfe745 (diff)
Root device machinery. Boot device is still not known yet.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/landisk/landisk/autoconf.c412
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