xref: /freebsd/stand/lua/menu.lua (revision 72e39d711d5300beb8f7fa07c17c62d88e2a31b6)
1088b4f5fSWarner Losh--
2*72e39d71SKyle Evans-- SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*72e39d71SKyle Evans--
4088b4f5fSWarner Losh-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
521d5bcbeSKyle Evans-- Copyright (C) 2018 Kyle Evans <kevans@FreeBSD.org>
6088b4f5fSWarner Losh-- All rights reserved.
7088b4f5fSWarner Losh--
8088b4f5fSWarner Losh-- Redistribution and use in source and binary forms, with or without
9088b4f5fSWarner Losh-- modification, are permitted provided that the following conditions
10088b4f5fSWarner Losh-- are met:
11088b4f5fSWarner Losh-- 1. Redistributions of source code must retain the above copyright
12088b4f5fSWarner Losh--    notice, this list of conditions and the following disclaimer.
13088b4f5fSWarner Losh-- 2. Redistributions in binary form must reproduce the above copyright
14088b4f5fSWarner Losh--    notice, this list of conditions and the following disclaimer in the
15088b4f5fSWarner Losh--    documentation and/or other materials provided with the distribution.
16088b4f5fSWarner Losh--
17088b4f5fSWarner Losh-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18088b4f5fSWarner Losh-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19088b4f5fSWarner Losh-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20088b4f5fSWarner Losh-- ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21088b4f5fSWarner Losh-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22088b4f5fSWarner Losh-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23088b4f5fSWarner Losh-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24088b4f5fSWarner Losh-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25088b4f5fSWarner Losh-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26088b4f5fSWarner Losh-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27088b4f5fSWarner Losh-- SUCH DAMAGE.
28088b4f5fSWarner Losh--
29088b4f5fSWarner Losh-- $FreeBSD$
30088b4f5fSWarner Losh--
31088b4f5fSWarner Losh
32088b4f5fSWarner Losh
33aedd6be5SKyle Evanslocal core = require("core")
34aedd6be5SKyle Evanslocal color = require("color")
35aedd6be5SKyle Evanslocal config = require("config")
36aedd6be5SKyle Evanslocal screen = require("screen")
37aedd6be5SKyle Evanslocal drawer = require("drawer")
38088b4f5fSWarner Losh
39aedd6be5SKyle Evanslocal menu = {}
40c8518398SKyle Evans
41e15abd1fSKyle Evanslocal OnOff = function(str, b)
429f71d421SKyle Evans	if b then
43e15abd1fSKyle Evans		return str .. color.escapef(color.GREEN) .. "On" ..
44aedd6be5SKyle Evans		    color.escapef(color.WHITE)
45e15abd1fSKyle Evans	else
46e15abd1fSKyle Evans		return str .. color.escapef(color.RED) .. "off" ..
47aedd6be5SKyle Evans		    color.escapef(color.WHITE)
48e15abd1fSKyle Evans	end
49e15abd1fSKyle Evansend
50e15abd1fSKyle Evans
517efc058fSKyle Evanslocal bootenvSet = function(env)
527efc058fSKyle Evans	loader.setenv("vfs.root.mountfrom", env)
537efc058fSKyle Evans	loader.setenv("currdev", env .. ":")
547efc058fSKyle Evans	config.reload()
557efc058fSKyle Evansend
567efc058fSKyle Evans
57b5746545SKyle Evans-- Module exports
588d415029SKyle Evansmenu.handlers = {
598d415029SKyle Evans	-- Menu handlers take the current menu and selected entry as parameters,
608d415029SKyle Evans	-- and should return a boolean indicating whether execution should
618d415029SKyle Evans	-- continue or not. The return value may be omitted if this entry should
628d415029SKyle Evans	-- have no bearing on whether we continue or not, indicating that we
638d415029SKyle Evans	-- should just continue after execution.
64e2df27e3SKyle Evans	[core.MENU_ENTRY] = function(_, entry)
658d415029SKyle Evans		-- run function
66aedd6be5SKyle Evans		entry.func()
678d415029SKyle Evans	end,
68e2df27e3SKyle Evans	[core.MENU_CAROUSEL_ENTRY] = function(_, entry)
698d415029SKyle Evans		-- carousel (rotating) functionality
70aedd6be5SKyle Evans		local carid = entry.carousel_id
71aedd6be5SKyle Evans		local caridx = config.getCarouselIndex(carid)
724f437f9eSKyle Evans		local choices = entry.items
734f437f9eSKyle Evans		if type(choices) == "function" then
744f437f9eSKyle Evans			choices = choices()
754f437f9eSKyle Evans		end
769f71d421SKyle Evans		if #choices > 0 then
77aedd6be5SKyle Evans			caridx = (caridx % #choices) + 1
78aedd6be5SKyle Evans			config.setCarouselIndex(carid, caridx)
79aedd6be5SKyle Evans			entry.func(caridx, choices[caridx], choices)
808d415029SKyle Evans		end
818d415029SKyle Evans	end,
82e2df27e3SKyle Evans	[core.MENU_SUBMENU] = function(_, entry)
838d415029SKyle Evans		-- recurse
849a28f948SKyle Evans		return menu.run(entry.submenu)
858d415029SKyle Evans	end,
86e2df27e3SKyle Evans	[core.MENU_RETURN] = function(_, entry)
878d415029SKyle Evans		-- allow entry to have a function/side effect
889f71d421SKyle Evans		if entry.func ~= nil then
89aedd6be5SKyle Evans			entry.func()
908d415029SKyle Evans		end
91aedd6be5SKyle Evans		return false
928d415029SKyle Evans	end,
93aedd6be5SKyle Evans}
94280e990bSKyle Evans-- loader menu tree is rooted at menu.welcome
95088b4f5fSWarner Losh
967efc058fSKyle Evansmenu.boot_environments = {
977efc058fSKyle Evans	entries = {
987efc058fSKyle Evans		-- return to welcome menu
997efc058fSKyle Evans		{
1007efc058fSKyle Evans			entry_type = core.MENU_RETURN,
1017efc058fSKyle Evans			name = "Back to main menu" ..
1027efc058fSKyle Evans			    color.highlight(" [Backspace]"),
1037efc058fSKyle Evans		},
1047efc058fSKyle Evans		{
1057efc058fSKyle Evans			entry_type = core.MENU_CAROUSEL_ENTRY,
1067efc058fSKyle Evans			carousel_id = "be_active",
1077efc058fSKyle Evans			items = core.bootenvList,
1087efc058fSKyle Evans			name = function(idx, choice, all_choices)
1097efc058fSKyle Evans				if #all_choices == 0 then
1107efc058fSKyle Evans					return "Active: "
1117efc058fSKyle Evans				end
1127efc058fSKyle Evans
1137efc058fSKyle Evans				local is_default = (idx == 1)
1147efc058fSKyle Evans				local bootenv_name = ""
1157efc058fSKyle Evans				local name_color
1167efc058fSKyle Evans				if is_default then
1177efc058fSKyle Evans					name_color = color.escapef(color.GREEN)
1187efc058fSKyle Evans				else
1197efc058fSKyle Evans					name_color = color.escapef(color.BLUE)
1207efc058fSKyle Evans				end
1217efc058fSKyle Evans				bootenv_name = bootenv_name .. name_color ..
1227efc058fSKyle Evans				    choice .. color.default()
1237efc058fSKyle Evans				return color.highlight("A").."ctive: " ..
1247efc058fSKyle Evans				    bootenv_name .. " (" .. idx .. " of " ..
1257efc058fSKyle Evans				    #all_choices .. ")"
1267efc058fSKyle Evans			end,
127e2df27e3SKyle Evans			func = function(_, choice, _)
1287efc058fSKyle Evans				bootenvSet(choice)
1297efc058fSKyle Evans			end,
1307efc058fSKyle Evans			alias = {"a", "A"},
1317efc058fSKyle Evans		},
1327efc058fSKyle Evans		{
1337efc058fSKyle Evans			entry_type = core.MENU_ENTRY,
1347efc058fSKyle Evans			name = function()
1357efc058fSKyle Evans				return color.highlight("b") .. "ootfs: " ..
1367efc058fSKyle Evans				    core.bootenvDefault()
1377efc058fSKyle Evans			end,
1387efc058fSKyle Evans			func = function()
1397efc058fSKyle Evans				-- Reset active boot environment to the default
1407efc058fSKyle Evans				config.setCarouselIndex("be_active", 1)
1417efc058fSKyle Evans				bootenvSet(core.bootenvDefault())
1427efc058fSKyle Evans			end,
1437efc058fSKyle Evans			alias = {"b", "B"},
1447efc058fSKyle Evans		},
1457efc058fSKyle Evans	},
1467efc058fSKyle Evans}
1477efc058fSKyle Evans
148088b4f5fSWarner Loshmenu.boot_options = {
149d8757746SKyle Evans	entries = {
150088b4f5fSWarner Losh		-- return to welcome menu
151088b4f5fSWarner Losh		{
152a7cf0562SKyle Evans			entry_type = core.MENU_RETURN,
153a51f9f0cSKyle Evans			name = "Back to main menu" ..
154a51f9f0cSKyle Evans			    color.highlight(" [Backspace]"),
155088b4f5fSWarner Losh		},
156088b4f5fSWarner Losh		-- load defaults
157088b4f5fSWarner Losh		{
158a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
159a51f9f0cSKyle Evans			name = "Load System " .. color.highlight("D") ..
160a51f9f0cSKyle Evans			    "efaults",
161a51f9f0cSKyle Evans			func = core.setDefaults,
162088b4f5fSWarner Losh			alias = {"d", "D"}
163088b4f5fSWarner Losh		},
164088b4f5fSWarner Losh		{
165a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
166088b4f5fSWarner Losh		},
167088b4f5fSWarner Losh		{
168a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
169a51f9f0cSKyle Evans			name = "Boot Options:",
170088b4f5fSWarner Losh		},
171088b4f5fSWarner Losh		-- acpi
172088b4f5fSWarner Losh		{
173a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
174c1ab36f5SKyle Evans			visible = core.isSystem386,
175088b4f5fSWarner Losh			name = function()
176fd2b19b3SKyle Evans				return OnOff(color.highlight("A") ..
177aedd6be5SKyle Evans				    "CPI       :", core.acpi)
178088b4f5fSWarner Losh			end,
179a51f9f0cSKyle Evans			func = core.setACPI,
180088b4f5fSWarner Losh			alias = {"a", "A"}
181088b4f5fSWarner Losh		},
182088b4f5fSWarner Losh		-- safe mode
183088b4f5fSWarner Losh		{
184a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
185088b4f5fSWarner Losh			name = function()
18657099121SKyle Evans				return OnOff("Safe " .. color.highlight("M") ..
187aedd6be5SKyle Evans				    "ode  :", core.sm)
188088b4f5fSWarner Losh			end,
189a51f9f0cSKyle Evans			func = core.setSafeMode,
190088b4f5fSWarner Losh			alias = {"m", "M"}
191088b4f5fSWarner Losh		},
192088b4f5fSWarner Losh		-- single user
193088b4f5fSWarner Losh		{
194a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
195088b4f5fSWarner Losh			name = function()
196fd2b19b3SKyle Evans				return OnOff(color.highlight("S") ..
197aedd6be5SKyle Evans				    "ingle user:", core.su)
198088b4f5fSWarner Losh			end,
199a51f9f0cSKyle Evans			func = core.setSingleUser,
200088b4f5fSWarner Losh			alias = {"s", "S"}
201088b4f5fSWarner Losh		},
202088b4f5fSWarner Losh		-- verbose boot
203088b4f5fSWarner Losh		{
204a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
205088b4f5fSWarner Losh			name = function()
206fd2b19b3SKyle Evans				return OnOff(color.highlight("V") ..
207aedd6be5SKyle Evans				    "erbose    :", core.verbose)
208088b4f5fSWarner Losh			end,
209a51f9f0cSKyle Evans			func = core.setVerbose,
210088b4f5fSWarner Losh			alias = {"v", "V"}
211088b4f5fSWarner Losh		},
212d8757746SKyle Evans	},
213aedd6be5SKyle Evans}
214088b4f5fSWarner Losh
215088b4f5fSWarner Loshmenu.welcome = {
216303253e5SKyle Evans	entries = function()
217aedd6be5SKyle Evans		local menu_entries = menu.welcome.all_entries
218303253e5SKyle Evans		-- Swap the first two menu items on single user boot
2199f71d421SKyle Evans		if core.isSingleUserBoot() then
2209a0904b0SKyle Evans			-- We'll cache the swapped menu, for performance
2219f71d421SKyle Evans			if menu.welcome.swapped_menu ~= nil then
222aedd6be5SKyle Evans				return menu.welcome.swapped_menu
2239a0904b0SKyle Evans			end
2245c1b5165SKyle Evans			-- Shallow copy the table
225aedd6be5SKyle Evans			menu_entries = core.shallowCopyTable(menu_entries)
2265c1b5165SKyle Evans
2279a0904b0SKyle Evans			-- Swap the first two menu entries
2284b6da14cSKyle Evans			menu_entries[1], menu_entries[2] =
229aedd6be5SKyle Evans			    menu_entries[2], menu_entries[1]
230303253e5SKyle Evans
2319a0904b0SKyle Evans			-- Then set their names to their alternate names
2329a0904b0SKyle Evans			menu_entries[1].name, menu_entries[2].name =
2339a0904b0SKyle Evans			    menu_entries[1].alternate_name,
234aedd6be5SKyle Evans			    menu_entries[2].alternate_name
235aedd6be5SKyle Evans			menu.welcome.swapped_menu = menu_entries
236303253e5SKyle Evans		end
237aedd6be5SKyle Evans		return menu_entries
238303253e5SKyle Evans	end,
239303253e5SKyle Evans	all_entries = {
240088b4f5fSWarner Losh		-- boot multi user
241088b4f5fSWarner Losh		{
242a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
243a51f9f0cSKyle Evans			name = color.highlight("B") .. "oot Multi user " ..
244a51f9f0cSKyle Evans			    color.highlight("[Enter]"),
2455c1b5165SKyle Evans			-- Not a standard menu entry function!
246a51f9f0cSKyle Evans			alternate_name = color.highlight("B") ..
247a51f9f0cSKyle Evans			    "oot Multi user",
248088b4f5fSWarner Losh			func = function()
249aedd6be5SKyle Evans				core.setSingleUser(false)
250aedd6be5SKyle Evans				core.boot()
251088b4f5fSWarner Losh			end,
252b458bf0dSKyle Evans			alias = {"b", "B"}
253088b4f5fSWarner Losh		},
254088b4f5fSWarner Losh		-- boot single user
255088b4f5fSWarner Losh		{
256a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
257a51f9f0cSKyle Evans			name = "Boot " .. color.highlight("S") .. "ingle user",
2585c1b5165SKyle Evans			-- Not a standard menu entry function!
259a51f9f0cSKyle Evans			alternate_name = "Boot " .. color.highlight("S") ..
260a51f9f0cSKyle Evans			    "ingle user " .. color.highlight("[Enter]"),
261088b4f5fSWarner Losh			func = function()
262aedd6be5SKyle Evans				core.setSingleUser(true)
263aedd6be5SKyle Evans				core.boot()
264088b4f5fSWarner Losh			end,
265088b4f5fSWarner Losh			alias = {"s", "S"}
266088b4f5fSWarner Losh		},
267088b4f5fSWarner Losh		-- escape to interpreter
268088b4f5fSWarner Losh		{
269a7cf0562SKyle Evans			entry_type = core.MENU_RETURN,
270a51f9f0cSKyle Evans			name = color.highlight("Esc") .. "ape to loader prompt",
271ef625845SKyle Evans			func = function()
272aedd6be5SKyle Evans				loader.setenv("autoboot_delay", "NO")
273ef625845SKyle Evans			end,
27439006570SKyle Evans			alias = {core.KEYSTR_ESCAPE}
275088b4f5fSWarner Losh		},
276088b4f5fSWarner Losh		-- reboot
277088b4f5fSWarner Losh		{
278a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
279a51f9f0cSKyle Evans			name = color.highlight("R") .. "eboot",
280088b4f5fSWarner Losh			func = function()
281aedd6be5SKyle Evans				loader.perform("reboot")
282088b4f5fSWarner Losh			end,
283088b4f5fSWarner Losh			alias = {"r", "R"}
284088b4f5fSWarner Losh		},
285088b4f5fSWarner Losh		{
286a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
287088b4f5fSWarner Losh		},
288088b4f5fSWarner Losh		{
289a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
290a51f9f0cSKyle Evans			name = "Options:",
291088b4f5fSWarner Losh		},
292088b4f5fSWarner Losh		-- kernel options
293088b4f5fSWarner Losh		{
294a7cf0562SKyle Evans			entry_type = core.MENU_CAROUSEL_ENTRY,
295ada26c4aSKyle Evans			carousel_id = "kernel",
296ada26c4aSKyle Evans			items = core.kernelList,
297ada26c4aSKyle Evans			name = function(idx, choice, all_choices)
2989f71d421SKyle Evans				if #all_choices == 0 then
299aedd6be5SKyle Evans					return "Kernel: "
300088b4f5fSWarner Losh				end
301b1b1f2b8SKyle Evans
302aedd6be5SKyle Evans				local is_default = (idx == 1)
303aedd6be5SKyle Evans				local kernel_name = ""
304aedd6be5SKyle Evans				local name_color
3059f71d421SKyle Evans				if is_default then
306aedd6be5SKyle Evans					name_color = color.escapef(color.GREEN)
307aedd6be5SKyle Evans					kernel_name = "default/"
308bcf48a15SKyle Evans				else
309aedd6be5SKyle Evans					name_color = color.escapef(color.BLUE)
310b1b1f2b8SKyle Evans				end
311fd2b19b3SKyle Evans				kernel_name = kernel_name .. name_color ..
312aedd6be5SKyle Evans				    choice .. color.default()
313fd2b19b3SKyle Evans				return color.highlight("K") .. "ernel: " ..
314fd2b19b3SKyle Evans				    kernel_name .. " (" .. idx .. " of " ..
315aedd6be5SKyle Evans				    #all_choices .. ")"
316088b4f5fSWarner Losh			end,
317e2df27e3SKyle Evans			func = function(_, choice, _)
318aedd6be5SKyle Evans				config.selectkernel(choice)
319088b4f5fSWarner Losh			end,
320088b4f5fSWarner Losh			alias = {"k", "K"}
321088b4f5fSWarner Losh		},
322088b4f5fSWarner Losh		-- boot options
323088b4f5fSWarner Losh		{
324a7cf0562SKyle Evans			entry_type = core.MENU_SUBMENU,
325a51f9f0cSKyle Evans			name = "Boot " .. color.highlight("O") .. "ptions",
3269a28f948SKyle Evans			submenu = menu.boot_options,
327088b4f5fSWarner Losh			alias = {"o", "O"}
328d8757746SKyle Evans		},
3297efc058fSKyle Evans		-- boot environments
3307efc058fSKyle Evans		{
3317efc058fSKyle Evans			entry_type = core.MENU_SUBMENU,
3327efc058fSKyle Evans			visible = function()
3337efc058fSKyle Evans				return core.isZFSBoot() and
3347efc058fSKyle Evans				    #core.bootenvList() > 1
3357efc058fSKyle Evans			end,
3367efc058fSKyle Evans			name = "Boot " .. color.highlight("E") .. "nvironments",
3377efc058fSKyle Evans			submenu = menu.boot_environments,
3387efc058fSKyle Evans			alias = {"e", "E"},
3397efc058fSKyle Evans		},
340d8757746SKyle Evans	},
341aedd6be5SKyle Evans}
342088b4f5fSWarner Losh
34320a81676SKyle Evansmenu.default = menu.welcome
34420a81676SKyle Evans
345088b4f5fSWarner Loshfunction menu.run(m)
346088b4f5fSWarner Losh
3479f71d421SKyle Evans	if menu.skip() then
348aedd6be5SKyle Evans		core.autoboot()
349aedd6be5SKyle Evans		return false
350088b4f5fSWarner Losh	end
351088b4f5fSWarner Losh
3529f71d421SKyle Evans	if m == nil then
35320a81676SKyle Evans		m = menu.default
354088b4f5fSWarner Losh	end
355088b4f5fSWarner Losh
356088b4f5fSWarner Losh	-- redraw screen
357aedd6be5SKyle Evans	screen.clear()
358aedd6be5SKyle Evans	screen.defcursor()
359aedd6be5SKyle Evans	local alias_table = drawer.drawscreen(m)
360088b4f5fSWarner Losh
36112b95c84SKyle Evans	-- Might return nil, that's ok
3627dcffa90SKyle Evans	local autoboot_key;
3637dcffa90SKyle Evans	if m == menu.default then
3647dcffa90SKyle Evans		autoboot_key = menu.autoboot()
3657dcffa90SKyle Evans	end
366e2df27e3SKyle Evans	local cont = true
3679f71d421SKyle Evans	while cont do
36812b95c84SKyle Evans		local key = autoboot_key or io.getchar()
36912b95c84SKyle Evans		autoboot_key = nil
370088b4f5fSWarner Losh
371b458bf0dSKyle Evans		-- Special key behaviors
3729f71d421SKyle Evans		if (key == core.KEY_BACKSPACE or key == core.KEY_DELETE) and
37320a81676SKyle Evans		    m ~= menu.default then
374aedd6be5SKyle Evans			break
3759f71d421SKyle Evans		elseif key == core.KEY_ENTER then
376aedd6be5SKyle Evans			core.boot()
377b458bf0dSKyle Evans			-- Should not return
378abc4f7e7SKyle Evans		end
379abc4f7e7SKyle Evans
380abc4f7e7SKyle Evans		key = string.char(key)
381088b4f5fSWarner Losh		-- check to see if key is an alias
382aedd6be5SKyle Evans		local sel_entry = nil
383088b4f5fSWarner Losh		for k, v in pairs(alias_table) do
3849f71d421SKyle Evans			if key == k then
385aedd6be5SKyle Evans				sel_entry = v
386088b4f5fSWarner Losh			end
387088b4f5fSWarner Losh		end
388088b4f5fSWarner Losh
389088b4f5fSWarner Losh		-- if we have an alias do the assigned action:
3909f71d421SKyle Evans		if sel_entry ~= nil then
3918d415029SKyle Evans			-- Get menu handler
392aedd6be5SKyle Evans			local handler = menu.handlers[sel_entry.entry_type]
3939f71d421SKyle Evans			if handler ~= nil then
3948d415029SKyle Evans				-- The handler's return value indicates whether
3958d415029SKyle Evans				-- we need to exit this menu. An omitted return
3968d415029SKyle Evans				-- value means "continue" by default.
397aedd6be5SKyle Evans				cont = handler(m, sel_entry)
3989f71d421SKyle Evans				if cont == nil then
399aedd6be5SKyle Evans					cont = true
400aefcaa7eSKyle Evans				end
401088b4f5fSWarner Losh			end
402088b4f5fSWarner Losh			-- if we got an alias key the screen is out of date:
403aedd6be5SKyle Evans			screen.clear()
404aedd6be5SKyle Evans			screen.defcursor()
405aedd6be5SKyle Evans			alias_table = drawer.drawscreen(m)
406088b4f5fSWarner Losh		end
407088b4f5fSWarner Losh	end
408088b4f5fSWarner Losh
40920a81676SKyle Evans	if m == menu.default then
410aedd6be5SKyle Evans		screen.defcursor()
411aedd6be5SKyle Evans		print("Exiting menu!")
412aedd6be5SKyle Evans		return false
413088b4f5fSWarner Losh	end
414088b4f5fSWarner Losh
415aedd6be5SKyle Evans	return true
416088b4f5fSWarner Loshend
417088b4f5fSWarner Losh
418088b4f5fSWarner Loshfunction menu.skip()
4199f71d421SKyle Evans	if core.isSerialBoot() then
420aedd6be5SKyle Evans		return true
421088b4f5fSWarner Losh	end
422aedd6be5SKyle Evans	local c = string.lower(loader.getenv("console") or "")
4239f71d421SKyle Evans	if c:match("^efi[ ;]") ~= nil or c:match("[ ;]efi[ ;]") ~= nil then
424aedd6be5SKyle Evans		return true
425088b4f5fSWarner Losh	end
426088b4f5fSWarner Losh
427aedd6be5SKyle Evans	c = string.lower(loader.getenv("beastie_disable") or "")
428aedd6be5SKyle Evans	print("beastie_disable", c)
429aedd6be5SKyle Evans	return c == "yes"
430088b4f5fSWarner Loshend
431088b4f5fSWarner Losh
432088b4f5fSWarner Loshfunction menu.autoboot()
433aedd6be5SKyle Evans	local ab = loader.getenv("autoboot_delay")
4349f71d421SKyle Evans	if ab ~= nil and ab:lower() == "no" then
43512b95c84SKyle Evans		return nil
4369f71d421SKyle Evans	elseif tonumber(ab) == -1 then
437aedd6be5SKyle Evans		core.boot()
438088b4f5fSWarner Losh	end
439aedd6be5SKyle Evans	ab = tonumber(ab) or 10
440088b4f5fSWarner Losh
441aedd6be5SKyle Evans	local x = loader.getenv("loader_menu_timeout_x") or 5
442aedd6be5SKyle Evans	local y = loader.getenv("loader_menu_timeout_y") or 22
443088b4f5fSWarner Losh
444aedd6be5SKyle Evans	local endtime = loader.time() + ab
445aedd6be5SKyle Evans	local time
446088b4f5fSWarner Losh
447088b4f5fSWarner Losh	repeat
448aedd6be5SKyle Evans		time = endtime - loader.time()
449aedd6be5SKyle Evans		screen.setcursor(x, y)
45057099121SKyle Evans		print("Autoboot in " .. time ..
45157099121SKyle Evans		    " seconds, hit [Enter] to boot" ..
452aedd6be5SKyle Evans		    " or any other key to stop     ")
453aedd6be5SKyle Evans		screen.defcursor()
4549f71d421SKyle Evans		if io.ischar() then
455aedd6be5SKyle Evans			local ch = io.getchar()
4569f71d421SKyle Evans			if ch == core.KEY_ENTER then
457aedd6be5SKyle Evans				break
458088b4f5fSWarner Losh			else
459088b4f5fSWarner Losh				-- erase autoboot msg
460aedd6be5SKyle Evans				screen.setcursor(0, y)
46166964bbcSKyle Evans				print(string.rep(" ", 80))
462aedd6be5SKyle Evans				screen.defcursor()
46312b95c84SKyle Evans				return ch
464088b4f5fSWarner Losh			end
465088b4f5fSWarner Losh		end
466088b4f5fSWarner Losh
467aedd6be5SKyle Evans		loader.delay(50000)
468aedd6be5SKyle Evans	until time <= 0
469aedd6be5SKyle Evans	core.boot()
470088b4f5fSWarner Losh
471088b4f5fSWarner Loshend
472088b4f5fSWarner Losh
473aedd6be5SKyle Evansreturn menu
474