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. *