xref: /freebsd/stand/lua/menu.lua (revision 04af422907599825aa89cce0399932835d414103)
1088b4f5fSWarner Losh--
272e39d71SKyle Evans-- SPDX-License-Identifier: BSD-2-Clause-FreeBSD
372e39d71SKyle 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
41beafe961SKyle Evanslocal drawn_menu
42ca16d83fSKyle Evans
43*04af4229SKyle Evanslocal function OnOff(str, value)
44*04af4229SKyle Evans	if value then
45e15abd1fSKyle Evans		return str .. color.escapef(color.GREEN) .. "On" ..
46aedd6be5SKyle Evans		    color.escapef(color.WHITE)
47e15abd1fSKyle Evans	else
48e15abd1fSKyle Evans		return str .. color.escapef(color.RED) .. "off" ..
49aedd6be5SKyle Evans		    color.escapef(color.WHITE)
50e15abd1fSKyle Evans	end
51e15abd1fSKyle Evansend
52e15abd1fSKyle Evans
539ed6f9efSKyle Evanslocal function bootenvSet(env)
547efc058fSKyle Evans	loader.setenv("vfs.root.mountfrom", env)
557efc058fSKyle Evans	loader.setenv("currdev", env .. ":")
567efc058fSKyle Evans	config.reload()
577efc058fSKyle Evansend
587efc058fSKyle Evans
59b5746545SKyle Evans-- Module exports
608d415029SKyle Evansmenu.handlers = {
618d415029SKyle Evans	-- Menu handlers take the current menu and selected entry as parameters,
628d415029SKyle Evans	-- and should return a boolean indicating whether execution should
638d415029SKyle Evans	-- continue or not. The return value may be omitted if this entry should
648d415029SKyle Evans	-- have no bearing on whether we continue or not, indicating that we
658d415029SKyle Evans	-- should just continue after execution.
66e2df27e3SKyle Evans	[core.MENU_ENTRY] = function(_, entry)
678d415029SKyle Evans		-- run function
68aedd6be5SKyle Evans		entry.func()
698d415029SKyle Evans	end,
70e2df27e3SKyle Evans	[core.MENU_CAROUSEL_ENTRY] = function(_, entry)
718d415029SKyle Evans		-- carousel (rotating) functionality
72aedd6be5SKyle Evans		local carid = entry.carousel_id
73aedd6be5SKyle Evans		local caridx = config.getCarouselIndex(carid)
744f437f9eSKyle Evans		local choices = entry.items
754f437f9eSKyle Evans		if type(choices) == "function" then
764f437f9eSKyle Evans			choices = choices()
774f437f9eSKyle Evans		end
789f71d421SKyle Evans		if #choices > 0 then
79aedd6be5SKyle Evans			caridx = (caridx % #choices) + 1
80aedd6be5SKyle Evans			config.setCarouselIndex(carid, caridx)
81aedd6be5SKyle Evans			entry.func(caridx, choices[caridx], choices)
828d415029SKyle Evans		end
838d415029SKyle Evans	end,
84e2df27e3SKyle Evans	[core.MENU_SUBMENU] = function(_, entry)
85da9ab827SKyle Evans		menu.process(entry.submenu)
868d415029SKyle Evans	end,
87e2df27e3SKyle Evans	[core.MENU_RETURN] = function(_, entry)
888d415029SKyle Evans		-- allow entry to have a function/side effect
899f71d421SKyle Evans		if entry.func ~= nil then
90aedd6be5SKyle Evans			entry.func()
918d415029SKyle Evans		end
92aedd6be5SKyle Evans		return false
938d415029SKyle Evans	end,
94aedd6be5SKyle Evans}
95280e990bSKyle Evans-- loader menu tree is rooted at menu.welcome
96088b4f5fSWarner Losh
977efc058fSKyle Evansmenu.boot_environments = {
987efc058fSKyle Evans	entries = {
997efc058fSKyle Evans		-- return to welcome menu
1007efc058fSKyle Evans		{
1017efc058fSKyle Evans			entry_type = core.MENU_RETURN,
1027efc058fSKyle Evans			name = "Back to main menu" ..
1037efc058fSKyle Evans			    color.highlight(" [Backspace]"),
1047efc058fSKyle Evans		},
1057efc058fSKyle Evans		{
1067efc058fSKyle Evans			entry_type = core.MENU_CAROUSEL_ENTRY,
1077efc058fSKyle Evans			carousel_id = "be_active",
1087efc058fSKyle Evans			items = core.bootenvList,
1097efc058fSKyle Evans			name = function(idx, choice, all_choices)
1107efc058fSKyle Evans				if #all_choices == 0 then
1117efc058fSKyle Evans					return "Active: "
1127efc058fSKyle Evans				end
1137efc058fSKyle Evans
1147efc058fSKyle Evans				local is_default = (idx == 1)
1157efc058fSKyle Evans				local bootenv_name = ""
1167efc058fSKyle Evans				local name_color
1177efc058fSKyle Evans				if is_default then
1187efc058fSKyle Evans					name_color = color.escapef(color.GREEN)
1197efc058fSKyle Evans				else
1207efc058fSKyle Evans					name_color = color.escapef(color.BLUE)
1217efc058fSKyle Evans				end
1227efc058fSKyle Evans				bootenv_name = bootenv_name .. name_color ..
1237efc058fSKyle Evans				    choice .. color.default()
1247efc058fSKyle Evans				return color.highlight("A").."ctive: " ..
1257efc058fSKyle Evans				    bootenv_name .. " (" .. idx .. " of " ..
1267efc058fSKyle Evans				    #all_choices .. ")"
1277efc058fSKyle Evans			end,
128e2df27e3SKyle Evans			func = function(_, choice, _)
1297efc058fSKyle Evans				bootenvSet(choice)
1307efc058fSKyle Evans			end,
1317efc058fSKyle Evans			alias = {"a", "A"},
1327efc058fSKyle Evans		},
1337efc058fSKyle Evans		{
1347efc058fSKyle Evans			entry_type = core.MENU_ENTRY,
1357efc058fSKyle Evans			name = function()
1367efc058fSKyle Evans				return color.highlight("b") .. "ootfs: " ..
1377efc058fSKyle Evans				    core.bootenvDefault()
1387efc058fSKyle Evans			end,
1397efc058fSKyle Evans			func = function()
1407efc058fSKyle Evans				-- Reset active boot environment to the default
1417efc058fSKyle Evans				config.setCarouselIndex("be_active", 1)
1427efc058fSKyle Evans				bootenvSet(core.bootenvDefault())
1437efc058fSKyle Evans			end,
1447efc058fSKyle Evans			alias = {"b", "B"},
1457efc058fSKyle Evans		},
1467efc058fSKyle Evans	},
1477efc058fSKyle Evans}
1487efc058fSKyle Evans
149088b4f5fSWarner Loshmenu.boot_options = {
150d8757746SKyle Evans	entries = {
151088b4f5fSWarner Losh		-- return to welcome menu
152088b4f5fSWarner Losh		{
153a7cf0562SKyle Evans			entry_type = core.MENU_RETURN,
154a51f9f0cSKyle Evans			name = "Back to main menu" ..
155a51f9f0cSKyle Evans			    color.highlight(" [Backspace]"),
156088b4f5fSWarner Losh		},
157088b4f5fSWarner Losh		-- load defaults
158088b4f5fSWarner Losh		{
159a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
160a51f9f0cSKyle Evans			name = "Load System " .. color.highlight("D") ..
161a51f9f0cSKyle Evans			    "efaults",
162a51f9f0cSKyle Evans			func = core.setDefaults,
1633cd5547bSKyle Evans			alias = {"d", "D"},
164088b4f5fSWarner Losh		},
165088b4f5fSWarner Losh		{
166a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
167088b4f5fSWarner Losh		},
168088b4f5fSWarner Losh		{
169a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
170a51f9f0cSKyle Evans			name = "Boot Options:",
171088b4f5fSWarner Losh		},
172088b4f5fSWarner Losh		-- acpi
173088b4f5fSWarner Losh		{
174a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
175c1ab36f5SKyle Evans			visible = core.isSystem386,
176088b4f5fSWarner Losh			name = function()
177fd2b19b3SKyle Evans				return OnOff(color.highlight("A") ..
178aedd6be5SKyle Evans				    "CPI       :", core.acpi)
179088b4f5fSWarner Losh			end,
180a51f9f0cSKyle Evans			func = core.setACPI,
1813cd5547bSKyle Evans			alias = {"a", "A"},
182088b4f5fSWarner Losh		},
183088b4f5fSWarner Losh		-- safe mode
184088b4f5fSWarner Losh		{
185a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
186088b4f5fSWarner Losh			name = function()
18757099121SKyle Evans				return OnOff("Safe " .. color.highlight("M") ..
188aedd6be5SKyle Evans				    "ode  :", core.sm)
189088b4f5fSWarner Losh			end,
190a51f9f0cSKyle Evans			func = core.setSafeMode,
1913cd5547bSKyle Evans			alias = {"m", "M"},
192088b4f5fSWarner Losh		},
193088b4f5fSWarner Losh		-- single user
194088b4f5fSWarner Losh		{
195a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
196088b4f5fSWarner Losh			name = function()
197fd2b19b3SKyle Evans				return OnOff(color.highlight("S") ..
198aedd6be5SKyle Evans				    "ingle user:", core.su)
199088b4f5fSWarner Losh			end,
200a51f9f0cSKyle Evans			func = core.setSingleUser,
2013cd5547bSKyle Evans			alias = {"s", "S"},
202088b4f5fSWarner Losh		},
203088b4f5fSWarner Losh		-- verbose boot
204088b4f5fSWarner Losh		{
205a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
206088b4f5fSWarner Losh			name = function()
207fd2b19b3SKyle Evans				return OnOff(color.highlight("V") ..
208aedd6be5SKyle Evans				    "erbose    :", core.verbose)
209088b4f5fSWarner Losh			end,
210a51f9f0cSKyle Evans			func = core.setVerbose,
2113cd5547bSKyle Evans			alias = {"v", "V"},
212088b4f5fSWarner Losh		},
213d8757746SKyle Evans	},
214aedd6be5SKyle Evans}
215088b4f5fSWarner Losh
216088b4f5fSWarner Loshmenu.welcome = {
217303253e5SKyle Evans	entries = function()
218aedd6be5SKyle Evans		local menu_entries = menu.welcome.all_entries
219303253e5SKyle Evans		-- Swap the first two menu items on single user boot
2209f71d421SKyle Evans		if core.isSingleUserBoot() then
2219a0904b0SKyle Evans			-- We'll cache the swapped menu, for performance
2229f71d421SKyle Evans			if menu.welcome.swapped_menu ~= nil then
223aedd6be5SKyle Evans				return menu.welcome.swapped_menu
2249a0904b0SKyle Evans			end
2255c1b5165SKyle Evans			-- Shallow copy the table
226ee4e69f1SKyle Evans			menu_entries = core.deepCopyTable(menu_entries)
2275c1b5165SKyle Evans
2289a0904b0SKyle Evans			-- Swap the first two menu entries
2294b6da14cSKyle Evans			menu_entries[1], menu_entries[2] =
230aedd6be5SKyle Evans			    menu_entries[2], menu_entries[1]
231303253e5SKyle Evans
2329a0904b0SKyle Evans			-- Then set their names to their alternate names
2339a0904b0SKyle Evans			menu_entries[1].name, menu_entries[2].name =
2349a0904b0SKyle Evans			    menu_entries[1].alternate_name,
235aedd6be5SKyle Evans			    menu_entries[2].alternate_name
236aedd6be5SKyle Evans			menu.welcome.swapped_menu = menu_entries
237303253e5SKyle Evans		end
238aedd6be5SKyle Evans		return menu_entries
239303253e5SKyle Evans	end,
240303253e5SKyle Evans	all_entries = {
241088b4f5fSWarner Losh		-- boot multi user
242088b4f5fSWarner Losh		{
243a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
244a51f9f0cSKyle Evans			name = color.highlight("B") .. "oot Multi user " ..
245a51f9f0cSKyle Evans			    color.highlight("[Enter]"),
2465c1b5165SKyle Evans			-- Not a standard menu entry function!
247a51f9f0cSKyle Evans			alternate_name = color.highlight("B") ..
248a51f9f0cSKyle Evans			    "oot Multi user",
249088b4f5fSWarner Losh			func = function()
250aedd6be5SKyle Evans				core.setSingleUser(false)
251aedd6be5SKyle Evans				core.boot()
252088b4f5fSWarner Losh			end,
2533cd5547bSKyle Evans			alias = {"b", "B"},
254088b4f5fSWarner Losh		},
255088b4f5fSWarner Losh		-- boot single user
256088b4f5fSWarner Losh		{
257a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
258a51f9f0cSKyle Evans			name = "Boot " .. color.highlight("S") .. "ingle user",
2595c1b5165SKyle Evans			-- Not a standard menu entry function!
260a51f9f0cSKyle Evans			alternate_name = "Boot " .. color.highlight("S") ..
261a51f9f0cSKyle Evans			    "ingle user " .. color.highlight("[Enter]"),
262088b4f5fSWarner Losh			func = function()
263aedd6be5SKyle Evans				core.setSingleUser(true)
264aedd6be5SKyle Evans				core.boot()
265088b4f5fSWarner Losh			end,
2663cd5547bSKyle Evans			alias = {"s", "S"},
267088b4f5fSWarner Losh		},
268088b4f5fSWarner Losh		-- escape to interpreter
269088b4f5fSWarner Losh		{
270a7cf0562SKyle Evans			entry_type = core.MENU_RETURN,
271a51f9f0cSKyle Evans			name = color.highlight("Esc") .. "ape to loader prompt",
272ef625845SKyle Evans			func = function()
273aedd6be5SKyle Evans				loader.setenv("autoboot_delay", "NO")
274ef625845SKyle Evans			end,
2753cd5547bSKyle Evans			alias = {core.KEYSTR_ESCAPE},
276088b4f5fSWarner Losh		},
277088b4f5fSWarner Losh		-- reboot
278088b4f5fSWarner Losh		{
279a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
280a51f9f0cSKyle Evans			name = color.highlight("R") .. "eboot",
281088b4f5fSWarner Losh			func = function()
282aedd6be5SKyle Evans				loader.perform("reboot")
283088b4f5fSWarner Losh			end,
2843cd5547bSKyle Evans			alias = {"r", "R"},
285088b4f5fSWarner Losh		},
286088b4f5fSWarner Losh		{
287a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
288088b4f5fSWarner Losh		},
289088b4f5fSWarner Losh		{
290a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
291a51f9f0cSKyle Evans			name = "Options:",
292088b4f5fSWarner Losh		},
293088b4f5fSWarner Losh		-- kernel options
294088b4f5fSWarner Losh		{
295a7cf0562SKyle Evans			entry_type = core.MENU_CAROUSEL_ENTRY,
296ada26c4aSKyle Evans			carousel_id = "kernel",
297ada26c4aSKyle Evans			items = core.kernelList,
298ada26c4aSKyle Evans			name = function(idx, choice, all_choices)
2999f71d421SKyle Evans				if #all_choices == 0 then
300aedd6be5SKyle Evans					return "Kernel: "
301088b4f5fSWarner Losh				end
302b1b1f2b8SKyle Evans
303aedd6be5SKyle Evans				local is_default = (idx == 1)
304aedd6be5SKyle Evans				local kernel_name = ""
305aedd6be5SKyle Evans				local name_color
3069f71d421SKyle Evans				if is_default then
307aedd6be5SKyle Evans					name_color = color.escapef(color.GREEN)
308aedd6be5SKyle Evans					kernel_name = "default/"
309bcf48a15SKyle Evans				else
310aedd6be5SKyle Evans					name_color = color.escapef(color.BLUE)
311b1b1f2b8SKyle Evans				end
312fd2b19b3SKyle Evans				kernel_name = kernel_name .. name_color ..
313aedd6be5SKyle Evans				    choice .. color.default()
314fd2b19b3SKyle Evans				return color.highlight("K") .. "ernel: " ..
315fd2b19b3SKyle Evans				    kernel_name .. " (" .. idx .. " of " ..
316aedd6be5SKyle Evans				    #all_choices .. ")"
317088b4f5fSWarner Losh			end,
318e2df27e3SKyle Evans			func = function(_, choice, _)
319322a2dddSKyle Evans				config.selectKernel(choice)
320088b4f5fSWarner Losh			end,
3213cd5547bSKyle Evans			alias = {"k", "K"},
322088b4f5fSWarner Losh		},
323088b4f5fSWarner Losh		-- boot options
324088b4f5fSWarner Losh		{
325a7cf0562SKyle Evans			entry_type = core.MENU_SUBMENU,
326a51f9f0cSKyle Evans			name = "Boot " .. color.highlight("O") .. "ptions",
3279a28f948SKyle Evans			submenu = menu.boot_options,
3283cd5547bSKyle Evans			alias = {"o", "O"},
329d8757746SKyle Evans		},
3307efc058fSKyle Evans		-- boot environments
3317efc058fSKyle Evans		{
3327efc058fSKyle Evans			entry_type = core.MENU_SUBMENU,
3337efc058fSKyle Evans			visible = function()
3347efc058fSKyle Evans				return core.isZFSBoot() and
3357efc058fSKyle Evans				    #core.bootenvList() > 1
3367efc058fSKyle Evans			end,
3377efc058fSKyle Evans			name = "Boot " .. color.highlight("E") .. "nvironments",
3387efc058fSKyle Evans			submenu = menu.boot_environments,
3397efc058fSKyle Evans			alias = {"e", "E"},
3407efc058fSKyle Evans		},
341d8757746SKyle Evans	},
342aedd6be5SKyle Evans}
343088b4f5fSWarner Losh
34420a81676SKyle Evansmenu.default = menu.welcome
34528384160SKyle Evans-- current_alias_table will be used to keep our alias table consistent across
34628384160SKyle Evans-- screen redraws, instead of relying on whatever triggered the redraw to update
34728384160SKyle Evans-- the local alias_table in menu.process.
34828384160SKyle Evansmenu.current_alias_table = {}
34920a81676SKyle Evans
3502a11b810SKyle Evansfunction menu.draw(menudef)
351beafe961SKyle Evans	-- Clear the screen, reset the cursor, then draw
352aedd6be5SKyle Evans	screen.clear()
353aedd6be5SKyle Evans	screen.defcursor()
3542a11b810SKyle Evans	menu.current_alias_table = drawer.drawscreen(menudef)
3552a11b810SKyle Evans	drawn_menu = menudef
35628384160SKyle Evansend
35728384160SKyle Evans
358ca16d83fSKyle Evans-- 'keypress' allows the caller to indicate that a key has been pressed that we
359ca16d83fSKyle Evans-- should process as our initial input.
3602a11b810SKyle Evansfunction menu.process(menudef, keypress)
3612a11b810SKyle Evans	assert(menudef ~= nil)
36228384160SKyle Evans
3632a11b810SKyle Evans	if drawn_menu ~= menudef then
3642a11b810SKyle Evans		menu.draw(menudef)
3657dcffa90SKyle Evans	end
366ca16d83fSKyle Evans
367da9ab827SKyle Evans	while true do
368ca16d83fSKyle Evans		local key = keypress or io.getchar()
369ca16d83fSKyle Evans		keypress = nil
370088b4f5fSWarner Losh
371b458bf0dSKyle Evans		-- Special key behaviors
3729f71d421SKyle Evans		if (key == core.KEY_BACKSPACE or key == core.KEY_DELETE) and
3732a11b810SKyle Evans		    menudef ~= 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
38328384160SKyle Evans		for k, v in pairs(menu.current_alias_table) do
3849f71d421SKyle Evans			if key == k then
385aedd6be5SKyle Evans				sel_entry = v
38628384160SKyle Evans				break
387088b4f5fSWarner Losh			end
388088b4f5fSWarner Losh		end
389088b4f5fSWarner Losh
390088b4f5fSWarner Losh		-- if we have an alias do the assigned action:
3919f71d421SKyle Evans		if sel_entry ~= nil then
392aedd6be5SKyle Evans			local handler = menu.handlers[sel_entry.entry_type]
3932a11b810SKyle Evans			assert(handler ~= nil)
394da9ab827SKyle Evans			-- The handler's return value indicates if we
395da9ab827SKyle Evans			-- need to exit this menu.  An omitted or true
396da9ab827SKyle Evans			-- return value means to continue.
3972a11b810SKyle Evans			if handler(menudef, sel_entry) == false then
398da9ab827SKyle Evans				return
399aefcaa7eSKyle Evans			end
40028384160SKyle Evans			-- If we got an alias key the screen is out of date...
40128384160SKyle Evans			-- redraw it.
4022a11b810SKyle Evans			menu.draw(menudef)
403088b4f5fSWarner Losh		end
404088b4f5fSWarner Losh	end
405088b4f5fSWarner Loshend
406088b4f5fSWarner Losh
407da9ab827SKyle Evansfunction menu.run()
408da9ab827SKyle Evans	if menu.skip() then
409da9ab827SKyle Evans		core.autoboot()
410da9ab827SKyle Evans		return
411da9ab827SKyle Evans	end
412da9ab827SKyle Evans
413beafe961SKyle Evans	menu.draw(menu.default)
414ca16d83fSKyle Evans	local autoboot_key = menu.autoboot()
415ca16d83fSKyle Evans
416ca16d83fSKyle Evans	menu.process(menu.default, autoboot_key)
417beafe961SKyle Evans	drawn_menu = nil
418da9ab827SKyle Evans
419da9ab827SKyle Evans	screen.defcursor()
420da9ab827SKyle Evans	print("Exiting menu!")
421088b4f5fSWarner Loshend
422088b4f5fSWarner Losh
423088b4f5fSWarner Loshfunction menu.skip()
4249f71d421SKyle Evans	if core.isSerialBoot() then
425aedd6be5SKyle Evans		return true
426088b4f5fSWarner Losh	end
427aedd6be5SKyle Evans	local c = string.lower(loader.getenv("console") or "")
4289f71d421SKyle Evans	if c:match("^efi[ ;]") ~= nil or c:match("[ ;]efi[ ;]") ~= nil then
429aedd6be5SKyle Evans		return true
430088b4f5fSWarner Losh	end
431088b4f5fSWarner Losh
432aedd6be5SKyle Evans	c = string.lower(loader.getenv("beastie_disable") or "")
433aedd6be5SKyle Evans	print("beastie_disable", c)
434aedd6be5SKyle Evans	return c == "yes"
435088b4f5fSWarner Loshend
436088b4f5fSWarner Losh
437088b4f5fSWarner Loshfunction menu.autoboot()
438aedd6be5SKyle Evans	local ab = loader.getenv("autoboot_delay")
4399f71d421SKyle Evans	if ab ~= nil and ab:lower() == "no" then
44012b95c84SKyle Evans		return nil
4419f71d421SKyle Evans	elseif tonumber(ab) == -1 then
442aedd6be5SKyle Evans		core.boot()
443088b4f5fSWarner Losh	end
444aedd6be5SKyle Evans	ab = tonumber(ab) or 10
445088b4f5fSWarner Losh
446aedd6be5SKyle Evans	local x = loader.getenv("loader_menu_timeout_x") or 5
447aedd6be5SKyle Evans	local y = loader.getenv("loader_menu_timeout_y") or 22
448088b4f5fSWarner Losh
449aedd6be5SKyle Evans	local endtime = loader.time() + ab
450aedd6be5SKyle Evans	local time
451088b4f5fSWarner Losh
452088b4f5fSWarner Losh	repeat
453aedd6be5SKyle Evans		time = endtime - loader.time()
454aedd6be5SKyle Evans		screen.setcursor(x, y)
45557099121SKyle Evans		print("Autoboot in " .. time ..
45657099121SKyle Evans		    " seconds, hit [Enter] to boot" ..
457aedd6be5SKyle Evans		    " or any other key to stop     ")
458aedd6be5SKyle Evans		screen.defcursor()
4599f71d421SKyle Evans		if io.ischar() then
460aedd6be5SKyle Evans			local ch = io.getchar()
4619f71d421SKyle Evans			if ch == core.KEY_ENTER then
462aedd6be5SKyle Evans				break
463088b4f5fSWarner Losh			else
464088b4f5fSWarner Losh				-- erase autoboot msg
465aedd6be5SKyle Evans				screen.setcursor(0, y)
46666964bbcSKyle Evans				print(string.rep(" ", 80))
467aedd6be5SKyle Evans				screen.defcursor()
46812b95c84SKyle Evans				return ch
469088b4f5fSWarner Losh			end
470088b4f5fSWarner Losh		end
471088b4f5fSWarner Losh
472aedd6be5SKyle Evans		loader.delay(50000)
473aedd6be5SKyle Evans	until time <= 0
474aedd6be5SKyle Evans	core.boot()
475088b4f5fSWarner Losh
476088b4f5fSWarner Loshend
477088b4f5fSWarner Losh
478aedd6be5SKyle Evansreturn menu
479