diff --git a/stand/defaults/loader.conf.5 b/stand/defaults/loader.conf.5 index 5ef54ee2c5d0..a364030b8814 100644 --- a/stand/defaults/loader.conf.5 +++ b/stand/defaults/loader.conf.5 @@ -1,522 +1,526 @@ .\" Copyright (c) 1999 Daniel C. Sobral .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .Dd February 9, 2025 .Dt LOADER.CONF 5 .Os .Sh NAME .Nm loader.conf .Nd "system bootstrap configuration information" .Sh DESCRIPTION The file .Nm contains descriptive information on bootstrapping the system. Through it you can specify the kernel to be booted, parameters to be passed to it, and additional modules to be loaded; and generally set all variables described in .Xr loader 8 . .Sh SYNTAX Though .Nm Ns 's format was defined explicitly to resemble .Xr rc.conf 5 , and can be sourced by .Xr sh 1 , some settings are treated in a special fashion. Also, the behavior of some settings is defined by the setting's suffix; the prefix identifies which module the setting controls. .Pp The general parsing rules are: .Bl -bullet .It Spaces and empty lines are ignored. .It A # sign will mark the remainder of the line as a comment. .It Only one setting can be present on each line. .El .Pp All settings have the following format: .Pp .Dl variable="value" .Pp Unless it belongs to one of the classes of settings that receive special treatment, a setting will set the value of a .Xr loader 8 environment variable. The settings that receive special treatment are listed below. Settings beginning with .Qq * below define the modules to be loaded and may have any prefix; the prefix identifies a module. All such settings sharing a common prefix refer to the same module. .Bl -tag -width Ar .It Ar autoboot_delay Delay in seconds before automatically booting. A user with console access will be able to interrupt the .Ic autoboot process and escape into the interactive mode by pressing a key on the console during this delay. .Pp If set to .Dq Li NO , no .Ic autoboot is automatically attempted after processing .Pa /boot/loader.rc , though explicit .Ic autoboot Ns 's are processed normally, using a 10 second delay. .Pp If set to .Dq Li 0 , no delay is inserted, but any keys pressed while the kernel and modules are loaded will enter interactive mode. .Pp If set to .Dq Li -1 , no delay will be inserted and .Nm starts interactive mode only if .Ic autoboot has failed. In combination with the .Va beastie_disable option, this option prevents users with console access from being able to interrupt the .Ic autoboot process and escape to the loader prompt. To use the .Va autoboot_delay option in this manner, .Va beastie_disable must be set to .Dq Li YES . .It Ar boot_* See list in .Xr loader.efi 8 since those flags apply to all boot loaders. .It Ar boot_verbose Set to "yes" to get the same effect as boot -v or booting verbose from the loader menu. .It Ar exec Immediately executes a .Xr loader 8 command. This type of setting cannot be processed by programs other than .Xr loader 8 , so its use should be avoided. Multiple instances of it will be processed independently. .It Ar loader_conf_dirs Space separated list of directories to process for configuration files. The lua-based loader will process files with a .Dq .conf suffix that are placed in these directories. Files found here are processed after the ones listed in .Va loader_conf_files but before the ones found in .Va local_loader_conf_files . .It Ar loader_conf_files Defines additional configuration files to be processed right after the present file. .Ar loader_conf_files should be treated as write-only. One cannot depend on any value remaining in the loader environment or carried over into the kernel environment. .It Ar local_loader_conf_files Space separated list of additional configuration files to be processed at last, i.e., after .Va loader_conf_files and .Va loader_conf_dirs are processed. .It Ar product_vars When set, must be a space separated list of environment variable names to walk through to guess product information. The order matters as reading a config file override the previously defined values. Undefined variables are silently ignored. .Pp When product information can be guessed, for each product information found, append .Pa /boot/loader.conf.d/PRODUCT to .Ar loader_conf_dirs . It can be typically used as follow: .Bd -literal smbios.system.planar.maker="PLANAR_MAKER" smbios.system.planar.product="PLANAR_PRODUCT" smbios.system.product="PRODUCT" uboot.m_product="M_PRODUCT" product_vars="smbios.system.planar.maker smbios.system.planar.product smbios.system.product uboot.m_product" .Ed .Pp to read files found in the following directories, in that order: .Bl -bullet -compact .It .Pa /boot/loader.conf.d/PLANAR_MAKER .It .Pa /boot/loader.conf.d/PLANAR_PRODUCT .It .Pa /boot/loader.conf.d/PRODUCT .It .Pa /boot/loader.conf.d/M_PRODUCT .El .It Ar kernel Name of the kernel to be loaded. If no kernel name is set, no additional modules will be loaded. The name must be a subdirectory of .Pa /boot that contains a kernel. .It Ar kernel_options Flags to be passed to the kernel. .It Ar vfs.root.mountfrom Specify the root partition to mount. For example: .Pp .Dl vfs.root.mountfrom="ufs:/dev/da0s1a" .Pp .Xr loader 8 automatically calculates the value of this tunable from .Pa /etc/fstab from the partition the kernel was loaded from. The calculated value might be calculated incorrectly when .Pa /etc/fstab is not available during .Xr loader 8 startup (as during diskless booting from NFS), or if a different device is desired by the user. The preferred value can be set in .Pa /loader.conf . .Pp The value can also be overridden from the .Xr loader 8 command line. This is useful for system recovery when .Pa /etc/fstab is damaged, lost, or read from the wrong partition. .It Ar password Protect boot menu with a password without interrupting .Ic autoboot process. The password should be in clear text format. If a password is set, boot menu will not appear until any key is pressed during countdown period specified by .Va autoboot_delay variable or .Ic autoboot process fails. In both cases user should provide specified password to be able to access boot menu. .It Ar bootlock_password Provides a password to be required by check-password before execution is allowed to continue. The password should be in clear text format. If a password is set, the user must provide specified password to boot. .It Ar verbose_loading If set to .Dq YES , module names will be displayed as they are loaded. .It Ar module_blacklist Blacklist of modules. Modules specified in the blacklist may not be loaded automatically with a .Ar *_load directive, but they may be loaded directly at the .Xr loader 8 prompt. Blacklisted modules may still be loaded indirectly as dependencies of other modules. .It Ar *_load If set to .Dq YES , that module will be loaded. If no name is defined (see below), the module's name is taken to be the same as the prefix. .It Ar *_name Defines the name of the module. .It Ar *_type Defines the module's type. If none is given, it defaults to a kld module. .It Ar *_flags Flags and parameters to be passed to the module. .It Ar *_before Commands to be executed before the module is loaded. Use of this setting should be avoided. .It Ar *_after Commands to be executed after the module is loaded. Use of this setting should be avoided. .It Ar *_error Commands to be executed if the loading of a module fails. Except for the special value .Dq abort , which aborts the bootstrap process, use of this setting should be avoided. .El .Pp .Em WARNING : developers should never use these suffixes for any kernel environment variables (tunables) or conflicts will result. .Sh DEFAULT SETTINGS Most of .Nm Ns 's default settings can be ignored. The few of them which are important or useful are: .Bl -tag -width bootfile -offset indent .It Va local_loader_conf_files .Pq Dq /boot/loader.conf.local Ensure .Va loader.conf.local can always be used to override settings from files found in .Va loader_conf_files and .Va loader_conf_dirs . .It Va bitmap_load .Pq Dq NO If set to .Dq YES , a bitmap will be loaded to be displayed on screen while booting. .It Va bitmap_name .Pq Dq Pa /boot/splash.bmp Name of the bitmap to be loaded. Any other name can be used. .It Va comconsole_speed .Dq ( 115200 or the value of the .Va BOOT_COMCONSOLE_SPEED variable when .Xr loader 8 was compiled). Sets the speed of the serial console. If the previous boot loader stage specified that a serial console is in use then the default speed is determined from the current serial port speed setting. .It Va console .Pq Dq vidconsole .Dq comconsole selects serial console, .Dq vidconsole selects the video console, .Dq efi selects the EFI console, .Dq nullconsole selects a mute console (useful for systems with neither a video console nor a serial port), and .Dq spinconsole selects the video console which prevents any input and hides all output replacing it with .Dq spinning character (useful for embedded products and such). .It Va screen.font Set font size for framebuffer mode. The default font size is selected based on screen resolution. Note that the terminal's size may vary. .It Va screen.textmode Value .Dq 0 will trigger BIOS loader to switch to use VESA BIOS Extension (VBE) frame buffer mode for console. The same effect can be achieved by setting .Va vbe_max_resolution . .Pp Value .Dq 1 will force BIOS loader to use VGA text mode. .Pp If .Va vbe_max_resolution is not set, the loader will try to set screen resolution based on EDID information. If EDID is not available, the default resolution is 800x600 (if available). .It Va screen.height .It Va screen.width .It Va screen.depth .Va screen.height , .Va screen.width , .Va screen.depth are set by loader when loader is using framebuffer mode to draw the screen. .It Va efi_max_resolution .It Va vbe_max_resolution Specify the maximum desired resolution for the EFI or VBE framebuffer console. The following values are accepted: .Bl -column "WidthxHeight" .It Sy Value Ta Sy Resolution .It 480p Ta 640x480 .It 720p Ta 1280x720 .It 1080p Ta 1920x1080 .It 1440p Ta 2560x1440 .It 2160p Ta 3840x2160 .It 4k Ta 3840x2160 .It 5k Ta 5120x2880 .It Va Width Ns x Ns Va Height Ta Va Width Ns x Ns Va Height .El .It Va kernel .Pq Dq kernel .It Va kernels .Pq Dq kernel kernel.old Space or comma separated list of kernels to present in the boot menu. .It Va loader_conf_files .Pq Dq Pa /boot/loader.conf /boot/loader.conf.local .It Va loader_conf_dirs .Pq Dq Pa /boot/loader.conf.d .It Va splash_bmp_load .Pq Dq NO If set to .Dq YES , will load the splash screen module, making it possible to display a bmp image on the screen while booting. .It Va splash_pcx_load .Pq Dq NO If set to .Dq YES , will load the splash screen module, making it possible to display a pcx image on the screen while booting. .It Va vesa_load .Pq Dq NO If set to .Dq YES , the vesa module will be loaded, enabling bitmaps above VGA resolution to be displayed. .It Va beastie_disable If set to .Dq YES , the beastie boot menu will be skipped. +.It Va loader_autoboot_show Pq Dq Li YES +If set to +.Dq NO , +the autoboot menu will not be displayed .It Va loader_logo Pq Dq Li orbbw Selects a desired logo in the beastie boot menu. Possible values are: .Dq Li orbbw , .Dq Li orb , .Dq Li fbsdbw , .Dq Li beastiebw , .Dq Li beastie , and .Dq Li none . .It Va loader_color If set to .Dq NO , the beastie boot menu will be displayed without ANSI coloring. .It Va entropy_cache_load .Pq Dq YES If set to .Dq NO , the very early boot-time entropy file will not be loaded. See the entropy entries in .Xr rc.conf 5 . .It Va entropy_cache_name .Pq Dq /boot/entropy The name of the very early boot-time entropy cache file. .It Va cpu_microcode_load .Pq Dq NO If set to .Dq YES , the microcode update file specified by .Va cpu_microcode_name will be loaded and applied very early during boot. This provides functionality similar to .Xr cpucontrol 8 but ensures that CPU features enabled by microcode updates can be used by the kernel. The update will be re-applied automatically when resuming from an ACPI sleep state. If the update file contains updates for multiple processor models, the kernel will search for and extract a matching update. Currently this setting is supported only on Intel .Dv i386 and .Dv amd64 processors. It has no effect on other processor types. .It Va cpu_microcode_name A path to a microcode update file. .El .Sh OTHER SETTINGS Other settings that may be used in .Nm that have no default value: .Bl -tag -width bootfile -offset indent .It Va fdt_overlays Specifies a comma-delimited list of FDT overlays to apply. .Pa /boot/dtb/overlays is created by default for overlays to be placed in. .It Va kernels_autodetect If set to .Dq YES , attempt to auto-detect kernels installed in .Pa /boot . This is an option specific to the Lua-based loader. It is not available in the default Forth-based loader. .El .Sh FILES .Bl -tag -width /boot/defaults/loader.conf -compact .It Pa /boot/defaults/loader.conf Default settings \(em do not change this file. .It Pa /boot/loader.conf User defined settings. .It Pa /boot/loader.conf.lua User defined settings written in lua. .It Pa /boot/loader.conf.d/*.conf User defined settings split in separate files. .It Pa /boot/loader.conf.d/*.lua User defined settings written in lua and split in separate files. .It Pa /boot/loader.conf.local Machine-specific settings for sites with a common loader.conf. Allow to override settings defined in other files. .El .Sh SEE ALSO .Xr kenv 1 , .Xr loader.conf.lua 5 , .Xr rc.conf 5 , .Xr boot 8 , .Xr cpucontrol 8 , .Xr loader 8 , .Xr loader.4th 8 .Sh HISTORY The file .Nm first appeared in .Fx 3.2 . .Sh AUTHORS This manual page was written by .An Daniel C. Sobral Aq dcs@FreeBSD.org . .Sh BUGS The .Xr loader 8 stops reading .Nm when it encounters a syntax error, so any options which are vital for booting a particular system (i.e., .Dq Va hw.ata.ata_dma Ns "=0" ) should precede any experimental additions to .Nm . diff --git a/stand/lua/menu.lua b/stand/lua/menu.lua index 7c36b6c8d3c8..fb0645eb46ba 100644 --- a/stand/lua/menu.lua +++ b/stand/lua/menu.lua @@ -1,585 +1,588 @@ -- -- SPDX-License-Identifier: BSD-2-Clause -- -- Copyright (c) 2015 Pedro Souza -- Copyright (c) 2018 Kyle Evans -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without -- modification, are permitted provided that the following conditions -- are met: -- 1. Redistributions of source code must retain the above copyright -- notice, this list of conditions and the following disclaimer. -- 2. Redistributions in binary form must reproduce the above copyright -- notice, this list of conditions and the following disclaimer in the -- documentation and/or other materials provided with the distribution. -- -- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -- SUCH DAMAGE. -- local cli = require("cli") local core = require("core") local color = require("color") local config = require("config") local screen = require("screen") local drawer = require("drawer") local menu = {} local drawn_menu local return_menu_entry = { entry_type = core.MENU_RETURN, name = "Back to main menu" .. color.highlight(" [Backspace]"), } local function OnOff(str, value) if value then return str .. color.escapefg(color.GREEN) .. "On" .. color.resetfg() else return str .. color.escapefg(color.RED) .. "off" .. color.resetfg() end 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 end local function multiUserPrompt() return loader.getenv("loader_menu_multi_user_prompt") or "Multi user" end -- Module exports menu.handlers = { -- Menu handlers take the current menu and selected entry as parameters, -- and should return a boolean indicating whether execution should -- continue or not. The return value may be omitted if this entry should -- have no bearing on whether we continue or not, indicating that we -- should just continue after execution. [core.MENU_ENTRY] = function(_, entry) -- run function entry.func() end, [core.MENU_CAROUSEL_ENTRY] = function(_, entry) -- carousel (rotating) functionality local carid = entry.carousel_id local caridx = config.getCarouselIndex(carid) local choices = entry.items if type(choices) == "function" then choices = choices() end if #choices > 0 then caridx = (caridx % #choices) + 1 config.setCarouselIndex(carid, caridx) entry.func(caridx, choices[caridx], choices) end end, [core.MENU_SUBMENU] = function(_, entry) menu.process(entry.submenu) end, [core.MENU_RETURN] = function(_, entry) -- allow entry to have a function/side effect if entry.func ~= nil then entry.func() end return false end, } -- loader menu tree is rooted at menu.welcome menu.boot_environments = { entries = { -- return to welcome menu return_menu_entry, { entry_type = core.MENU_CAROUSEL_ENTRY, carousel_id = "be_active", items = core.bootenvList, name = function(idx, choice, all_choices) if #all_choices == 0 then return "Active: " end local is_default = (idx == 1) local bootenv_name = "" local name_color if is_default then name_color = color.escapefg(color.GREEN) else name_color = color.escapefg(color.CYAN) end bootenv_name = bootenv_name .. name_color .. choice .. color.resetfg() return color.highlight("A").."ctive: " .. bootenv_name .. " (" .. idx .. " of " .. #all_choices .. ")" end, func = function(_, choice, _) bootenvSet(choice) end, alias = {"a", "A"}, }, { entry_type = core.MENU_ENTRY, visible = function() return core.isRewinded() == false end, name = function() return color.highlight("b") .. "ootfs: " .. core.bootenvDefault() end, func = function() -- Reset active boot environment to the default config.setCarouselIndex("be_active", 1) bootenvSet(core.bootenvDefault()) end, alias = {"b", "B"}, }, }, } menu.boot_options = { entries = { -- return to welcome menu return_menu_entry, -- load defaults { entry_type = core.MENU_ENTRY, name = "Load System " .. color.highlight("D") .. "efaults", func = core.setDefaults, alias = {"d", "D"}, }, { entry_type = core.MENU_SEPARATOR, }, { entry_type = core.MENU_SEPARATOR, name = "Boot Options:", }, -- acpi { entry_type = core.MENU_ENTRY, visible = core.hasACPI, name = function() return OnOff(color.highlight("A") .. "CPI :", core.acpi) end, func = core.setACPI, alias = {"a", "A"}, }, -- safe mode { entry_type = core.MENU_ENTRY, name = function() return OnOff("Safe " .. color.highlight("M") .. "ode :", core.sm) end, func = core.setSafeMode, alias = {"m", "M"}, }, -- single user { entry_type = core.MENU_ENTRY, name = function() return OnOff(color.highlight("S") .. "ingle user:", core.su) end, func = core.setSingleUser, alias = {"s", "S"}, }, -- verbose boot { entry_type = core.MENU_ENTRY, name = function() return OnOff(color.highlight("V") .. "erbose :", core.verbose) end, func = core.setVerbose, alias = {"v", "V"}, }, }, } menu.welcome = { entries = function() local menu_entries = menu.welcome.all_entries local multi_user = menu_entries.multi_user local single_user = menu_entries.single_user local boot_entry_1, boot_entry_2 if core.isSingleUserBoot() then -- Swap the first two menu items on single user boot. -- We'll cache the alternate entries for performance. local alts = menu_entries.alts if alts == nil then single_user = core.deepCopyTable(single_user) multi_user = core.deepCopyTable(multi_user) single_user.name = single_user.alternate_name multi_user.name = multi_user.alternate_name menu_entries.alts = { single_user = single_user, multi_user = multi_user, } else single_user = alts.single_user multi_user = alts.multi_user end boot_entry_1, boot_entry_2 = single_user, multi_user else boot_entry_1, boot_entry_2 = multi_user, single_user end return { boot_entry_1, boot_entry_2, menu_entries.prompt, menu_entries.reboot, menu_entries.console, { entry_type = core.MENU_SEPARATOR, }, { entry_type = core.MENU_SEPARATOR, name = "Kernel:", }, menu_entries.kernel_options, { entry_type = core.MENU_SEPARATOR, }, { entry_type = core.MENU_SEPARATOR, name = "Options:", }, menu_entries.boot_options, menu_entries.zpool_checkpoints, menu_entries.boot_envs, menu_entries.chainload, menu_entries.vendor, { entry_type = core.MENU_SEPARATOR, }, menu_entries.loader_needs_upgrade, } end, all_entries = { multi_user = { entry_type = core.MENU_ENTRY, name = function() return color.highlight("B") .. "oot " .. multiUserPrompt() .. " " .. color.highlight("[Enter]") end, -- Not a standard menu entry function! alternate_name = function() return color.highlight("B") .. "oot " .. multiUserPrompt() end, func = function() core.setSingleUser(false) core.boot() end, alias = {"b", "B"}, }, single_user = { entry_type = core.MENU_ENTRY, name = "Boot " .. color.highlight("S") .. "ingle user", -- Not a standard menu entry function! alternate_name = "Boot " .. color.highlight("S") .. "ingle user " .. color.highlight("[Enter]"), func = function() core.setSingleUser(true) core.boot() end, alias = {"s", "S"}, }, console = { entry_type = core.MENU_ENTRY, name = function() return color.highlight("C") .. "ons: " .. core.getConsoleName() end, func = function() core.nextConsoleChoice() end, alias = {"c", "C"}, }, prompt = { entry_type = core.MENU_RETURN, name = color.highlight("Esc") .. "ape to loader prompt", func = function() loader.setenv("autoboot_delay", "NO") end, alias = {core.KEYSTR_ESCAPE}, }, reboot = { entry_type = core.MENU_ENTRY, name = color.highlight("R") .. "eboot", func = function() loader.perform("reboot") end, alias = {"r", "R"}, }, kernel_options = { entry_type = core.MENU_CAROUSEL_ENTRY, carousel_id = "kernel", items = core.kernelList, name = function(idx, choice, all_choices) if #all_choices == 0 then return "" end local kernel_name local name_color if idx == 1 then name_color = color.escapefg(color.GREEN) else name_color = color.escapefg(color.CYAN) end kernel_name = name_color .. choice .. color.resetfg() return kernel_name .. " (" .. idx .. " of " .. #all_choices .. ")" end, func = function(_, choice, _) if loader.getenv("kernelname") ~= nil then loader.perform("unload") end config.selectKernel(choice) end, alias = {"k", "K"}, }, boot_options = { entry_type = core.MENU_SUBMENU, name = "Boot " .. color.highlight("O") .. "ptions", submenu = menu.boot_options, alias = {"o", "O"}, }, zpool_checkpoints = { entry_type = core.MENU_ENTRY, name = function() local rewind = "No" if core.isRewinded() then rewind = "Yes" end return "Rewind ZFS " .. color.highlight("C") .. "heckpoint: " .. rewind end, func = function() core.changeRewindCheckpoint() if core.isRewinded() then bootenvSet( core.bootenvDefaultRewinded()) else bootenvSet(core.bootenvDefault()) end config.setCarouselIndex("be_active", 1) end, visible = function() return core.isZFSBoot() and core.isCheckpointed() end, alias = {"c", "C"}, }, boot_envs = { entry_type = core.MENU_SUBMENU, visible = function() return core.isZFSBoot() and #core.bootenvList() > 1 end, name = "Boot " .. color.highlight("E") .. "nvironments", submenu = menu.boot_environments, alias = {"e", "E"}, }, chainload = { entry_type = core.MENU_ENTRY, name = function() return 'Chain' .. color.highlight("L") .. "oad " .. loader.getenv('chain_disk') end, func = function() loader.perform("chain " .. loader.getenv('chain_disk')) end, visible = function() return loader.getenv('chain_disk') ~= nil end, alias = {"l", "L"}, }, loader_needs_upgrade = { entry_type = core.MENU_SEPARATOR, name = function() return color.highlight("Loader needs to be updated") end, visible = function() return core.loaderTooOld() end }, vendor = { entry_type = core.MENU_ENTRY, visible = function() return false end }, }, } menu.default = menu.welcome -- current_alias_table will be used to keep our alias table consistent across -- screen redraws, instead of relying on whatever triggered the redraw to update -- the local alias_table in menu.process. menu.current_alias_table = {} function menu.draw(menudef) -- Clear the screen, reset the cursor, then draw screen.clear() menu.current_alias_table = drawer.drawscreen(menudef) drawn_menu = menudef screen.defcursor() end -- 'keypress' allows the caller to indicate that a key has been pressed that we -- should process as our initial input. function menu.process(menudef, keypress) assert(menudef ~= nil) if drawn_menu ~= menudef then menu.draw(menudef) end while true do local key = keypress or io.getchar() keypress = nil -- Special key behaviors if (key == core.KEY_BACKSPACE or key == core.KEY_DELETE) and menudef ~= menu.default then break elseif key == core.KEY_ENTER then core.boot() -- Should not return. If it does, escape menu handling -- and drop to loader prompt. return false end key = string.char(key) -- check to see if key is an alias local sel_entry = nil for k, v in pairs(menu.current_alias_table) do if key == k then sel_entry = v break end end -- if we have an alias do the assigned action: if sel_entry ~= nil then local handler = menu.handlers[sel_entry.entry_type] assert(handler ~= nil) -- The handler's return value indicates if we -- need to exit this menu. An omitted or true -- return value means to continue. if handler(menudef, sel_entry) == false then return end -- If we got an alias key the screen is out of date... -- redraw it. menu.draw(menudef) end end end function menu.run() local autoboot_key local delay = loader.getenv("autoboot_delay") if delay ~= nil and delay:lower() == "no" then delay = nil else delay = tonumber(delay) or 10 end if delay == -1 then core.boot() return end menu.draw(menu.default) if delay ~= nil then autoboot_key = menu.autoboot(delay) -- autoboot_key should return the key pressed. It will only -- return nil if we hit the timeout and executed the timeout -- command. Bail out. if autoboot_key == nil then return end end menu.process(menu.default, autoboot_key) drawn_menu = nil screen.defcursor() -- We explicitly want the newline print adds print("Exiting menu!") end function menu.autoboot(delay) local x = loader.getenv("loader_menu_timeout_x") or 4 local y = loader.getenv("loader_menu_timeout_y") or 24 + local autoboot_show = loader.getenv("loader_autoboot_show") or "yes" local endtime = loader.time() + delay local time local last repeat time = endtime - loader.time() if last == nil or last ~= time then last = time - screen.setcursor(x, y) - printc("Autoboot in " .. time .. - " seconds. [Space] to pause ") - screen.defcursor() + if autoboot_show == "yes" then + screen.setcursor(x, y) + printc("Autoboot in " .. time .. + " seconds. [Space] to pause ") + screen.defcursor() + end end if io.ischar() then local ch = io.getchar() if ch == core.KEY_ENTER then break else -- Erase autoboot msg. While real VT100s -- wouldn't scroll when receiving a char with -- the cursor at (79, 24), bad emulators do. -- Avoid the issue by stopping at 79. screen.setcursor(1, y) printc(string.rep(" ", 79)) screen.defcursor() return ch end end loader.delay(50000) until time <= 0 local cmd = loader.getenv("menu_timeout_command") or "boot" cli_execute_unparsed(cmd) return nil end -- CLI commands function cli.menu() menu.run() end return menu