xref: /freebsd/stand/lua/menu.lua (revision 9a28f948ee29bfea13c8f128383acc06b2819aeb)
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
39aedd6be5SKyle Evanslocal skip
40aedd6be5SKyle Evanslocal run
41aedd6be5SKyle Evanslocal autoboot
42088b4f5fSWarner Losh
43e15abd1fSKyle Evanslocal OnOff = function(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
53b5746545SKyle Evans-- Module exports
548d415029SKyle Evansmenu.handlers = {
558d415029SKyle Evans	-- Menu handlers take the current menu and selected entry as parameters,
568d415029SKyle Evans	-- and should return a boolean indicating whether execution should
578d415029SKyle Evans	-- continue or not. The return value may be omitted if this entry should
588d415029SKyle Evans	-- have no bearing on whether we continue or not, indicating that we
598d415029SKyle Evans	-- should just continue after execution.
608d415029SKyle Evans	[core.MENU_ENTRY] = function(current_menu, entry)
618d415029SKyle Evans		-- run function
62aedd6be5SKyle Evans		entry.func()
638d415029SKyle Evans	end,
648d415029SKyle Evans	[core.MENU_CAROUSEL_ENTRY] = function(current_menu, entry)
658d415029SKyle Evans		-- carousel (rotating) functionality
66aedd6be5SKyle Evans		local carid = entry.carousel_id
67aedd6be5SKyle Evans		local caridx = config.getCarouselIndex(carid)
68aedd6be5SKyle Evans		local choices = entry.items()
698d415029SKyle Evans
709f71d421SKyle Evans		if #choices > 0 then
71aedd6be5SKyle Evans			caridx = (caridx % #choices) + 1
72aedd6be5SKyle Evans			config.setCarouselIndex(carid, caridx)
73aedd6be5SKyle Evans			entry.func(caridx, choices[caridx], choices)
748d415029SKyle Evans		end
758d415029SKyle Evans	end,
768d415029SKyle Evans	[core.MENU_SUBMENU] = function(current_menu, entry)
778d415029SKyle Evans		-- recurse
78*9a28f948SKyle Evans		return menu.run(entry.submenu)
798d415029SKyle Evans	end,
808d415029SKyle Evans	[core.MENU_RETURN] = function(current_menu, entry)
818d415029SKyle Evans		-- allow entry to have a function/side effect
829f71d421SKyle Evans		if entry.func ~= nil then
83aedd6be5SKyle Evans			entry.func()
848d415029SKyle Evans		end
85aedd6be5SKyle Evans		return false
868d415029SKyle Evans	end,
87aedd6be5SKyle Evans}
88280e990bSKyle Evans-- loader menu tree is rooted at menu.welcome
89088b4f5fSWarner Losh
90088b4f5fSWarner Loshmenu.boot_options = {
91d8757746SKyle Evans	entries = {
92088b4f5fSWarner Losh		-- return to welcome menu
93088b4f5fSWarner Losh		{
94a7cf0562SKyle Evans			entry_type = core.MENU_RETURN,
95088b4f5fSWarner Losh			name = function()
9657099121SKyle Evans				return "Back to main menu" ..
97aedd6be5SKyle Evans				    color.highlight(" [Backspace]")
981666dfc0SKyle Evans			end
99088b4f5fSWarner Losh		},
100088b4f5fSWarner Losh
101088b4f5fSWarner Losh		-- load defaults
102088b4f5fSWarner Losh		{
103a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
104088b4f5fSWarner Losh			name = function()
10557099121SKyle Evans				return "Load System " .. color.highlight("D") ..
106aedd6be5SKyle Evans				    "efaults"
107088b4f5fSWarner Losh			end,
108088b4f5fSWarner Losh			func = function()
109aedd6be5SKyle Evans				core.setDefaults()
110088b4f5fSWarner Losh			end,
111088b4f5fSWarner Losh			alias = {"d", "D"}
112088b4f5fSWarner Losh		},
113088b4f5fSWarner Losh
114088b4f5fSWarner Losh		{
115a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
116088b4f5fSWarner Losh		},
117088b4f5fSWarner Losh
118088b4f5fSWarner Losh		{
119a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
120088b4f5fSWarner Losh			name = function()
121aedd6be5SKyle Evans				return "Boot Options:"
122088b4f5fSWarner Losh			end
123088b4f5fSWarner Losh		},
124088b4f5fSWarner Losh
125088b4f5fSWarner Losh		-- acpi
126088b4f5fSWarner Losh		{
127a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
128c1ab36f5SKyle Evans			visible = core.isSystem386,
129088b4f5fSWarner Losh			name = function()
130fd2b19b3SKyle Evans				return OnOff(color.highlight("A") ..
131aedd6be5SKyle Evans				    "CPI       :", core.acpi)
132088b4f5fSWarner Losh			end,
133088b4f5fSWarner Losh			func = function()
134aedd6be5SKyle Evans				core.setACPI()
135088b4f5fSWarner Losh			end,
136088b4f5fSWarner Losh			alias = {"a", "A"}
137088b4f5fSWarner Losh		},
138088b4f5fSWarner Losh		-- safe mode
139088b4f5fSWarner Losh		{
140a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
141088b4f5fSWarner Losh			name = function()
14257099121SKyle Evans				return OnOff("Safe " .. color.highlight("M") ..
143aedd6be5SKyle Evans				    "ode  :", core.sm)
144088b4f5fSWarner Losh			end,
145088b4f5fSWarner Losh			func = function()
146aedd6be5SKyle Evans				core.setSafeMode()
147088b4f5fSWarner Losh			end,
148088b4f5fSWarner Losh			alias = {"m", "M"}
149088b4f5fSWarner Losh		},
150088b4f5fSWarner Losh		-- single user
151088b4f5fSWarner Losh		{
152a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
153088b4f5fSWarner Losh			name = function()
154fd2b19b3SKyle Evans				return OnOff(color.highlight("S") ..
155aedd6be5SKyle Evans				    "ingle user:", core.su)
156088b4f5fSWarner Losh			end,
157088b4f5fSWarner Losh			func = function()
158aedd6be5SKyle Evans				core.setSingleUser()
159088b4f5fSWarner Losh			end,
160088b4f5fSWarner Losh			alias = {"s", "S"}
161088b4f5fSWarner Losh		},
162088b4f5fSWarner Losh		-- verbose boot
163088b4f5fSWarner Losh		{
164a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
165088b4f5fSWarner Losh			name = function()
166fd2b19b3SKyle Evans				return OnOff(color.highlight("V") ..
167aedd6be5SKyle Evans				    "erbose    :", core.verbose)
168088b4f5fSWarner Losh			end,
169088b4f5fSWarner Losh			func = function()
170aedd6be5SKyle Evans				core.setVerbose()
171088b4f5fSWarner Losh			end,
172088b4f5fSWarner Losh			alias = {"v", "V"}
173088b4f5fSWarner Losh		},
174d8757746SKyle Evans	},
175aedd6be5SKyle Evans}
176088b4f5fSWarner Losh
177088b4f5fSWarner Loshmenu.welcome = {
178303253e5SKyle Evans	entries = function()
179aedd6be5SKyle Evans		local menu_entries = menu.welcome.all_entries
180303253e5SKyle Evans		-- Swap the first two menu items on single user boot
1819f71d421SKyle Evans		if core.isSingleUserBoot() then
1829a0904b0SKyle Evans			-- We'll cache the swapped menu, for performance
1839f71d421SKyle Evans			if menu.welcome.swapped_menu ~= nil then
184aedd6be5SKyle Evans				return menu.welcome.swapped_menu
1859a0904b0SKyle Evans			end
1865c1b5165SKyle Evans			-- Shallow copy the table
187aedd6be5SKyle Evans			menu_entries = core.shallowCopyTable(menu_entries)
1885c1b5165SKyle Evans
1899a0904b0SKyle Evans			-- Swap the first two menu entries
1904b6da14cSKyle Evans			menu_entries[1], menu_entries[2] =
191aedd6be5SKyle Evans			    menu_entries[2], menu_entries[1]
192303253e5SKyle Evans
1939a0904b0SKyle Evans			-- Then set their names to their alternate names
1949a0904b0SKyle Evans			menu_entries[1].name, menu_entries[2].name =
1959a0904b0SKyle Evans			    menu_entries[1].alternate_name,
196aedd6be5SKyle Evans			    menu_entries[2].alternate_name
197aedd6be5SKyle Evans			menu.welcome.swapped_menu = menu_entries
198303253e5SKyle Evans		end
199aedd6be5SKyle Evans		return menu_entries
200303253e5SKyle Evans	end,
201303253e5SKyle Evans	all_entries = {
202088b4f5fSWarner Losh		-- boot multi user
203088b4f5fSWarner Losh		{
204a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
205088b4f5fSWarner Losh			name = function()
206fd2b19b3SKyle Evans				return color.highlight("B") ..
207fd2b19b3SKyle Evans				    "oot Multi user " ..
208aedd6be5SKyle Evans				    color.highlight("[Enter]")
209088b4f5fSWarner Losh			end,
2105c1b5165SKyle Evans			-- Not a standard menu entry function!
2115c1b5165SKyle Evans			alternate_name = function()
2125c1b5165SKyle Evans				return color.highlight("B") ..
213aedd6be5SKyle Evans				    "oot Multi user"
2145c1b5165SKyle Evans			end,
215088b4f5fSWarner Losh			func = function()
216aedd6be5SKyle Evans				core.setSingleUser(false)
217aedd6be5SKyle Evans				core.boot()
218088b4f5fSWarner Losh			end,
219b458bf0dSKyle Evans			alias = {"b", "B"}
220088b4f5fSWarner Losh		},
221088b4f5fSWarner Losh
222088b4f5fSWarner Losh		-- boot single user
223088b4f5fSWarner Losh		{
224a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
225088b4f5fSWarner Losh			name = function()
226fd2b19b3SKyle Evans				return "Boot " .. color.highlight("S") ..
227aedd6be5SKyle Evans				    "ingle user"
228088b4f5fSWarner Losh			end,
2295c1b5165SKyle Evans			-- Not a standard menu entry function!
2305c1b5165SKyle Evans			alternate_name = function()
2315c1b5165SKyle Evans				return "Boot " .. color.highlight("S") ..
232aedd6be5SKyle Evans				    "ingle user " .. color.highlight("[Enter]")
2335c1b5165SKyle Evans			end,
234088b4f5fSWarner Losh			func = function()
235aedd6be5SKyle Evans				core.setSingleUser(true)
236aedd6be5SKyle Evans				core.boot()
237088b4f5fSWarner Losh			end,
238088b4f5fSWarner Losh			alias = {"s", "S"}
239088b4f5fSWarner Losh		},
240088b4f5fSWarner Losh
241088b4f5fSWarner Losh		-- escape to interpreter
242088b4f5fSWarner Losh		{
243a7cf0562SKyle Evans			entry_type = core.MENU_RETURN,
244088b4f5fSWarner Losh			name = function()
245fd2b19b3SKyle Evans				return color.highlight("Esc") ..
246aedd6be5SKyle Evans				    "ape to loader prompt"
247088b4f5fSWarner Losh			end,
248ef625845SKyle Evans			func = function()
249aedd6be5SKyle Evans				loader.setenv("autoboot_delay", "NO")
250ef625845SKyle Evans			end,
25139006570SKyle Evans			alias = {core.KEYSTR_ESCAPE}
252088b4f5fSWarner Losh		},
253088b4f5fSWarner Losh
254088b4f5fSWarner Losh		-- reboot
255088b4f5fSWarner Losh		{
256a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
257088b4f5fSWarner Losh			name = function()
258aedd6be5SKyle Evans				return color.highlight("R") .. "eboot"
259088b4f5fSWarner Losh			end,
260088b4f5fSWarner Losh			func = function()
261aedd6be5SKyle Evans				loader.perform("reboot")
262088b4f5fSWarner Losh			end,
263088b4f5fSWarner Losh			alias = {"r", "R"}
264088b4f5fSWarner Losh		},
265088b4f5fSWarner Losh
266088b4f5fSWarner Losh
267088b4f5fSWarner Losh		{
268a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
269088b4f5fSWarner Losh		},
270088b4f5fSWarner Losh
271088b4f5fSWarner Losh		{
272a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
273088b4f5fSWarner Losh			name = function()
274aedd6be5SKyle Evans				return "Options:"
275088b4f5fSWarner Losh			end
276088b4f5fSWarner Losh		},
277088b4f5fSWarner Losh
278088b4f5fSWarner Losh		-- kernel options
279088b4f5fSWarner Losh		{
280a7cf0562SKyle Evans			entry_type = core.MENU_CAROUSEL_ENTRY,
281ada26c4aSKyle Evans			carousel_id = "kernel",
282ada26c4aSKyle Evans			items = core.kernelList,
283ada26c4aSKyle Evans			name = function(idx, choice, all_choices)
2849f71d421SKyle Evans				if #all_choices == 0 then
285aedd6be5SKyle Evans					return "Kernel: "
286088b4f5fSWarner Losh				end
287b1b1f2b8SKyle Evans
288aedd6be5SKyle Evans				local is_default = (idx == 1)
289aedd6be5SKyle Evans				local kernel_name = ""
290aedd6be5SKyle Evans				local name_color
2919f71d421SKyle Evans				if is_default then
292aedd6be5SKyle Evans					name_color = color.escapef(color.GREEN)
293aedd6be5SKyle Evans					kernel_name = "default/"
294bcf48a15SKyle Evans				else
295aedd6be5SKyle Evans					name_color = color.escapef(color.BLUE)
296b1b1f2b8SKyle Evans				end
297fd2b19b3SKyle Evans				kernel_name = kernel_name .. name_color ..
298aedd6be5SKyle Evans				    choice .. color.default()
299fd2b19b3SKyle Evans				return color.highlight("K") .. "ernel: " ..
300fd2b19b3SKyle Evans				    kernel_name .. " (" .. idx .. " of " ..
301aedd6be5SKyle Evans				    #all_choices .. ")"
302088b4f5fSWarner Losh			end,
3035d1e2f83SKyle Evans			func = function(idx, choice, all_choices)
304aedd6be5SKyle Evans				config.selectkernel(choice)
305088b4f5fSWarner Losh			end,
306088b4f5fSWarner Losh			alias = {"k", "K"}
307088b4f5fSWarner Losh		},
308088b4f5fSWarner Losh
309088b4f5fSWarner Losh		-- boot options
310088b4f5fSWarner Losh		{
311a7cf0562SKyle Evans			entry_type = core.MENU_SUBMENU,
312088b4f5fSWarner Losh			name = function()
313fd2b19b3SKyle Evans				return "Boot " .. color.highlight("O") ..
314aedd6be5SKyle Evans				    "ptions"
315088b4f5fSWarner Losh			end,
316*9a28f948SKyle Evans			submenu = menu.boot_options,
317088b4f5fSWarner Losh			alias = {"o", "O"}
318d8757746SKyle Evans		},
319d8757746SKyle Evans	},
320aedd6be5SKyle Evans}
321088b4f5fSWarner Losh
32220a81676SKyle Evansmenu.default = menu.welcome
32320a81676SKyle Evans
324088b4f5fSWarner Loshfunction menu.run(m)
325088b4f5fSWarner Losh
3269f71d421SKyle Evans	if menu.skip() then
327aedd6be5SKyle Evans		core.autoboot()
328aedd6be5SKyle Evans		return false
329088b4f5fSWarner Losh	end
330088b4f5fSWarner Losh
3319f71d421SKyle Evans	if m == nil then
33220a81676SKyle Evans		m = menu.default
333088b4f5fSWarner Losh	end
334088b4f5fSWarner Losh
335088b4f5fSWarner Losh	-- redraw screen
336aedd6be5SKyle Evans	screen.clear()
337aedd6be5SKyle Evans	screen.defcursor()
338aedd6be5SKyle Evans	local alias_table = drawer.drawscreen(m)
339088b4f5fSWarner Losh
340aedd6be5SKyle Evans	menu.autoboot()
341088b4f5fSWarner Losh
342aedd6be5SKyle Evans	cont = true
3439f71d421SKyle Evans	while cont do
344aedd6be5SKyle Evans		local key = io.getchar()
345088b4f5fSWarner Losh
346b458bf0dSKyle Evans		-- Special key behaviors
3479f71d421SKyle Evans		if (key == core.KEY_BACKSPACE or key == core.KEY_DELETE) and
34820a81676SKyle Evans		    m ~= menu.default then
349aedd6be5SKyle Evans			break
3509f71d421SKyle Evans		elseif key == core.KEY_ENTER then
351aedd6be5SKyle Evans			core.boot()
352b458bf0dSKyle Evans			-- Should not return
353abc4f7e7SKyle Evans		end
354abc4f7e7SKyle Evans
355abc4f7e7SKyle Evans		key = string.char(key)
356088b4f5fSWarner Losh		-- check to see if key is an alias
357aedd6be5SKyle Evans		local sel_entry = nil
358088b4f5fSWarner Losh		for k, v in pairs(alias_table) do
3599f71d421SKyle Evans			if key == k then
360aedd6be5SKyle Evans				sel_entry = v
361088b4f5fSWarner Losh			end
362088b4f5fSWarner Losh		end
363088b4f5fSWarner Losh
364088b4f5fSWarner Losh		-- if we have an alias do the assigned action:
3659f71d421SKyle Evans		if sel_entry ~= nil then
3668d415029SKyle Evans			-- Get menu handler
367aedd6be5SKyle Evans			local handler = menu.handlers[sel_entry.entry_type]
3689f71d421SKyle Evans			if handler ~= nil then
3698d415029SKyle Evans				-- The handler's return value indicates whether
3708d415029SKyle Evans				-- we need to exit this menu. An omitted return
3718d415029SKyle Evans				-- value means "continue" by default.
372aedd6be5SKyle Evans				cont = handler(m, sel_entry)
3739f71d421SKyle Evans				if cont == nil then
374aedd6be5SKyle Evans					cont = true
375aefcaa7eSKyle Evans				end
376088b4f5fSWarner Losh			end
377088b4f5fSWarner Losh			-- if we got an alias key the screen is out of date:
378aedd6be5SKyle Evans			screen.clear()
379aedd6be5SKyle Evans			screen.defcursor()
380aedd6be5SKyle Evans			alias_table = drawer.drawscreen(m)
381088b4f5fSWarner Losh		end
382088b4f5fSWarner Losh	end
383088b4f5fSWarner Losh
38420a81676SKyle Evans	if m == menu.default then
385aedd6be5SKyle Evans		screen.defcursor()
386aedd6be5SKyle Evans		print("Exiting menu!")
387aedd6be5SKyle Evans		return false
388088b4f5fSWarner Losh	end
389088b4f5fSWarner Losh
390aedd6be5SKyle Evans	return true
391088b4f5fSWarner Loshend
392088b4f5fSWarner Losh
393088b4f5fSWarner Loshfunction menu.skip()
3949f71d421SKyle Evans	if core.isSerialBoot() then
395aedd6be5SKyle Evans		return true
396088b4f5fSWarner Losh	end
397aedd6be5SKyle Evans	local c = string.lower(loader.getenv("console") or "")
3989f71d421SKyle Evans	if c:match("^efi[ ;]") ~= nil or c:match("[ ;]efi[ ;]") ~= nil then
399aedd6be5SKyle Evans		return true
400088b4f5fSWarner Losh	end
401088b4f5fSWarner Losh
402aedd6be5SKyle Evans	c = string.lower(loader.getenv("beastie_disable") or "")
403aedd6be5SKyle Evans	print("beastie_disable", c)
404aedd6be5SKyle Evans	return c == "yes"
405088b4f5fSWarner Loshend
406088b4f5fSWarner Losh
407088b4f5fSWarner Loshfunction menu.autoboot()
40849550489SKyle Evans	if menu.already_autoboot then
409aedd6be5SKyle Evans		return
410088b4f5fSWarner Losh	end
411aedd6be5SKyle Evans	menu.already_autoboot = true
412088b4f5fSWarner Losh
413aedd6be5SKyle Evans	local ab = loader.getenv("autoboot_delay")
4149f71d421SKyle Evans	if ab ~= nil and ab:lower() == "no" then
415aedd6be5SKyle Evans		return
4169f71d421SKyle Evans	elseif tonumber(ab) == -1 then
417aedd6be5SKyle Evans		core.boot()
418088b4f5fSWarner Losh	end
419aedd6be5SKyle Evans	ab = tonumber(ab) or 10
420088b4f5fSWarner Losh
421aedd6be5SKyle Evans	local x = loader.getenv("loader_menu_timeout_x") or 5
422aedd6be5SKyle Evans	local y = loader.getenv("loader_menu_timeout_y") or 22
423088b4f5fSWarner Losh
424aedd6be5SKyle Evans	local endtime = loader.time() + ab
425aedd6be5SKyle Evans	local time
426088b4f5fSWarner Losh
427088b4f5fSWarner Losh	repeat
428aedd6be5SKyle Evans		time = endtime - loader.time()
429aedd6be5SKyle Evans		screen.setcursor(x, y)
43057099121SKyle Evans		print("Autoboot in " .. time ..
43157099121SKyle Evans		    " seconds, hit [Enter] to boot" ..
432aedd6be5SKyle Evans		    " or any other key to stop     ")
433aedd6be5SKyle Evans		screen.defcursor()
4349f71d421SKyle Evans		if io.ischar() then
435aedd6be5SKyle Evans			local ch = io.getchar()
4369f71d421SKyle Evans			if ch == core.KEY_ENTER then
437aedd6be5SKyle Evans				break
438088b4f5fSWarner Losh			else
439088b4f5fSWarner Losh				-- erase autoboot msg
440aedd6be5SKyle Evans				screen.setcursor(0, y)
441088b4f5fSWarner Losh				print("                                        "
442aedd6be5SKyle Evans				    .. "                                        ")
443aedd6be5SKyle Evans				screen.defcursor()
444aedd6be5SKyle Evans				return
445088b4f5fSWarner Losh			end
446088b4f5fSWarner Losh		end
447088b4f5fSWarner Losh
448aedd6be5SKyle Evans		loader.delay(50000)
449aedd6be5SKyle Evans	until time <= 0
450aedd6be5SKyle Evans	core.boot()
451088b4f5fSWarner Losh
452088b4f5fSWarner Loshend
453088b4f5fSWarner Losh
454aedd6be5SKyle Evansreturn menu
455