xref: /freebsd/stand/lua/menu.lua (revision beafe961479d4c7380e3c0dab4b18bcf60d29255)
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
41*beafe961SKyle Evanslocal drawn_menu
42ca16d83fSKyle Evans
439ed6f9efSKyle Evanslocal function OnOff(str, b)
449f71d421SKyle Evans	if b 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
350*beafe961SKyle Evansfunction menu.draw(m)
351*beafe961SKyle Evans	-- Clear the screen, reset the cursor, then draw
352aedd6be5SKyle Evans	screen.clear()
353aedd6be5SKyle Evans	screen.defcursor()
35428384160SKyle Evans	menu.current_alias_table = drawer.drawscreen(m)
355*beafe961SKyle Evans	drawn_menu = m
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.
360ca16d83fSKyle Evansfunction menu.process(m, keypress)
36128384160SKyle Evans	assert(m ~= nil)
36228384160SKyle Evans
363*beafe961SKyle Evans	if drawn_menu ~= m then
364*beafe961SKyle Evans		menu.draw(m)
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
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
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
3928d415029SKyle Evans			-- Get menu handler
393aedd6be5SKyle Evans			local handler = menu.handlers[sel_entry.entry_type]
3949f71d421SKyle Evans			if handler ~= nil then
395da9ab827SKyle Evans				-- The handler's return value indicates if we
396da9ab827SKyle Evans				-- need to exit this menu.  An omitted or true
397da9ab827SKyle Evans				-- return value means to continue.
398da9ab827SKyle Evans				if handler(m, sel_entry) == false then
399da9ab827SKyle Evans					return
400aefcaa7eSKyle Evans				end
401088b4f5fSWarner Losh			end
40228384160SKyle Evans			-- If we got an alias key the screen is out of date...
40328384160SKyle Evans			-- redraw it.
404*beafe961SKyle Evans			menu.draw(m)
405088b4f5fSWarner Losh		end
406088b4f5fSWarner Losh	end
407088b4f5fSWarner Loshend
408088b4f5fSWarner Losh
409da9ab827SKyle Evansfunction menu.run()
410da9ab827SKyle Evans	if menu.skip() then
411da9ab827SKyle Evans		core.autoboot()
412da9ab827SKyle Evans		return
413da9ab827SKyle Evans	end
414da9ab827SKyle Evans
415*beafe961SKyle Evans	menu.draw(menu.default)
416ca16d83fSKyle Evans	local autoboot_key = menu.autoboot()
417ca16d83fSKyle Evans
418ca16d83fSKyle Evans	menu.process(menu.default, autoboot_key)
419*beafe961SKyle Evans	drawn_menu = nil
420da9ab827SKyle Evans
421da9ab827SKyle Evans	screen.defcursor()
422da9ab827SKyle Evans	print("Exiting menu!")
423088b4f5fSWarner Loshend
424088b4f5fSWarner Losh
425088b4f5fSWarner Loshfunction menu.skip()
4269f71d421SKyle Evans	if core.isSerialBoot() then
427aedd6be5SKyle Evans		return true
428088b4f5fSWarner Losh	end
429aedd6be5SKyle Evans	local c = string.lower(loader.getenv("console") or "")
4309f71d421SKyle Evans	if c:match("^efi[ ;]") ~= nil or c:match("[ ;]efi[ ;]") ~= nil then
431aedd6be5SKyle Evans		return true
432088b4f5fSWarner Losh	end
433088b4f5fSWarner Losh
434aedd6be5SKyle Evans	c = string.lower(loader.getenv("beastie_disable") or "")
435aedd6be5SKyle Evans	print("beastie_disable", c)
436aedd6be5SKyle Evans	return c == "yes"
437088b4f5fSWarner Loshend
438088b4f5fSWarner Losh
439088b4f5fSWarner Loshfunction menu.autoboot()
440aedd6be5SKyle Evans	local ab = loader.getenv("autoboot_delay")
4419f71d421SKyle Evans	if ab ~= nil and ab:lower() == "no" then
44212b95c84SKyle Evans		return nil
4439f71d421SKyle Evans	elseif tonumber(ab) == -1 then
444aedd6be5SKyle Evans		core.boot()
445088b4f5fSWarner Losh	end
446aedd6be5SKyle Evans	ab = tonumber(ab) or 10
447088b4f5fSWarner Losh
448aedd6be5SKyle Evans	local x = loader.getenv("loader_menu_timeout_x") or 5
449aedd6be5SKyle Evans	local y = loader.getenv("loader_menu_timeout_y") or 22
450088b4f5fSWarner Losh
451aedd6be5SKyle Evans	local endtime = loader.time() + ab
452aedd6be5SKyle Evans	local time
453088b4f5fSWarner Losh
454088b4f5fSWarner Losh	repeat
455aedd6be5SKyle Evans		time = endtime - loader.time()
456aedd6be5SKyle Evans		screen.setcursor(x, y)
45757099121SKyle Evans		print("Autoboot in " .. time ..
45857099121SKyle Evans		    " seconds, hit [Enter] to boot" ..
459aedd6be5SKyle Evans		    " or any other key to stop     ")
460aedd6be5SKyle Evans		screen.defcursor()
4619f71d421SKyle Evans		if io.ischar() then
462aedd6be5SKyle Evans			local ch = io.getchar()
4639f71d421SKyle Evans			if ch == core.KEY_ENTER then
464aedd6be5SKyle Evans				break
465088b4f5fSWarner Losh			else
466088b4f5fSWarner Losh				-- erase autoboot msg
467aedd6be5SKyle Evans				screen.setcursor(0, y)
46866964bbcSKyle Evans				print(string.rep(" ", 80))
469aedd6be5SKyle Evans				screen.defcursor()
47012b95c84SKyle Evans				return ch
471088b4f5fSWarner Losh			end
472088b4f5fSWarner Losh		end
473088b4f5fSWarner Losh
474aedd6be5SKyle Evans		loader.delay(50000)
475aedd6be5SKyle Evans	until time <= 0
476aedd6be5SKyle Evans	core.boot()
477088b4f5fSWarner Losh
478088b4f5fSWarner Loshend
479088b4f5fSWarner Losh
480aedd6be5SKyle Evansreturn menu
481