From d76330efd9f970c3d0e5b848f6ba330b1bd1ee3d Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 3 Feb 2023 08:37:31 -0700 Subject: [PATCH] kboot: Probe all disks and partitions for a kernel Guess where to boot from when bootdev= isn't on the command line or other config. Search all the disks and partitions for one that looks like it could be a boot partition (same as we do when probing zpools). Return the first one we find. Sponsored by: Netflix Reviewed by: tsoome Differential Revision: https://reviews.freebsd.org/D38319 --- stand/kboot/hostdisk.c | 69 +++++++++++++++++++++++++++++++++--------- stand/kboot/kboot.h | 1 + stand/kboot/main.c | 2 ++ 3 files changed, 58 insertions(+), 14 deletions(-) diff --git a/stand/kboot/hostdisk.c b/stand/kboot/hostdisk.c index 3c924293223a..b71ae256b0f6 100644 --- a/stand/kboot/hostdisk.c +++ b/stand/kboot/hostdisk.c @@ -488,6 +488,61 @@ hostdisk_parsedev(struct devdesc **idev, const char *devspec, const char **path) return (0); } +/* XXX refactor */ +static bool +sanity_check_currdev(void) +{ + struct stat st; + + return (stat(PATH_DEFAULTS_LOADER_CONF, &st) == 0 || +#ifdef PATH_BOOTABLE_TOKEN + stat(PATH_BOOTABLE_TOKEN, &st) == 0 || /* non-standard layout */ +#endif + stat(PATH_KERNEL, &st) == 0); +} + +static const char * +hostdisk_try_one(hdinfo_t *hd) +{ + char *fn; + + if (asprintf(&fn, "%s:", hd->hd_dev) == -1) + return (NULL); + set_currdev(fn); + printf("Trying %s\n", fn); + if (sanity_check_currdev()) + return (fn); + printf("Failed %s\n", fn); + free(fn); + return (NULL); +} + +const char * +hostdisk_gen_probe(void) +{ + hdinfo_t *hd, *md; + const char *rv = NULL; + + STAILQ_FOREACH(hd, &hdinfo, hd_link) { + /* try whole disk */ + if (hd->hd_flags & HDF_HAS_ZPOOL) + continue; + rv = hostdisk_try_one(hd); + if (rv != NULL) + return (rv); + + /* try all partitions */ + STAILQ_FOREACH(md, &hd->hd_children, hd_link) { + if (md->hd_flags & HDF_HAS_ZPOOL) + continue; + rv = hostdisk_try_one(md); + if (rv != NULL) + return (rv); + } + } + return (false); +} + #ifdef LOADER_ZFS_SUPPORT static bool hostdisk_zfs_check_one(hdinfo_t *hd) @@ -524,19 +579,6 @@ hostdisk_zfs_probe(void) } } -/* XXX refactor */ -static bool -sanity_check_currdev(void) -{ - struct stat st; - - return (stat(PATH_DEFAULTS_LOADER_CONF, &st) == 0 || -#ifdef PATH_BOOTABLE_TOKEN - stat(PATH_BOOTABLE_TOKEN, &st) == 0 || /* non-standard layout */ -#endif - stat(PATH_KERNEL, &st) == 0); -} - /* This likely shoud move to libsa/zfs/zfs.c and be used by at least EFI booting */ static bool probe_zfs_currdev(uint64_t pool_guid, uint64_t root_guid, bool setcurrdev) @@ -599,5 +641,4 @@ hostdisk_zfs_find_default(void) } return (false); } - #endif diff --git a/stand/kboot/kboot.h b/stand/kboot/kboot.h index 58cbedff67a1..d7e406f86d7a 100644 --- a/stand/kboot/kboot.h +++ b/stand/kboot/kboot.h @@ -22,6 +22,7 @@ uint8_t kboot_get_kernel_machine_bits(void); /* hostdisk.c */ extern const char *hostfs_root; +const char *hostdisk_gen_probe(void); void hostdisk_zfs_probe(void); bool hostdisk_zfs_find_default(void); diff --git a/stand/kboot/main.c b/stand/kboot/main.c index e8320503647f..b8523cb202a2 100644 --- a/stand/kboot/main.c +++ b/stand/kboot/main.c @@ -221,6 +221,8 @@ main(int argc, const char **argv) devinit(); bootdev = getenv("bootdev"); + if (bootdev == NULL) + bootdev = hostdisk_gen_probe(); if (bootdev == NULL) bootdev="zfs:"; hostfs_root = getenv("hostfs_root");