The branch main has been updated by imp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=784150fd25351f4a38f4d983882f4a26cc5d3272

commit 784150fd25351f4a38f4d983882f4a26cc5d3272
Author:     Warner Losh <[email protected]>
AuthorDate: 2026-02-27 00:57:39 +0000
Commit:     Warner Losh <[email protected]>
CommitDate: 2026-02-27 01:01:36 +0000

    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
---
 stand/efi/libefi/efizfs.c | 10 +++++++---
 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.

Reply via email to