xref: /freebsd/stand/lua/menu.lua (revision 66964bbc36334eade58778fcb50f13f6d4d6326b)
1088b4f5fSWarner Losh--
2088b4f5fSWarner Losh-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
321d5bcbeSKyle Evans-- Copyright (C) 2018 Kyle Evans <kevans@FreeBSD.org>
4088b4f5fSWarner Losh-- All rights reserved.
5088b4f5fSWarner Losh--
6088b4f5fSWarner Losh-- Redistribution and use in source and binary forms, with or without
7088b4f5fSWarner Losh-- modification, are permitted provided that the following conditions
8088b4f5fSWarner Losh-- are met:
9088b4f5fSWarner Losh-- 1. Redistributions of source code must retain the above copyright
10088b4f5fSWarner Losh--    notice, this list of conditions and the following disclaimer.
11088b4f5fSWarner Losh-- 2. Redistributions in binary form must reproduce the above copyright
12088b4f5fSWarner Losh--    notice, this list of conditions and the following disclaimer in the
13088b4f5fSWarner Losh--    documentation and/or other materials provided with the distribution.
14088b4f5fSWarner Losh--
15088b4f5fSWarner Losh-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16088b4f5fSWarner Losh-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17088b4f5fSWarner Losh-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18088b4f5fSWarner Losh-- ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19088b4f5fSWarner Losh-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20088b4f5fSWarner Losh-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21088b4f5fSWarner Losh-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22088b4f5fSWarner Losh-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23088b4f5fSWarner Losh-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24088b4f5fSWarner Losh-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25088b4f5fSWarner Losh-- SUCH DAMAGE.
26088b4f5fSWarner Losh--
27088b4f5fSWarner Losh-- $FreeBSD$
28088b4f5fSWarner Losh--
29088b4f5fSWarner Losh
30088b4f5fSWarner Losh
31aedd6be5SKyle Evanslocal core = require("core")
32aedd6be5SKyle Evanslocal color = require("color")
33aedd6be5SKyle Evanslocal config = require("config")
34aedd6be5SKyle Evanslocal screen = require("screen")
35aedd6be5SKyle Evanslocal drawer = require("drawer")
36088b4f5fSWarner Losh
37aedd6be5SKyle Evanslocal menu = {}
38c8518398SKyle Evans
39e15abd1fSKyle Evanslocal OnOff = function(str, b)
409f71d421SKyle Evans	if b then
41e15abd1fSKyle Evans		return str .. color.escapef(color.GREEN) .. "On" ..
42aedd6be5SKyle Evans		    color.escapef(color.WHITE)
43e15abd1fSKyle Evans	else
44e15abd1fSKyle Evans		return str .. color.escapef(color.RED) .. "off" ..
45aedd6be5SKyle Evans		    color.escapef(color.WHITE)
46e15abd1fSKyle Evans	end
47e15abd1fSKyle Evansend
48e15abd1fSKyle Evans
497efc058fSKyle Evanslocal bootenvSet = function(env)
507efc058fSKyle Evans	loader.setenv("vfs.root.mountfrom", env)
517efc058fSKyle Evans	loader.setenv("currdev", env .. ":")
527efc058fSKyle Evans	config.reload()
537efc058fSKyle Evansend
547efc058fSKyle Evans
55b5746545SKyle Evans-- Module exports
568d415029SKyle Evansmenu.handlers = {
578d415029SKyle Evans	-- Menu handlers take the current menu and selected entry as parameters,
588d415029SKyle Evans	-- and should return a boolean indicating whether execution should
598d415029SKyle Evans	-- continue or not. The return value may be omitted if this entry should
608d415029SKyle Evans	-- have no bearing on whether we continue or not, indicating that we
618d415029SKyle Evans	-- should just continue after execution.
62e2df27e3SKyle Evans	[core.MENU_ENTRY] = function(_, entry)
638d415029SKyle Evans		-- run function
64aedd6be5SKyle Evans		entry.func()
658d415029SKyle Evans	end,
66e2df27e3SKyle Evans	[core.MENU_CAROUSEL_ENTRY] = function(_, entry)
678d415029SKyle Evans		-- carousel (rotating) functionality
68aedd6be5SKyle Evans		local carid = entry.carousel_id
69aedd6be5SKyle Evans		local caridx = config.getCarouselIndex(carid)
704f437f9eSKyle Evans		local choices = entry.items
714f437f9eSKyle Evans		if type(choices) == "function" then
724f437f9eSKyle Evans			choices = choices()
734f437f9eSKyle Evans		end
749f71d421SKyle Evans		if #choices > 0 then
75aedd6be5SKyle Evans			caridx = (caridx % #choices) + 1
76aedd6be5SKyle Evans			config.setCarouselIndex(carid, caridx)
77aedd6be5SKyle Evans			entry.func(caridx, choices[caridx], choices)
788d415029SKyle Evans		end
798d415029SKyle Evans	end,
80e2df27e3SKyle Evans	[core.MENU_SUBMENU] = function(_, entry)
818d415029SKyle Evans		-- recurse
829a28f948SKyle Evans		return menu.run(entry.submenu)
838d415029SKyle Evans	end,
84e2df27e3SKyle Evans	[core.MENU_RETURN] = function(_, entry)
858d415029SKyle Evans		-- allow entry to have a function/side effect
869f71d421SKyle Evans		if entry.func ~= nil then
87aedd6be5SKyle Evans			entry.func()
888d415029SKyle Evans		end
89aedd6be5SKyle Evans		return false
908d415029SKyle Evans	end,
91aedd6be5SKyle Evans}
92280e990bSKyle Evans-- loader menu tree is rooted at menu.welcome
93088b4f5fSWarner Losh
947efc058fSKyle Evansmenu.boot_environments = {
957efc058fSKyle Evans	entries = {
967efc058fSKyle Evans		-- return to welcome menu
977efc058fSKyle Evans		{
987efc058fSKyle Evans			entry_type = core.MENU_RETURN,
997efc058fSKyle Evans			name = "Back to main menu" ..
1007efc058fSKyle Evans			    color.highlight(" [Backspace]"),
1017efc058fSKyle Evans		},
1027efc058fSKyle Evans		{
1037efc058fSKyle Evans			entry_type = core.MENU_CAROUSEL_ENTRY,
1047efc058fSKyle Evans			carousel_id = "be_active",
1057efc058fSKyle Evans			items = core.bootenvList,
1067efc058fSKyle Evans			name = function(idx, choice, all_choices)
1077efc058fSKyle Evans				if #all_choices == 0 then
1087efc058fSKyle Evans					return "Active: "
1097efc058fSKyle Evans				end
1107efc058fSKyle Evans
1117efc058fSKyle Evans				local is_default = (idx == 1)
1127efc058fSKyle Evans				local bootenv_name = ""
1137efc058fSKyle Evans				local name_color
1147efc058fSKyle Evans				if is_default then
1157efc058fSKyle Evans					name_color = color.escapef(color.GREEN)
1167efc058fSKyle Evans				else
1177efc058fSKyle Evans					name_color = color.escapef(color.BLUE)
1187efc058fSKyle Evans				end
1197efc058fSKyle Evans				bootenv_name = bootenv_name .. name_color ..
1207efc058fSKyle Evans				    choice .. color.default()
1217efc058fSKyle Evans				return color.highlight("A").."ctive: " ..
1227efc058fSKyle Evans				    bootenv_name .. " (" .. idx .. " of " ..
1237efc058fSKyle Evans				    #all_choices .. ")"
1247efc058fSKyle Evans			end,
125e2df27e3SKyle Evans			func = function(_, choice, _)
1267efc058fSKyle Evans				bootenvSet(choice)
1277efc058fSKyle Evans			end,
1287efc058fSKyle Evans			alias = {"a", "A"},
1297efc058fSKyle Evans		},
1307efc058fSKyle Evans		{
1317efc058fSKyle Evans			entry_type = core.MENU_ENTRY,
1327efc058fSKyle Evans			name = function()
1337efc058fSKyle Evans				return color.highlight("b") .. "ootfs: " ..
1347efc058fSKyle Evans				    core.bootenvDefault()
1357efc058fSKyle Evans			end,
1367efc058fSKyle Evans			func = function()
1377efc058fSKyle Evans				-- Reset active boot environment to the default
1387efc058fSKyle Evans				config.setCarouselIndex("be_active", 1)
1397efc058fSKyle Evans				bootenvSet(core.bootenvDefault())
1407efc058fSKyle Evans			end,
1417efc058fSKyle Evans			alias = {"b", "B"},
1427efc058fSKyle Evans		},
1437efc058fSKyle Evans	},
1447efc058fSKyle Evans}
1457efc058fSKyle Evans
146088b4f5fSWarner Loshmenu.boot_options = {
147d8757746SKyle Evans	entries = {
148088b4f5fSWarner Losh		-- return to welcome menu
149088b4f5fSWarner Losh		{
150a7cf0562SKyle Evans			entry_type = core.MENU_RETURN,
151a51f9f0cSKyle Evans			name = "Back to main menu" ..
152a51f9f0cSKyle Evans			    color.highlight(" [Backspace]"),
153088b4f5fSWarner Losh		},
154088b4f5fSWarner Losh		-- load defaults
155088b4f5fSWarner Losh		{
156a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
157a51f9f0cSKyle Evans			name = "Load System " .. color.highlight("D") ..
158a51f9f0cSKyle Evans			    "efaults",
159a51f9f0cSKyle Evans			func = core.setDefaults,
160088b4f5fSWarner Losh			alias = {"d", "D"}
161088b4f5fSWarner Losh		},
162088b4f5fSWarner Losh		{
163a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
164088b4f5fSWarner Losh		},
165088b4f5fSWarner Losh		{
166a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
167a51f9f0cSKyle Evans			name = "Boot Options:",
168088b4f5fSWarner Losh		},
169088b4f5fSWarner Losh		-- acpi
170088b4f5fSWarner Losh		{
171a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
172c1ab36f5SKyle Evans			visible = core.isSystem386,
173088b4f5fSWarner Losh			name = function()
174fd2b19b3SKyle Evans				return OnOff(color.highlight("A") ..
175aedd6be5SKyle Evans				    "CPI       :", core.acpi)
176088b4f5fSWarner Losh			end,
177a51f9f0cSKyle Evans			func = core.setACPI,
178088b4f5fSWarner Losh			alias = {"a", "A"}
179088b4f5fSWarner Losh		},
180088b4f5fSWarner Losh		-- safe mode
181088b4f5fSWarner Losh		{
182a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
183088b4f5fSWarner Losh			name = function()
18457099121SKyle Evans				return OnOff("Safe " .. color.highlight("M") ..
185aedd6be5SKyle Evans				    "ode  :", core.sm)
186088b4f5fSWarner Losh			end,
187a51f9f0cSKyle Evans			func = core.setSafeMode,
188088b4f5fSWarner Losh			alias = {"m", "M"}
189088b4f5fSWarner Losh		},
190088b4f5fSWarner Losh		-- single user
191088b4f5fSWarner Losh		{
192a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
193088b4f5fSWarner Losh			name = function()
194fd2b19b3SKyle Evans				return OnOff(color.highlight("S") ..
195aedd6be5SKyle Evans				    "ingle user:", core.su)
196088b4f5fSWarner Losh			end,
197a51f9f0cSKyle Evans			func = core.setSingleUser,
198088b4f5fSWarner Losh			alias = {"s", "S"}
199088b4f5fSWarner Losh		},
200088b4f5fSWarner Losh		-- verbose boot
201088b4f5fSWarner Losh		{
202a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
203088b4f5fSWarner Losh			name = function()
204fd2b19b3SKyle Evans				return OnOff(color.highlight("V") ..
205aedd6be5SKyle Evans				    "erbose    :", core.verbose)
206088b4f5fSWarner Losh			end,
207a51f9f0cSKyle Evans			func = core.setVerbose,
208088b4f5fSWarner Losh			alias = {"v", "V"}
209088b4f5fSWarner Losh		},
210d8757746SKyle Evans	},
211aedd6be5SKyle Evans}
212088b4f5fSWarner Losh
213088b4f5fSWarner Loshmenu.welcome = {
214303253e5SKyle Evans	entries = function()
215aedd6be5SKyle Evans		local menu_entries = menu.welcome.all_entries
216303253e5SKyle Evans		-- Swap the first two menu items on single user boot
2179f71d421SKyle Evans		if core.isSingleUserBoot() then
2189a0904b0SKyle Evans			-- We'll cache the swapped menu, for performance
2199f71d421SKyle Evans			if menu.welcome.swapped_menu ~= nil then
220aedd6be5SKyle Evans				return menu.welcome.swapped_menu
2219a0904b0SKyle Evans			end
2225c1b5165SKyle Evans			-- Shallow copy the table
223aedd6be5SKyle Evans			menu_entries = core.shallowCopyTable(menu_entries)
2245c1b5165SKyle Evans
2259a0904b0SKyle Evans			-- Swap the first two menu entries
2264b6da14cSKyle Evans			menu_entries[1], menu_entries[2] =
227aedd6be5SKyle Evans			    menu_entries[2], menu_entries[1]
228303253e5SKyle Evans
2299a0904b0SKyle Evans			-- Then set their names to their alternate names
2309a0904b0SKyle Evans			menu_entries[1].name, menu_entries[2].name =
2319a0904b0SKyle Evans			    menu_entries[1].alternate_name,
232aedd6be5SKyle Evans			    menu_entries[2].alternate_name
233aedd6be5SKyle Evans			menu.welcome.swapped_menu = menu_entries
234303253e5SKyle Evans		end
235aedd6be5SKyle Evans		return menu_entries
236303253e5SKyle Evans	end,
237303253e5SKyle Evans	all_entries = {
238088b4f5fSWarner Losh		-- boot multi user
239088b4f5fSWarner Losh		{
240a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
241a51f9f0cSKyle Evans			name = color.highlight("B") .. "oot Multi user " ..
242a51f9f0cSKyle Evans			    color.highlight("[Enter]"),
2435c1b5165SKyle Evans			-- Not a standard menu entry function!
244a51f9f0cSKyle Evans			alternate_name = color.highlight("B") ..
245a51f9f0cSKyle Evans			    "oot Multi user",
246088b4f5fSWarner Losh			func = function()
247aedd6be5SKyle Evans				core.setSingleUser(false)
248aedd6be5SKyle Evans				core.boot()
249088b4f5fSWarner Losh			end,
250b458bf0dSKyle Evans			alias = {"b", "B"}
251088b4f5fSWarner Losh		},
252088b4f5fSWarner Losh		-- boot single user
253088b4f5fSWarner Losh		{
254a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
255a51f9f0cSKyle Evans			name = "Boot " .. color.highlight("S") .. "ingle user",
2565c1b5165SKyle Evans			-- Not a standard menu entry function!
257a51f9f0cSKyle Evans			alternate_name = "Boot " .. color.highlight("S") ..
258a51f9f0cSKyle Evans			    "ingle user " .. color.highlight("[Enter]"),
259088b4f5fSWarner Losh			func = function()
260aedd6be5SKyle Evans				core.setSingleUser(true)
261aedd6be5SKyle Evans				core.boot()
262088b4f5fSWarner Losh			end,
263088b4f5fSWarner Losh			alias = {"s", "S"}
264088b4f5fSWarner Losh		},
265088b4f5fSWarner Losh		-- escape to interpreter
266088b4f5fSWarner Losh		{
267a7cf0562SKyle Evans			entry_type = core.MENU_RETURN,
268a51f9f0cSKyle Evans			name = color.highlight("Esc") .. "ape to loader prompt",
269ef625845SKyle Evans			func = function()
270aedd6be5SKyle Evans				loader.setenv("autoboot_delay", "NO")
271ef625845SKyle Evans			end,
27239006570SKyle Evans			alias = {core.KEYSTR_ESCAPE}
273088b4f5fSWarner Losh		},
274088b4f5fSWarner Losh		-- reboot
275088b4f5fSWarner Losh		{
276a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
277a51f9f0cSKyle Evans			name = color.highlight("R") .. "eboot",
278088b4f5fSWarner Losh			func = function()
279aedd6be5SKyle Evans				loader.perform("reboot")
280088b4f5fSWarner Losh			end,
281088b4f5fSWarner Losh			alias = {"r", "R"}
282088b4f5fSWarner Losh		},
283088b4f5fSWarner Losh		{
284a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
285088b4f5fSWarner Losh		},
286088b4f5fSWarner Losh		{
287a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
288a51f9f0cSKyle Evans			name = "Options:",
289088b4f5fSWarner Losh		},
290088b4f5fSWarner Losh		-- kernel options
291088b4f5fSWarner Losh		{
292a7cf0562SKyle Evans			entry_type = core.MENU_CAROUSEL_ENTRY,
293ada26c4aSKyle Evans			carousel_id = "kernel",
294ada26c4aSKyle Evans			items = core.kernelList,
295ada26c4aSKyle Evans			name = function(idx, choice, all_choices)
2969f71d421SKyle Evans				if #all_choices == 0 then
297aedd6be5SKyle Evans					return "Kernel: "
298088b4f5fSWarner Losh				end
299b1b1f2b8SKyle Evans
300aedd6be5SKyle Evans				local is_default = (idx == 1)
301aedd6be5SKyle Evans				local kernel_name = ""
302aedd6be5SKyle Evans				local name_color
3039f71d421SKyle Evans				if is_default then
304aedd6be5SKyle Evans					name_color = color.escapef(color.GREEN)
305aedd6be5SKyle Evans					kernel_name = "default/"
306bcf48a15SKyle Evans				else
307aedd6be5SKyle Evans					name_color = color.escapef(color.BLUE)
308b1b1f2b8SKyle Evans				end
309fd2b19b3SKyle Evans				kernel_name = kernel_name .. name_color ..
310aedd6be5SKyle Evans				    choice .. color.default()
311fd2b19b3SKyle Evans				return color.highlight("K") .. "ernel: " ..
312fd2b19b3SKyle Evans				    kernel_name .. " (" .. idx .. " of " ..
313aedd6be5SKyle Evans				    #all_choices .. ")"
314088b4f5fSWarner Losh			end,
315e2df27e3SKyle Evans			func = function(_, choice, _)
316aedd6be5SKyle Evans				config.selectkernel(choice)
317088b4f5fSWarner Losh			end,
318088b4f5fSWarner Losh			alias = {"k", "K"}
319088b4f5fSWarner Losh		},
320088b4f5fSWarner Losh		-- boot options
321088b4f5fSWarner Losh		{
322a7cf0562SKyle Evans			entry_type = core.MENU_SUBMENU,
323a51f9f0cSKyle Evans			name = "Boot " .. color.highlight("O") .. "ptions",
3249a28f948SKyle Evans			submenu = menu.boot_options,
325088b4f5fSWarner Losh			alias = {"o", "O"}
326d8757746SKyle Evans		},
3277efc058fSKyle Evans		-- boot environments
3287efc058fSKyle Evans		{
3297efc058fSKyle Evans			entry_type = core.MENU_SUBMENU,
3307efc058fSKyle Evans			visible = function()
3317efc058fSKyle Evans				return core.isZFSBoot() and
3327efc058fSKyle Evans				    #core.bootenvList() > 1
3337efc058fSKyle Evans			end,
3347efc058fSKyle Evans			name = "Boot " .. color.highlight("E") .. "nvironments",
3357efc058fSKyle Evans			submenu = menu.boot_environments,
3367efc058fSKyle Evans			alias = {"e", "E"},
3377efc058fSKyle Evans		},
338d8757746SKyle Evans	},
339aedd6be5SKyle Evans}
340088b4f5fSWarner Losh
34120a81676SKyle Evansmenu.default = menu.welcome
34220a81676SKyle Evans
343088b4f5fSWarner Loshfunction menu.run(m)
344088b4f5fSWarner Losh
3459f71d421SKyle Evans	if menu.skip() then
346aedd6be5SKyle Evans		core.autoboot()
347aedd6be5SKyle Evans		return false
348088b4f5fSWarner Losh	end
349088b4f5fSWarner Losh
3509f71d421SKyle Evans	if m == nil then
35120a81676SKyle Evans		m = menu.default
352088b4f5fSWarner Losh	end
353088b4f5fSWarner Losh
354088b4f5fSWarner Losh	-- redraw screen
355aedd6be5SKyle Evans	screen.clear()
356aedd6be5SKyle Evans	screen.defcursor()
357aedd6be5SKyle Evans	local alias_table = drawer.drawscreen(m)
358088b4f5fSWarner Losh
35912b95c84SKyle Evans	-- Might return nil, that's ok
3607dcffa90SKyle Evans	local autoboot_key;
3617dcffa90SKyle Evans	if m == menu.default then
3627dcffa90SKyle Evans		autoboot_key = menu.autoboot()
3637dcffa90SKyle Evans	end
364e2df27e3SKyle Evans	local cont = true
3659f71d421SKyle Evans	while cont do
36612b95c84SKyle Evans		local key = autoboot_key or io.getchar()
36712b95c84SKyle Evans		autoboot_key = nil
368088b4f5fSWarner Losh
369b458bf0dSKyle Evans		-- Special key behaviors
3709f71d421SKyle Evans		if (key == core.KEY_BACKSPACE or key == core.KEY_DELETE) and
37120a81676SKyle Evans		    m ~= menu.default then
372aedd6be5SKyle Evans			break
3739f71d421SKyle Evans		elseif key == core.KEY_ENTER then
374aedd6be5SKyle Evans			core.boot()
375b458bf0dSKyle Evans			-- Should not return
376abc4f7e7SKyle Evans		end
377abc4f7e7SKyle Evans
378abc4f7e7SKyle Evans		key = string.char(key)
379088b4f5fSWarner Losh		-- check to see if key is an alias
380aedd6be5SKyle Evans		local sel_entry = nil
381088b4f5fSWarner Losh		for k, v in pairs(alias_table) do
3829f71d421SKyle Evans			if key == k then
383aedd6be5SKyle Evans				sel_entry = v
384088b4f5fSWarner Losh			end
385088b4f5fSWarner Losh		end
386088b4f5fSWarner Losh
387088b4f5fSWarner Losh		-- if we have an alias do the assigned action:
3889f71d421SKyle Evans		if sel_entry ~= nil then
3898d415029SKyle Evans			-- Get menu handler
390aedd6be5SKyle Evans			local handler = menu.handlers[sel_entry.entry_type]
3919f71d421SKyle Evans			if handler ~= nil then
3928d415029SKyle Evans				-- The handler's return value indicates whether
3938d415029SKyle Evans				-- we need to exit this menu. An omitted return
3948d415029SKyle Evans				-- value means "continue" by default.
395aedd6be5SKyle Evans				cont = handler(m, sel_entry)
3969f71d421SKyle Evans				if cont == nil then
397aedd6be5SKyle Evans					cont = true
398aefcaa7eSKyle Evans				end
399088b4f5fSWarner Losh			end
400088b4f5fSWarner Losh			-- if we got an alias key the screen is out of date:
401aedd6be5SKyle Evans			screen.clear()
402aedd6be5SKyle Evans			screen.defcursor()
403aedd6be5SKyle Evans			alias_table = drawer.drawscreen(m)
404088b4f5fSWarner Losh		end
405088b4f5fSWarner Losh	end
406088b4f5fSWarner Losh
40720a81676SKyle Evans	if m == menu.default then
408aedd6be5SKyle Evans		screen.defcursor()
409aedd6be5SKyle Evans		print("Exiting menu!")
410aedd6be5SKyle Evans		return false
411088b4f5fSWarner Losh	end
412088b4f5fSWarner Losh
413aedd6be5SKyle Evans	return true
414088b4f5fSWarner Loshend
415088b4f5fSWarner Losh
416088b4f5fSWarner Loshfunction menu.skip()
4179f71d421SKyle Evans	if core.isSerialBoot() then
418aedd6be5SKyle Evans		return true
419088b4f5fSWarner Losh	end
420aedd6be5SKyle Evans	local c = string.lower(loader.getenv("console") or "")
4219f71d421SKyle Evans	if c:match("^efi[ ;]") ~= nil or c:match("[ ;]efi[ ;]") ~= nil then
422aedd6be5SKyle Evans		return true
423088b4f5fSWarner Losh	end
424088b4f5fSWarner Losh
425aedd6be5SKyle Evans	c = string.lower(loader.getenv("beastie_disable") or "")
426aedd6be5SKyle Evans	print("beastie_disable", c)
427aedd6be5SKyle Evans	return c == "yes"
428088b4f5fSWarner Loshend
429088b4f5fSWarner Losh
430088b4f5fSWarner Loshfunction menu.autoboot()
431aedd6be5SKyle Evans	local ab = loader.getenv("autoboot_delay")
4329f71d421SKyle Evans	if ab ~= nil and ab:lower() == "no" then
43312b95c84SKyle Evans		return nil
4349f71d421SKyle Evans	elseif tonumber(ab) == -1 then
435aedd6be5SKyle Evans		core.boot()
436088b4f5fSWarner Losh	end
437aedd6be5SKyle Evans	ab = tonumber(ab) or 10
438088b4f5fSWarner Losh
439aedd6be5SKyle Evans	local x = loader.getenv("loader_menu_timeout_x") or 5
440aedd6be5SKyle Evans	local y = loader.getenv("loader_menu_timeout_y") or 22
441088b4f5fSWarner Losh
442aedd6be5SKyle Evans	local endtime = loader.time() + ab
443aedd6be5SKyle Evans	local time
444088b4f5fSWarner Losh
445088b4f5fSWarner Losh	repeat
446aedd6be5SKyle Evans		time = endtime - loader.time()
447aedd6be5SKyle Evans		screen.setcursor(x, y)
44857099121SKyle Evans		print("Autoboot in " .. time ..
44957099121SKyle Evans		    " seconds, hit [Enter] to boot" ..
450aedd6be5SKyle Evans		    " or any other key to stop     ")
451aedd6be5SKyle Evans		screen.defcursor()
4529f71d421SKyle Evans		if io.ischar() then
453aedd6be5SKyle Evans			local ch = io.getchar()
4549f71d421SKyle Evans			if ch == core.KEY_ENTER then
455aedd6be5SKyle Evans				break
456088b4f5fSWarner Losh			else
457088b4f5fSWarner Losh				-- erase autoboot msg
458aedd6be5SKyle Evans				screen.setcursor(0, y)
459*66964bbcSKyle Evans				print(string.rep(" ", 80))
460aedd6be5SKyle Evans				screen.defcursor()
46112b95c84SKyle Evans				return ch
462088b4f5fSWarner Losh			end
463088b4f5fSWarner Losh		end
464088b4f5fSWarner Losh
465aedd6be5SKyle Evans		loader.delay(50000)
466aedd6be5SKyle Evans	until time <= 0
467aedd6be5SKyle Evans	core.boot()
468088b4f5fSWarner Losh
469088b4f5fSWarner Loshend
470088b4f5fSWarner Losh
471aedd6be5SKyle Evansreturn menu
472