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
This commit is contained in:
Warner Losh 2023-02-03 08:37:31 -07:00
parent cb96a0ef00
commit d76330efd9
3 changed files with 58 additions and 14 deletions

View file

@ -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

View file

@ -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);

View file

@ -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");