Index: sys/dev/dkwedge/dk.c =================================================================== RCS file: /cvsroot/src/sys/dev/dkwedge/dk.c,v retrieving revision 1.173 diff -d -p -u -r1.173 dk.c --- sys/dev/dkwedge/dk.c 13 Apr 2025 14:01:00 -0000 1.173 +++ sys/dev/dkwedge/dk.c 1 May 2026 09:27:56 -0000 @@ -150,6 +150,10 @@ static int dkwedge_del1(struct dkwedge_i static int dk_open_parent(dev_t, int, struct vnode **); static int dk_close_parent(struct vnode *, int); +static device_t dkwedge_rootspec_hook(const char *); +static void dkwedge_rootspec_print(void); +static void dkwedge_norootspec_print(void); + static dev_type_open(dkopen); static dev_type_close(dkclose); static dev_type_cancel(dkcancel); @@ -999,8 +1003,17 @@ dkwedge_find_by_parent(const char *name, return dv; } -void -dkwedge_print_wnames(void) +static device_t +dkwedge_rootspec_hook(const char *spec) +{ + device_t dv; + + dv = dkwedge_find_by_wname(spec); + return dv; +} + +static void +dkwedge_rootspec_print(void) { struct dkwedge_softc *sc; int i; @@ -1015,6 +1028,17 @@ dkwedge_print_wnames(void) } /* + * Only list the device names for the wedge:xxx root spec hook. + * For the NAME= root spec hook don't print anything otherwise + * we just get the same wedge device list twice. + */ +static void +dkwedge_norootspec_print(void) +{ + /* nothing */ +} + +/* * We need a dummy object to stuff into the dkwedge discovery method link * set to ensure that there is always at least one object in the set. */ @@ -1078,6 +1102,12 @@ dkwedge_init(void) } rw_exit(&dkwedge_discovery_methods_lock); + + /* never unloaded, so don't need to save the hook establish cookies */ + mountroot_rootspec_hook_establish("wedge", + dkwedge_rootspec_hook, dkwedge_rootspec_print); + mountroot_rootspec_hook_establish("NAME", + dkwedge_rootspec_hook, dkwedge_norootspec_print); } #ifdef DKWEDGE_AUTODISCOVER Index: sys/kern/kern_hook.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_hook.c,v retrieving revision 1.16 diff -d -p -u -r1.16 kern_hook.c --- sys/kern/kern_hook.c 4 Jan 2026 01:34:37 -0000 1.16 +++ sys/kern/kern_hook.c 1 May 2026 09:27:57 -0000 @@ -255,6 +255,93 @@ domountroothook(device_t therootdev) } } +/* + * "Mountroot rootspec hook" types, functions, and variables. + */ + +static LIST_HEAD(rootspec_hook_list, rootspec_hook_desc) rootspec_hook_list = + LIST_HEAD_INITIALIZER(rootspec_hook_list); +struct rootspec_hook_desc { + LIST_ENTRY(rootspec_hook_desc) hk_list; + device_t (*hk_hook_func)(const char *); + void (*hk_print_func)(void); + const char *hk_prefix; + size_t hk_prefixlen; +}; + +struct rootspec_hook_desc * +mountroot_rootspec_hook_establish(const char *prefix, + device_t (*hookfn)(const char *), void (*printfn)(void)) +{ + struct rootspec_hook_desc *hd; + +#ifdef DIAGNOSTIC + LIST_FOREACH(hd, &rootspec_hook_list, hk_list) { + if (strcmp(hd->hk_prefix, prefix) == 0) { + panic("%s: hook for '%s' already exists", + __func__, prefix); + } + } +#endif + + hd = kmem_zalloc(sizeof(*hd), KM_SLEEP); + hd->hk_hook_func = hookfn; + hd->hk_print_func = printfn; + hd->hk_prefix = prefix; + hd->hk_prefixlen = strlen(prefix); + LIST_INSERT_HEAD(&rootspec_hook_list, hd, hk_list); + + return hd; +} + +void +mountroot_rootspec_hook_disestablish(struct rootspec_hook_desc *hd) +{ +#ifdef DIAGNOSTIC + struct rootspec_hook_desc *hd0; + + LIST_FOREACH(hd0, &rootspec_hook_list, hk_list) { + if (hd == hd0) + break; + } + + if (hd0 == NULL) + panic("%s: hook %p not established", __func__, hd); +#endif + + LIST_REMOVE(hd, hk_list); + kmem_free(hd, sizeof(*hd)); +} + +device_t +domountroot_rootspec_hooks(const char *spec) +{ + struct rootspec_hook_desc *hd; + device_t ret; + + LIST_FOREACH(hd, &rootspec_hook_list, hk_list) { + if ((strlen(spec) > hd->hk_prefixlen + 1) && + (spec[hd->hk_prefixlen] == ':' || spec[hd->hk_prefixlen] == '=') && + (strncmp(hd->hk_prefix, spec, hd->hk_prefixlen) == 0)) { + ret = (*hd->hk_hook_func)(spec + hd->hk_prefixlen + 1); + if (ret != NULL) + return ret; + } + } + + return NULL; +} + +void +domountroot_rootspec_print(void) +{ + struct rootspec_hook_desc *hd; + + LIST_FOREACH(hd, &rootspec_hook_list, hk_list) + (*hd->hk_print_func)(); +} + + static hook_list_t exechook_list = LIST_HEAD_INITIALIZER(exechook_list); void * Index: sys/kern/kern_subr.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_subr.c,v retrieving revision 1.231 diff -d -p -u -r1.231 kern_subr.c --- sys/kern/kern_subr.c 19 Jan 2023 07:40:58 -0000 1.231 +++ sys/kern/kern_subr.c 1 May 2026 09:27:57 -0000 @@ -109,7 +109,6 @@ __KERNEL_RCSID(0, "$NetBSD: kern_subr.c, static device_t finddevice(const char *); 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); static void setroot_md(device_t *); @@ -666,10 +655,10 @@ setroot_dump(device_t rootdv, device_t d static device_t finddevice(const char *name) { - const char *wname; + device_t dv; - if ((wname = getwedgename(name, strlen(name))) != NULL) - return dkwedge_find_by_wname(wname); + if ((dv = domountroot_rootspec_hooks(name)) != NULL) + return dv; return device_find_by_xname(name); } @@ -704,7 +693,7 @@ getdisk(const char *str, int len, int de printf(" %s", device_xname(dv)); } deviter_release(&di); - dkwedge_print_wnames(); + domountroot_rootspec_print(); if (isdump) printf(" none"); #if defined(DDB) @@ -715,28 +704,10 @@ getdisk(const char *str, int len, int de return dv; } -static const char * -getwedgename(const char *name, int namelen) -{ - const char *wpfx1 = "wedge:"; - const char *wpfx2 = "NAME="; - const int wpfx1len = strlen(wpfx1); - const int wpfx2len = strlen(wpfx2); - - if (namelen > wpfx1len && strncmp(name, wpfx1, wpfx1len) == 0) - return name + wpfx1len; - - if (namelen > wpfx2len && strncasecmp(name, wpfx2, wpfx2len) == 0) - return name + wpfx2len; - - return NULL; -} - static device_t parsedisk(const char *str, int len, int defpart, dev_t *devp) { device_t dv; - const char *wname; char c; int majdev, part; char xname[16]; /* same size as dv_xname */ @@ -744,9 +715,7 @@ parsedisk(const char *str, int len, int if (len == 0) return (NULL); - if ((wname = getwedgename(str, len)) != NULL) { - if ((dv = dkwedge_find_by_wname(wname)) == NULL) - return NULL; + if ((dv = domountroot_rootspec_hooks(str)) != NULL) { part = defpart; goto gotdisk; } Index: sys/sys/systm.h =================================================================== RCS file: /cvsroot/src/sys/sys/systm.h,v retrieving revision 1.306 diff -d -p -u -r1.306 systm.h --- sys/sys/systm.h 12 May 2024 10:34:56 -0000 1.306 +++ sys/sys/systm.h 1 May 2026 09:27:57 -0000 @@ -63,12 +63,13 @@ struct clockframe; struct lwp; struct proc; +struct rootspec_hook_desc; struct sysent; struct timeval; struct tty; struct uio; -struct vnode; struct vmspace; +struct vnode; extern const char *panicstr; /* panic message */ extern int doing_shutdown; /* shutting down */ @@ -587,6 +588,15 @@ void mountroothook_disestablish(void *); void mountroothook_destroy(void); void domountroothook(device_t); +/* Regiser rootspec/bootdevice prefixs for per-driver handling. */ +struct rootspec_hook_desc * + mountroot_rootspec_hook_establish(const char *, + device_t (*)(const char *), + void (*)(void)); +void mountroot_rootspec_hook_disestablish(struct rootspec_hook_desc *); +device_t domountroot_rootspec_hooks(const char *); +void domountroot_rootspec_print(void); + /* * Exec hooks. Subsystems may want to do cleanup when a process * execs.