Index: sys/kern/kern_subr.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_subr.c,v
retrieving revision 1.222
diff -p -u -r1.222 kern_subr.c
--- sys/kern/kern_subr.c        5 Jan 2019 18:03:41 -0000       1.222
+++ sys/kern/kern_subr.c        16 Jan 2019 21:03:03 -0000
@@ -107,8 +107,8 @@ __KERNEL_RCSID(0, "$NetBSD: kern_subr.c,

/* XXX these should eventually move to subr_autoconf.c */
static device_t finddevice(const char *);
-static device_t getdisk(char *, int, int, dev_t *, int);
-static device_t parsedisk(char *, int, int, dev_t *);
+static device_t getdisk(const char *, int, int, dev_t *, int);
+static device_t parsedisk(const char *, int, int, dev_t *);
static const char *getwedgename(const char *, int);

static void setroot_nfs(device_t);
@@ -185,10 +185,13 @@ setroot(device_t bootdv, int bootpartiti
{

       /*
-        * Let bootcode augment "rootspec".
+        * Let bootcode augment "rootspec", ensure that
+        * rootdev is invalid to avoid confusion.
        */
-       if (rootspec == NULL)
+       if (rootspec == NULL) {
               rootspec = bootspec;
+               rootdev = NODEV;
+       }

       /*
        * force boot device to md0
@@ -448,9 +451,9 @@ setroot_ask(device_t bootdv, int bootpar

/*
 * configure
- *   dev_t rootdev
+ *   device_t root_device
+ *   dev_t rootdev (for disks)
 *
- * return device_t or NULL if not found
 */
static void
setroot_root(device_t bootdv, int bootpartition)
@@ -459,6 +462,7 @@ setroot_root(device_t bootdv, int bootpa
       int majdev;
       const char *rootdevname;
       char buf[128];
+       dev_t nrootdev;

       if (rootspec == NULL) {

@@ -490,20 +494,17 @@ setroot_root(device_t bootdv, int bootpa
                */

               /*
-                * If it's a network interface, we can bail out
-                * early.
+                * If rootspec can be parsed, just use it.
                */
-               rootdv = finddevice(rootspec);
-               if (rootdv != NULL && device_class(rootdv) == DV_IFNET)
-                       goto haveroot;
-
-               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));
+               rootdv = parsedisk(rootspec, strlen(rootspec), 0, &nrootdev);
+               if (rootdv != NULL) {
+                       rootdev = nrootdev;
                       goto haveroot;
               }

+               /*
+                * Fall back to rootdev, compute rootdv for it
+                */
               rootdevname = devsw_blk2name(major(rootdev));
               if (rootdevname == NULL) {
                       printf("unknown device major 0x%llx\n",
@@ -647,11 +648,22 @@ finddevice(const char *name)
}

static device_t
-getdisk(char *str, int len, int defpart, dev_t *devp, int isdump)
+getdisk(const char *str, int len, int defpart, dev_t *devp, int isdump)
{
       device_t dv;
       deviter_t di;

+       if (len == 4 && strcmp(str, "halt") == 0)
+               cpu_reboot(RB_HALT, NULL);
+       else if (len == 6 && strcmp(str, "reboot") == 0)
+               cpu_reboot(0, NULL);
+#if defined(DDB)
+       else if (len == 3 && strcmp(str, "ddb") == 0) {
+               console_debugger();
+               return NULL;
+       }
+#endif
+
       if ((dv = parsedisk(str, len, defpart, devp)) == NULL) {
               printf("use one of:");
               for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL;
@@ -689,35 +701,33 @@ getwedgename(const char *name, int namel
}

static device_t
-parsedisk(char *str, int len, int defpart, dev_t *devp)
+parsedisk(const char *str, int len, int defpart, dev_t *devp)
{
       device_t dv;
       const char *wname;
-       char *cp, c;
+       char c;
       int majdev, part;
+       char xname[16]; /* same size as dv_xname */
+
       if (len == 0)
               return (NULL);

-       if (len == 4 && strcmp(str, "halt") == 0)
-               cpu_reboot(RB_HALT, NULL);
-       else if (len == 6 && strcmp(str, "reboot") == 0)
-               cpu_reboot(0, NULL);
-#if defined(DDB)
-       else if (len == 3 && strcmp(str, "ddb") == 0)
-               console_debugger();
-#endif
-
-       cp = str + len - 1;
-       c = *cp;
-
       if ((wname = getwedgename(str, len)) != NULL) {
               if ((dv = dkwedge_find_by_wname(wname)) == NULL)
                       return NULL;
               part = defpart;
               goto gotdisk;
-       } else if (c >= 'a' && c <= ('a' + MAXPARTITIONS - 1)) {
+       }
+
+       c = str[len-1];
+       if (c >= 'a' && c <= ('a' + MAXPARTITIONS - 1)) {
               part = c - 'a';
-               *cp = '\0';
+               len--;
+               if (len > sizeof(xname)-1)
+                       return NULL;
+               memcpy(xname, str, len);
+               xname[len] = '\0';
+               str = xname;
       } else
               part = defpart;

@@ -739,6 +749,5 @@ parsedisk(char *str, int len, int defpar
                       *devp = NODEV;
       }

-       *cp = c;
       return (dv);
}