diff options
| author | Warner Losh <imp@FreeBSD.org> | 2026-02-27 00:57:39 +0000 |
|---|---|---|
| committer | Warner Losh <imp@FreeBSD.org> | 2026-02-27 01:01:36 +0000 |
| commit | 784150fd25351f4a38f4d983882f4a26cc5d3272 (patch) | |
| tree | c56283ee8b14a13812c203988721a3918c847237 | |
| parent | d69fc3a9dc71768e125e83d35274f0820063e42d (diff) | |
stand/efi: Allow RELAXED or STRICT boot policies
The RELAXED boot policy will automatically search for any root
filesystem (currently zfs only) on any device. STRICT policy only
searches on the boot device. RELEAXED will still prefer the device we
booted from, which is the smallest behavior change we should do. STRICT
may be needed for releases, though.
Sponsored by: Netflix
Reviewed by: glebius
Differential Revision: https://reviews.freebsd.org/D55107
| -rw-r--r-- | stand/efi/libefi/efizfs.c | 10 | ||||
| -rw-r--r-- | stand/efi/loader/main.c | 40 |
2 files changed, 42 insertions, 8 deletions
diff --git a/stand/efi/libefi/efizfs.c b/stand/efi/libefi/efizfs.c index 563cf841143a..8ad410488b9c 100644 --- a/stand/efi/libefi/efizfs.c +++ b/stand/efi/libefi/efizfs.c @@ -76,7 +76,7 @@ efizfs_get_guid_by_handle(EFI_HANDLE handle, uint64_t *guid) } static void -insert_zfs(EFI_HANDLE handle, uint64_t guid) +insert_zfs(EFI_HANDLE handle, uint64_t guid, bool head) { zfsinfo_t *zi; @@ -84,7 +84,10 @@ insert_zfs(EFI_HANDLE handle, uint64_t guid) if (zi != NULL) { zi->zi_handle = handle; zi->zi_pool_guid = guid; - STAILQ_INSERT_TAIL(&zfsinfo, zi, zi_link); + if (head) + STAILQ_INSERT_HEAD(&zfsinfo, zi, zi_link); + else + STAILQ_INSERT_TAIL(&zfsinfo, zi, zi_link); } } @@ -110,7 +113,8 @@ efi_zfs_probe(void) snprintf(devname, sizeof(devname), "%s%dp%d:", efipart_hddev.dv_name, hd->pd_unit, pd->pd_unit); if (zfs_probe_dev(devname, &guid, false) == 0) - insert_zfs(pd->pd_handle, guid); + insert_zfs(pd->pd_handle, guid, + pd->pd_handle == boot_img->DeviceHandle); } } } diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c index d8508d7d91a0..f83db2e0668d 100644 --- a/stand/efi/loader/main.c +++ b/stand/efi/loader/main.c @@ -143,6 +143,16 @@ UINT16 boot_current; */ EFI_LOADED_IMAGE *boot_img; +enum boot_policies { + STRICT, + RELAXED, +} boot_policy = RELAXED; + +const char *policy_map[] = { + [STRICT] = "strict", + [RELAXED] = "relaxed", +}; + static bool has_keyboard(void) { @@ -592,13 +602,14 @@ find_currdev(bool do_bootmgr, char *boot_info, size_t boot_info_sz) zfsinfo_t *zi; /* - * Did efi_zfs_probe() detect the boot pool? If so, use the zpool - * it found, if it's sane. ZFS is the only thing that looks for - * disks and pools to boot. This may change in the future, however, - * if we allow specifying which pool to boot from via UEFI variables - * rather than the bootenv stuff that FreeBSD uses today. + * First try the zfs pool(s) that were on the boot device, then + * try any other pool if we have a relaxed policy. zfsinfo has + * the pools that had elements on the boot device first. */ STAILQ_FOREACH(zi, zfsinfo, zi_link) { + if (boot_policy == STRICT && + zi->zi_handle != boot_img->DeviceHandle) + continue; printf("Trying ZFS pool 0x%jx\n", zi->zi_pool_guid); if (probe_zfs_currdev(zi->zi_pool_guid)) return (0); @@ -1189,6 +1200,23 @@ efi_smbios_detect(void) (void)smbios_detect(smbios_v2_ptr); } +static void +set_boot_policy(void) +{ + const char *policy; + + if ((policy = getenv("boot_policy")) == NULL) + return; + for (int i = 0; i < nitems(policy_map); i++) { + if (strcmp(policy, policy_map[i]) == 0) { + boot_policy = i; + return; + } + } + printf("Unknown boot_policy '%s', defaulting to %s\n", + policy, policy_map[boot_policy]); +} + EFI_STATUS main(int argc, CHAR16 *argv[]) { @@ -1287,6 +1315,8 @@ main(int argc, CHAR16 *argv[]) read_loader_env("LoaderEnv", "/efi/freebsd/loader.env", false); read_loader_env("NextLoaderEnv", NULL, true); + set_boot_policy(); + /* * We now have two notions of console. howto should be viewed as * overrides. If console is already set, don't set it again. |
