Module Name: src
Committed By: mlelstv
Date: Sat Jan 5 09:39:56 UTC 2019
Modified Files:
src/sys/kern: kern_subr.c
Log Message:
Refactor setroot, no functional change intended.
setroot
- prepare special cases
- loop until root is set
setroot_nfs
- special case for disk boot + NFS root
setroot_ask
- Prompt user
setroot_root
- set root device
setroot_dump
- set dump device
To generate a diff of this commit:
cvs rdiff -u -r1.220 -r1.221 src/sys/kern/kern_subr.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/kern_subr.c
diff -u src/sys/kern/kern_subr.c:1.220 src/sys/kern/kern_subr.c:1.221
--- src/sys/kern/kern_subr.c:1.220 Sun Oct 7 11:24:16 2018
+++ src/sys/kern/kern_subr.c Sat Jan 5 09:39:56 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_subr.c,v 1.220 2018/10/07 11:24:16 mlelstv Exp $ */
+/* $NetBSD: kern_subr.c,v 1.221 2019/01/05 09:39:56 mlelstv Exp $ */
/*-
* Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc.
@@ -79,7 +79,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.220 2018/10/07 11:24:16 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.221 2019/01/05 09:39:56 mlelstv Exp $");
#include "opt_ddb.h"
#include "opt_md.h"
@@ -111,6 +111,12 @@ static device_t getdisk(char *, int, int
static device_t parsedisk(char *, int, int, dev_t *);
static const char *getwedgename(const char *, int);
+static void setroot_nfs(device_t);
+static void setroot_ask(device_t, int);
+static void setroot_root(device_t, int);
+static void setroot_dump(device_t, device_t);
+
+
#ifdef TFTPROOT
int tftproot_dhcpboot(device_t);
#endif
@@ -154,6 +160,8 @@ int md_is_root = 0;
/*
* The device and partition that we booted from.
+ *
+ * This data might be initialized by MD code, but is defined here.
*/
device_t booted_device;
const char *booted_method;
@@ -174,71 +182,92 @@ char *bootspec;
void
setroot(device_t bootdv, int bootpartition)
{
- device_t dv;
- deviter_t di;
- int len, majdev;
- dev_t nrootdev;
- dev_t ndumpdev = NODEV;
- char buf[128];
- const char *rootdevname;
- const char *dumpdevname;
- device_t rootdv = NULL; /* XXX gcc -Wuninitialized */
- device_t dumpdv = NULL;
- struct ifnet *ifp;
- const char *deffsname;
- struct vfsops *vops;
+
+ /*
+ * Let bootcode augment "rootspec".
+ */
+ if (rootspec == NULL)
+ rootspec = bootspec;
+
+ /*
+ * force boot device to md0
+ */
+ if (md_is_root)
+ rootspec = "md0";
#ifdef TFTPROOT
- if (tftproot_dhcpboot(bootdv) != 0)
- boothowto |= RB_ASKNAME;
+ /*
+ * XXX
+ * if rootspec specifies an interface
+ * sets root_device to that interface
+ * reuses NFS init code to set up network
+ * fetch image into ram disk
+ *
+ * if successful, we change rootspec
+ */
+ if (tftproot_dhcpboot(bootdv) == 0)
+ rootspec = "md0";
#endif
-
+
/*
- * For root on md0 we have to force the attachment of md0.
+ * quirk for
+ * evbarm/mini2440
+ * hpcarm
+ * hpcmips
+ * hpcsh
+ *
+ * if rootfstype is set to NFS and the
+ * kernel supports NFS and the boot device
+ * is unknown or not a network interface
+ * -> chose the first network interface you find
+ *
+ * hp300 has similar MD code
*/
- if (md_is_root) {
- int md_major;
- dev_t md_dev;
-
- bootdv = NULL;
- md_major = devsw_name2blk("md", NULL, 0);
- if (md_major >= 0) {
- md_dev = MAKEDISKDEV(md_major, 0, RAW_PART);
- if (bdev_open(md_dev, FREAD, S_IFBLK, curlwp) == 0)
- bootdv = device_find_by_xname("md0");
- }
- if (bootdv == NULL)
- panic("Cannot open \"md0\" (root)");
- }
+ setroot_nfs(bootdv);
/*
- * Let bootcode augment "rootspec".
+ * If no bootdv was found by MD code and no
+ * root specified ask the user.
*/
- if (rootspec == NULL)
- rootspec = bootspec;
+ if (rootspec == NULL && bootdv == NULL)
+ boothowto |= RB_ASKNAME;
/*
- * If NFS is specified as the file system, and we found
- * a DV_DISK boot device (or no boot device at all), then
- * find a reasonable network interface for "rootspec".
+ * loop until a root device is specified
*/
+ do {
+ if (boothowto & RB_ASKNAME)
+ setroot_ask(bootdv, bootpartition);
+ else
+ setroot_root(bootdv, bootpartition);
+
+ if (root_device == NULL)
+ boothowto |= RB_ASKNAME;
+ } while (root_device == NULL);
+}
+
+/*
+ * If NFS is specified as the file system, and we found
+ * a DV_DISK boot device (or no boot device at all), then
+ * find a reasonable network interface for "rootspec".
+ */
+static void
+setroot_nfs(device_t dv)
+{
+ struct vfsops *vops;
+ struct ifnet *ifp;
+
vops = vfs_getopsbyname(MOUNT_NFS);
if (vops != NULL && strcmp(rootfstype, MOUNT_NFS) == 0 &&
rootspec == NULL &&
- (bootdv == NULL || device_class(bootdv) != DV_IFNET)) {
+ (dv == NULL || device_class(dv) != DV_IFNET)) {
int s = pserialize_read_enter();
IFNET_READER_FOREACH(ifp) {
if ((ifp->if_flags &
(IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
break;
}
- if (ifp == NULL) {
- /*
- * Can't find a suitable interface; ask the
- * user.
- */
- boothowto |= RB_ASKNAME;
- } else {
+ if (ifp != NULL) {
/*
* Have a suitable interface; behave as if
* the user specified this interface.
@@ -249,152 +278,170 @@ setroot(device_t bootdv, int bootpartiti
}
if (vops != NULL)
vfs_delref(vops);
+}
- /*
- * If wildcarded root and we the boot device wasn't determined,
- * ask the user.
- */
- if (rootspec == NULL && bootdv == NULL)
- boothowto |= RB_ASKNAME;
+static void
+setroot_ask(device_t bootdv, int bootpartition)
+{
+ device_t dv, defdumpdv, rootdv, dumpdv;
+ dev_t nrootdev, ndumpdev;
+ struct vfsops *vops;
+ const char *deffsname;
+ int len;
+ char buf[128];
- top:
- if (boothowto & RB_ASKNAME) {
- device_t defdumpdv;
-
- for (;;) {
- printf("root device");
- if (bootdv != NULL) {
- printf(" (default %s", device_xname(bootdv));
- if (DEV_USES_PARTITIONS(bootdv))
- printf("%c", bootpartition + 'a');
- printf(")");
- }
- printf(": ");
- len = cngetsn(buf, sizeof(buf));
- if (len == 0 && bootdv != NULL) {
- strlcpy(buf, device_xname(bootdv), sizeof(buf));
- len = strlen(buf);
- }
- if (len > 0 && buf[len - 1] == '*') {
- buf[--len] = '\0';
- dv = getdisk(buf, len, 1, &nrootdev, 0);
- if (dv != NULL) {
- rootdv = dv;
- break;
- }
- }
- dv = getdisk(buf, len, bootpartition, &nrootdev, 0);
+ for (;;) {
+ printf("root device");
+ if (bootdv != NULL) {
+ printf(" (default %s", device_xname(bootdv));
+ if (DEV_USES_PARTITIONS(bootdv))
+ printf("%c", bootpartition + 'a');
+ printf(")");
+ }
+ printf(": ");
+ len = cngetsn(buf, sizeof(buf));
+ if (len == 0 && bootdv != NULL) {
+ strlcpy(buf, device_xname(bootdv), sizeof(buf));
+ len = strlen(buf);
+ }
+ if (len > 0 && buf[len - 1] == '*') {
+ buf[--len] = '\0';
+ dv = getdisk(buf, len, 1, &nrootdev, 0);
if (dv != NULL) {
rootdv = dv;
break;
}
}
+ dv = getdisk(buf, len, bootpartition, &nrootdev, 0);
+ if (dv != NULL) {
+ rootdv = dv;
+ break;
+ }
+ }
+ rootdev = nrootdev;
- /*
- * Set up the default dump device. If root is on
- * a network device, there is no default dump
- * device, since we don't support dumps to the
- * network.
- */
- if (DEV_USES_PARTITIONS(rootdv) == 0)
- defdumpdv = NULL;
- else
- defdumpdv = rootdv;
-
- for (;;) {
- printf("dump device");
+ /*
+ * Set up the default dump device. If root is on
+ * a network device or a disk without partitions,
+ * there is no default dump device.
+ */
+ if (DEV_USES_PARTITIONS(rootdv) == 0)
+ defdumpdv = NULL;
+ else
+ defdumpdv = rootdv;
+
+ ndumpdev = NODEV;
+ for (;;) {
+ printf("dump device");
+ if (defdumpdv != NULL) {
+ /*
+ * Note, we know it's a disk if we get here.
+ */
+ printf(" (default %sb)", device_xname(defdumpdv));
+ }
+ printf(": ");
+ len = cngetsn(buf, sizeof(buf));
+ if (len == 0) {
if (defdumpdv != NULL) {
- /*
- * Note, we know it's a disk if we get here.
- */
- printf(" (default %sb)", device_xname(defdumpdv));
- }
- printf(": ");
- len = cngetsn(buf, sizeof(buf));
- if (len == 0) {
- if (defdumpdv != NULL) {
- ndumpdev = MAKEDISKDEV(major(nrootdev),
- DISKUNIT(nrootdev), 1);
- }
- dumpdv = defdumpdv;
- break;
- }
- if (len == 4 && strcmp(buf, "none") == 0) {
- dumpdv = NULL;
- break;
- }
- dv = getdisk(buf, len, 1, &ndumpdev, 1);
- if (dv != NULL) {
- dumpdv = dv;
- break;
+ ndumpdev = MAKEDISKDEV(major(nrootdev),
+ DISKUNIT(nrootdev), 1);
}
+ dumpdv = defdumpdv;
+ break;
}
+ if (len == 4 && strcmp(buf, "none") == 0) {
+ dumpdv = NULL;
+ break;
+ }
+ dv = getdisk(buf, len, 1, &ndumpdev, 1);
+ if (dv != NULL) {
+ dumpdv = dv;
+ break;
+ }
+ }
+ dumpdev = ndumpdev;
- rootdev = nrootdev;
- dumpdev = ndumpdev;
+ for (vops = LIST_FIRST(&vfs_list); vops != NULL;
+ vops = LIST_NEXT(vops, vfs_list)) {
+ if (vops->vfs_mountroot != NULL &&
+ strcmp(rootfstype, vops->vfs_name) == 0)
+ break;
+ }
+
+ if (vops == NULL) {
+ deffsname = "generic";
+ } else
+ deffsname = vops->vfs_name;
- for (vops = LIST_FIRST(&vfs_list); vops != NULL;
- vops = LIST_NEXT(vops, vfs_list)) {
- if (vops->vfs_mountroot != NULL &&
- strcmp(rootfstype, vops->vfs_name) == 0)
+ for (;;) {
+ printf("file system (default %s): ", deffsname);
+ len = cngetsn(buf, sizeof(buf));
+ if (len == 0) {
+ if (strcmp(deffsname, "generic") == 0)
+ rootfstype = ROOT_FSTYPE_ANY;
break;
}
-
- if (vops == NULL) {
- deffsname = "generic";
- } else
- deffsname = vops->vfs_name;
-
- for (;;) {
- printf("file system (default %s): ", deffsname);
- len = cngetsn(buf, sizeof(buf));
- if (len == 0) {
- if (strcmp(deffsname, "generic") == 0)
- rootfstype = ROOT_FSTYPE_ANY;
- break;
- }
- if (len == 4 && strcmp(buf, "halt") == 0)
- cpu_reboot(RB_HALT, NULL);
- else if (len == 6 && strcmp(buf, "reboot") == 0)
- cpu_reboot(0, NULL);
+ if (len == 4 && strcmp(buf, "halt") == 0)
+ cpu_reboot(RB_HALT, NULL);
+ else if (len == 6 && strcmp(buf, "reboot") == 0)
+ cpu_reboot(0, NULL);
#if defined(DDB)
- else if (len == 3 && strcmp(buf, "ddb") == 0) {
- console_debugger();
- }
+ else if (len == 3 && strcmp(buf, "ddb") == 0) {
+ console_debugger();
+ }
#endif
- else if (len == 7 && strcmp(buf, "generic") == 0) {
- rootfstype = ROOT_FSTYPE_ANY;
- break;
+ else if (len == 7 && strcmp(buf, "generic") == 0) {
+ rootfstype = ROOT_FSTYPE_ANY;
+ break;
+ }
+ vops = vfs_getopsbyname(buf);
+ if (vops == NULL || vops->vfs_mountroot == NULL) {
+ printf("use one of: generic");
+ for (vops = LIST_FIRST(&vfs_list);
+ vops != NULL;
+ vops = LIST_NEXT(vops, vfs_list)) {
+ if (vops->vfs_mountroot != NULL)
+ printf(" %s", vops->vfs_name);
}
- vops = vfs_getopsbyname(buf);
- if (vops == NULL || vops->vfs_mountroot == NULL) {
- printf("use one of: generic");
- for (vops = LIST_FIRST(&vfs_list);
- vops != NULL;
- vops = LIST_NEXT(vops, vfs_list)) {
- if (vops->vfs_mountroot != NULL)
- printf(" %s", vops->vfs_name);
- }
- if (vops != NULL)
- vfs_delref(vops);
+ if (vops != NULL)
+ vfs_delref(vops);
#if defined(DDB)
- printf(" ddb");
+ printf(" ddb");
#endif
- printf(" halt reboot\n");
- } else {
- /*
- * XXX If *vops gets freed between here and
- * the call to mountroot(), rootfstype will
- * point to something unexpected. But in
- * this case the system will fail anyway.
- */
- rootfstype = vops->vfs_name;
- vfs_delref(vops);
- break;
- }
+ printf(" halt reboot\n");
+ } else {
+ /*
+ * XXX If *vops gets freed between here and
+ * the call to mountroot(), rootfstype will
+ * point to something unexpected. But in
+ * this case the system will fail anyway.
+ */
+ rootfstype = vops->vfs_name;
+ vfs_delref(vops);
+ break;
}
+ }
+
+ root_device = rootdv;
+ setroot_dump(root_device, dumpdv);
+}
+
+/*
+ * configure
+ * dev_t rootdev
+ *
+ * return device_t or NULL if not found
+ */
+static void
+setroot_root(device_t bootdv, int bootpartition)
+{
+ device_t rootdv;
+ int majdev;
+ const char *rootdevname;
+ char buf[128];
+
+ if (rootspec == NULL) {
- } else if (rootspec == NULL) {
/*
* Wildcarded root; use the boot device.
*/
@@ -426,17 +473,14 @@ setroot(device_t bootdv, int bootpartiti
* If it's a network interface, we can bail out
* early.
*/
- dv = finddevice(rootspec);
- if (dv != NULL && device_class(dv) == DV_IFNET) {
- rootdv = dv;
+ rootdv = finddevice(rootspec);
+ if (rootdv != NULL && device_class(rootdv) == DV_IFNET)
goto haveroot;
- }
- if (dv != NULL && device_class(dv) == DV_DISK &&
- !DEV_USES_PARTITIONS(dv) &&
- (majdev = devsw_name2blk(device_xname(dv), NULL, 0)) >= 0) {
- rootdv = dv;
- rootdev = makedev(majdev, device_unit(dv));
+ if (rootdv != NULL && device_class(rootdv) == DV_DISK &&
+ !DEV_USES_PARTITIONS(rootdv) &&
+ (majdev = devsw_name2blk(device_xname(rootdv), NULL, 0)) >= 0) {
+ rootdev = makedev(majdev, device_unit(rootdv));
goto haveroot;
}
@@ -444,8 +488,7 @@ setroot(device_t bootdv, int bootpartiti
if (rootdevname == NULL) {
printf("unknown device major 0x%llx\n",
(unsigned long long)rootdev);
- boothowto |= RB_ASKNAME;
- goto top;
+ return;
}
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "%s%llu", rootdevname,
@@ -455,15 +498,11 @@ setroot(device_t bootdv, int bootpartiti
if (rootdv == NULL) {
printf("device %s (0x%llx) not configured\n",
buf, (unsigned long long)rootdev);
- boothowto |= RB_ASKNAME;
- goto top;
+ return;
}
}
- haveroot:
-
- root_device = rootdv;
-
+haveroot:
switch (device_class(rootdv)) {
case DV_IFNET:
case DV_DISK:
@@ -471,13 +510,31 @@ setroot(device_t bootdv, int bootpartiti
if (DEV_USES_PARTITIONS(rootdv))
aprint_normal("%c", (int)DISKPART(rootdev) + 'a');
break;
-
default:
printf("can't determine root device\n");
- boothowto |= RB_ASKNAME;
- goto top;
+ return;
}
+ root_device = rootdv;
+ setroot_dump(rootdv, NULL);
+}
+
+/*
+ * configure
+ * dev_t dumpdev
+ * dev_t dumpcdev
+ *
+ * set to NODEV if device not found
+ */
+static void
+setroot_dump(device_t rootdv, device_t dumpdv)
+{
+ device_t dv;
+ deviter_t di;
+ const char *dumpdevname;
+ int majdev;
+ char buf[128];
+
/*
* Now configure the dump device.
*