-/* $OpenBSD: autoconf.c,v 1.2 1996/08/26 11:01:33 pefo Exp $ */
+/* $OpenBSD: autoconf.c,v 1.3 1996/09/02 11:33:22 pefo Exp $ */
/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * Copyright (c) 1995 Theo de Raadt
* Copyright (c) 1988 University of Utah.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
* from: Utah Hdr: autoconf.c 1.31 91/01/21
*
* from: @(#)autoconf.c 8.1 (Berkeley) 6/10/93
- * $Id: autoconf.c,v 1.2 1996/08/26 11:01:33 pefo Exp $
+ * $Id: autoconf.c,v 1.3 1996/09/02 11:33:22 pefo Exp $
*/
/*
#include <machine/autoconf.h>
+struct device *parsedisk __P((char *, int, int, dev_t *));
+void setroot __P((void));
+
/*
* The following several variables are related to
* the configuration process, and are used in initializing
*/
int cold = 1; /* if 1, still working on cold-start */
int cpuspeed = 150; /* approx # instr per usec. */
+char bootdev[16]; /* to hold boot dev name */
+struct device *bootdv = NULL;
/*
* Configure all devices found that we know about.
panic("no mainbus found");
(void)spl0();
-#ifdef GENERIC
- if ((boothowto & RB_ASKNAME) == 0)
- setroot();
- setconf();
-#else
setroot();
-#endif
swapconf();
cold = 0;
}
dumpconf();
}
-#define DOSWAP /* Change swdevt and dumpdev too */
-u_long bootdev; /* should be dev_t, but not until 32 bits */
-
-static char devname[][2] = {
- 's','d', /* 0 = sd */
- 'x','x', /* 1 = unused */
- 'x','x', /* 2 = unused */
- 'x','x', /* 3 = unused */
- 'x','x', /* 4 = unused */
- 'x','x', /* 5 = unused */
- 'x','x', /* 6 = unused */
- 'f','d', /* 7 = floppy */
+/*
+ * the rest of this file was influenced/copied from Theo de Raadt's
+ * code in the sparc port to nuke the "options GENERIC" stuff.
+ */
+
+static struct nam2blk {
+ char *name;
+ int maj;
+} nam2blk[] = {
+ { "sd", 0 }, /* 0 = sd */
+ { "fd", 7 }, /* 7 = floppy (ick!)*/
};
+static int
+findblkmajor(dv)
+ struct device *dv;
+{
+ char *name = dv->dv_xname;
+ register int i;
+
+ for (i = 0; i < sizeof(nam2blk)/sizeof(nam2blk[0]); ++i)
+ if (strncmp(name, nam2blk[i].name, strlen(nam2blk[0].name)) == 0)
+ return (nam2blk[i].maj);
+ 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.tqh_first; dv != NULL;
+ dv = dv->dv_list.tqe_next) {
+ if (dv->dv_class == DV_DISK)
+ printf(" %s[a-h]", 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, 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.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) {
+ if (dv->dv_class == DV_DISK &&
+ strcmp(str, dv->dv_xname) == 0) {
+ majdev = findblkmajor(dv);
+ if (majdev < 0)
+ panic("parsedisk");
+ mindev = (dv->dv_unit << PARTITIONSHIFT) + part;
+ *devp = makedev(majdev, mindev);
+ 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.
*/
+void
setroot()
{
- int majdev, mindev, unit, part, controller;
- dev_t temp, orootdev;
+ int majdev, mindev, unit, part, len;
+ dev_t temp;
struct swdevt *swp;
+ struct device *dv;
+ dev_t nrootdev, nswapdev = NODEV;
+ char buf[128];
+ extern int (*mountroot) __P((void *));
+
+#if defined(NFSCLIENT)
+ extern char *nfsbootdevname;
+ extern int nfs_mountroot __P((void *));
+#endif
+#if defined(FFS)
+ extern int ffs_mountroot __P((void *));
+#endif
- if (boothowto & RB_DFLTROOT ||
- (bootdev & B_MAGICMASK) != B_DEVMAGIC)
+ /* Lookup boot device from boot if not set by configuration */
+ if(bootdv == NULL) {
+ bootdv = parsedisk(bootdev, strlen(bootdev), 0, &temp);
+ }
+ if(bootdv == NULL) {
+ printf("boot device: lookup '%s' failed.\n", bootdev);
+ boothowto |= RB_ASKNAME; /* Don't Panic :-) */
+ }
+ else {
+ printf("boot device: %s.\n", bootdv->dv_xname);
+ }
+
+ if (boothowto & RB_ASKNAME) {
+ for (;;) {
+ printf("root device ");
+ if (bootdv != NULL)
+ printf("(default %s%c)",
+ bootdv->dv_xname,
+ bootdv->dv_class == DV_DISK
+ ? 'a' : ' ');
+ printf(": ");
+ len = getsn(buf, sizeof(buf));
+ if (len == 0 && bootdv != NULL) {
+ strcpy(buf, bootdv->dv_xname);
+ len = strlen(buf);
+ }
+ 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, 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 = getsn(buf, sizeof(buf));
+ if (len == 0 && bootdv != NULL) {
+ switch (bootdv->dv_class) {
+ case DV_IFNET:
+ nswapdev = NODEV;
+ break;
+ case DV_DISK:
+ nswapdev = makedev(major(nrootdev),
+ (minor(nrootdev) & ~ PARTITIONMASK)
+| 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.
+ */
+ if (bootdv == NULL)
+ panic("boot device not known");
+
+ majdev = findblkmajor(bootdv);
+
+ if (majdev >= 0) {
+ /*
+ * Root and Swap are on disk.
+ * Boot is always from partition 0.
+ */
+ rootdev = MAKEDISKDEV(majdev, bootdv->dv_unit, 0);
+ nswapdev = MAKEDISKDEV(majdev, bootdv->dv_unit, 1);
+ dumpdev = nswapdev;
+ }
+ 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;
+ }
+
+ switch (bootdv->dv_class) {
+#if defined(NFSCLIENT)
+ case DV_IFNET:
+ mountroot = nfs_mountroot;
+ nfsbootdevname = bootdv->dv_xname;
return;
- majdev = B_TYPE(bootdev);
- if (majdev >= sizeof(devname) / sizeof(devname[0]))
+#endif
+#if defined(FFS)
+ case DV_DISK:
+ mountroot = ffs_mountroot;
+ majdev = major(rootdev);
+ mindev = minor(rootdev);
+ printf("root on %s%c\n", bootdv->dv_xname,
+ (mindev & PARTITIONMASK) + 'a');
+ break;
+#endif
+ default:
+ printf("can't figure root, hope your kernel is right\n");
return;
- controller = B_CONTROLLER(bootdev);
- part = B_PARTITION(bootdev);
- unit = B_UNIT(bootdev);
+ }
- mindev = (unit << PARTITIONSHIFT) + part;
- orootdev = rootdev;
- rootdev = makedev(majdev, mindev);
/*
- * If the original rootdev is the same as the one
- * just calculated, don't need to adjust the swap configuration.
+ * XXX: What is this doing?
*/
- if (rootdev == orootdev)
- return;
-
- printf("changing root device to %c%c%d%c\n",
- devname[majdev][0], devname[majdev][1],
- unit, part + 'a');
-
-#ifdef DOSWAP
+ mindev &= ~PARTITIONMASK;
+ temp = NODEV;
for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
if (majdev == major(swp->sw_dev) &&
- (mindev / MAXPARTITIONS) == (minor(swp->sw_dev) / MAXPARTITIONS)) {
+ mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
temp = swdevt[0].sw_dev;
swdevt[0].sw_dev = swp->sw_dev;
swp->sw_dev = temp;
return;
/*
- * If dumpdev was the same as the old primary swap
- * device, move it to the new primary swap device.
+ * 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
+}
+
+/*
+ * find a device matching "name" and unit number
+ */
+struct device *
+getdevunit(name, unit)
+ char *name;
+ int unit;
+{
+ struct device *dev = alldevs.tqh_first;
+ char num[10], fullname[16];
+ int lunit;
+
+ /* compute length of name and decimal expansion of unit number */
+ sprintf(num, "%d", unit);
+ lunit = strlen(num);
+ if (strlen(name) + lunit >= sizeof(fullname) - 1)
+ panic("config_attach: device name too long");
+
+ strcpy(fullname, name);
+ strcat(fullname, num);
+
+ while (strcmp(dev->dv_xname, fullname) != 0) {
+ if ((dev = dev->dv_list.tqe_next) == NULL)
+ return NULL;
+ }
+ return dev;
}
/*
* Look at the string 'cp' and decode the boot device.
* Boot names look like: scsi()disk(n)rdisk()partition(1)\bsd
+ * (beware for empty scsi id's...)
*/
void
makebootdev(cp)
char *cp;
{
- int majdev, unit, part, ctrl;
- char dv[8];
+ int unit, part, ctrl;
- bootdev = B_DEVMAGIC;
-
- dv[0] = *cp;
+ bootdev[0] = *cp;
ctrl = getpno(&cp);
if(*cp++ == ')') {
- dv[1] = *cp;
+ bootdev[1] = *cp;
unit = getpno(&cp);
-
- for (majdev = 0; majdev < sizeof(devname)/sizeof(devname[0]); majdev++)
- if (dv[0] == devname[majdev][0] &&
- dv[1] == devname[majdev][1] && cp[0] == ')')
- bootdev = MAKEBOOTDEV(majdev, 0, ctrl, unit,0);
}
+ sprintf(&bootdev[2], "%d", ctrl*16 + unit);
}
getpno(cp)
char **cp;