The branch main has been updated by kevans:

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

commit c7ff706b31c22f10c2403869c46b443448da3e08
Author:     Kyle Evans <[email protected]>
AuthorDate: 2026-06-04 13:57:16 +0000
Commit:     Kyle Evans <[email protected]>
CommitDate: 2026-06-04 13:59:49 +0000

    lualoader: add be-list and be-switch commands
    
    This is useful for driving BE changes from the loader command prompt,
    rather than having to use the menu.  Note that the active carousel in
    the boot environment carousel doesn't currently reflect a switch in
    boot environments done this way- I'm considering this only a minor bug,
    as you probably can't or won't go back to the menu if you're using these
    commands.
    
    Reviewed by:    imp (previous version)
---
 stand/lua/cli.lua    | 23 +++++++++++++++++++++++
 stand/lua/core.lua   | 43 +++++++++++++++++++++++++++++++++++++++++++
 stand/lua/core.lua.8 | 17 ++++++++++++++++-
 stand/lua/menu.lua   |  7 +------
 stand/man/loader.8   | 15 ++++++++++++++-
 5 files changed, 97 insertions(+), 8 deletions(-)

diff --git a/stand/lua/cli.lua b/stand/lua/cli.lua
index dda8c3da4c89..fe358b7fd7ab 100644
--- a/stand/lua/cli.lua
+++ b/stand/lua/cli.lua
@@ -160,6 +160,29 @@ cli["disable-module"] = function(...)
        setModule(argv[1], false)
 end
 
+cli['be-list'] = function(...)
+       local _, argv = cli.arguments(...)
+       if #argv ~= 0 then
+               print("usage error: be-list")
+               return
+       end
+
+       for _, bootenv in core.bootenvIter() do
+               print(bootenv)
+       end
+end
+
+cli['be-switch'] = function(...)
+       local _, argv = cli.arguments(...)
+       if #argv == 0 then
+               print("usage error: be-switch beName")
+               return
+       end
+
+       local env = argv[1]
+       core.switchBE(env)
+end
+
 cli["toggle-module"] = function(...)
        local _, argv = cli.arguments(...)
        if #argv == 0 then
diff --git a/stand/lua/core.lua b/stand/lua/core.lua
index 471e579619c7..11fe17d7cfbe 100644
--- a/stand/lua/core.lua
+++ b/stand/lua/core.lua
@@ -314,6 +314,21 @@ function core.bootenvFilter(func)
        return oldf
 end
 
+function core.bootenvIter()
+       local envs = core.bootenvList()
+
+       if #envs ~= 0 then
+               local root = "zfs:" .. loader.getenv("zfs_be_root") .. "/"
+
+               for idx, bespec in ipairs(envs) do
+                       bespec = bespec:gsub("^" .. root, "")
+                       envs[idx] = bespec
+               end
+       end
+
+       return next, envs, nil
+end
+
 function core.bootenvList()
        local bootenv_count = tonumber(loader.getenv(bootenv_list .. "_count"))
        local bootenvs = {}
@@ -567,6 +582,34 @@ function core.nextConsoleChoice()
        end
 end
 
+function core.switchBE(env)
+       -- This branch will most likely be taken by the switch-be CLI command,
+       -- not by the menu.  We could do some more validation that it's a valid
+       -- BE and let the user fully specify a zfs:be/dataset to avoid the
+       -- validation, but this isn't done at the moment.
+       if not env:match("^zfs:") then
+               local root = loader.getenv("zfs_be_root")
+
+               if not root then
+                       print("ZFS BE root not available -- no action taken")
+                       return
+               end
+
+               if not env:match("^" .. root) then
+                       env = "zfs:" .. root .. "/" .. env
+               else
+                       env = "zfs:" .. env
+               end
+       end
+
+       loader.setenv("vfs.root.mountfrom", env)
+       loader.setenv("currdev", env .. ":")
+       config.reload()
+       if loader.getenv("kernelname") ~= nil then
+               loader.perform("unload")
+       end
+end
+
 -- The graphical-enabled loaders have unicode drawing character support. The
 -- text-only ones do not. We check the old and new bindings for term_drawrect 
as
 -- a proxy for unicode support, which will work on older boot loaders as well
diff --git a/stand/lua/core.lua.8 b/stand/lua/core.lua.8
index 325320b2fce8..5cb2b46bd9d1 100644
--- a/stand/lua/core.lua.8
+++ b/stand/lua/core.lua.8
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 8, 2026
+.Dd June 4, 2026
 .Dt CORE.LUA 8
 .Os
 .Sh NAME
@@ -175,6 +175,12 @@ returns true, then the boot environment is retained in the 
list.
 Otherwise, the boot environment is hidden.
 The old filter, if any, is returned to allow the caller to compose a filter on
 top of another filter.
+.It Fn core.bootenvIter
+Returns an iterator over the known boot environment list.
+The returned boot environment names do not include the boot environmnt root,
+which would need to be added back on from the
+.Ev zfs_be_root
+environment variable.
 .It Fn core.bootenvList
 Returns a table of boot environments, or an empty table.
 These will be picked up using the
@@ -229,6 +235,15 @@ If there are no elements, this returns nil and nil.
 If there is one element, this returns the front element and an empty table.
 This will not operate on truly associative tables; numeric indices are
 required.
+.It Fn core.switchBE beName
+Switch to the requested
+.Fa beName .
+It may be either be formatted as a fully-qualified loader dataset path
+.Dq zfs:pool/ROOT/beName ,
+or like one of
+.Dq pool/ROOT/beName
+or
+.Dq beName .
 .It Fn core.loaderTooOld
 Returns true if the loader is too old.
 Specifically, this means, is the loader old enough to require one or more
diff --git a/stand/lua/menu.lua b/stand/lua/menu.lua
index fb0645eb46ba..fb2603eb4b4c 100644
--- a/stand/lua/menu.lua
+++ b/stand/lua/menu.lua
@@ -53,12 +53,7 @@ local function OnOff(str, value)
 end
 
 local function bootenvSet(env)
-       loader.setenv("vfs.root.mountfrom", env)
-       loader.setenv("currdev", env .. ":")
-       config.reload()
-       if loader.getenv("kernelname") ~= nil then
-               loader.perform("unload")
-       end
+       core.switchBE(env)
 end
 
 local function multiUserPrompt()
diff --git a/stand/man/loader.8 b/stand/man/loader.8
index 484e0a7b300c..e35414049e23 100644
--- a/stand/man/loader.8
+++ b/stand/man/loader.8
@@ -26,7 +26,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd November 14, 2025
+.Dd June 4, 2026
 .Dt LOADER 8
 .Os
 .Sh NAME
@@ -97,6 +97,19 @@ and
 .Pp
 .Bl -tag -width indent -compact
 .\" sort the following entries according to the second field
+.It Ic be-list
+Lists the boot environments that are visible to
+.Nm .
+The listed names may be used directly with
+.Ic be-switch .
+.It Ic be-switch Ar beName
+Switch to the
+.Ar beName
+boot environment.
+The
+.Nm
+configuration will be reloaded from the new root, and any previously loaded
+kernel and modules will be immediately unloaded.
 .It Ic boot-conf
 Load the
 .Nm

Reply via email to