xref: /freebsd/stand/lua/menu.lua (revision 8d415029e18f7364a1f05208031384fca6cade8d)
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
31088b4f5fSWarner Loshlocal core = require("core");
32088b4f5fSWarner Loshlocal color = require("color");
33088b4f5fSWarner Loshlocal config = require("config");
34088b4f5fSWarner Loshlocal screen = require("screen");
35088b4f5fSWarner Loshlocal drawer = require("drawer");
36088b4f5fSWarner Losh
37c8518398SKyle Evanslocal menu = {};
38c8518398SKyle Evans
39088b4f5fSWarner Loshlocal OnOff;
40088b4f5fSWarner Loshlocal skip;
41088b4f5fSWarner Loshlocal run;
42088b4f5fSWarner Loshlocal autoboot;
43ada26c4aSKyle Evanslocal carousel_choices = {};
44088b4f5fSWarner Losh
45*8d415029SKyle Evansmenu.handlers = {
46*8d415029SKyle Evans	-- Menu handlers take the current menu and selected entry as parameters,
47*8d415029SKyle Evans	-- and should return a boolean indicating whether execution should
48*8d415029SKyle Evans	-- continue or not. The return value may be omitted if this entry should
49*8d415029SKyle Evans	-- have no bearing on whether we continue or not, indicating that we
50*8d415029SKyle Evans	-- should just continue after execution.
51*8d415029SKyle Evans	[core.MENU_ENTRY] = function(current_menu, entry)
52*8d415029SKyle Evans		-- run function
53*8d415029SKyle Evans		entry.func();
54*8d415029SKyle Evans	end,
55*8d415029SKyle Evans	[core.MENU_CAROUSEL_ENTRY] = function(current_menu, entry)
56*8d415029SKyle Evans		-- carousel (rotating) functionality
57*8d415029SKyle Evans		local carid = entry.carousel_id;
58*8d415029SKyle Evans		local caridx = menu.getCarouselIndex(carid);
59*8d415029SKyle Evans		local choices = entry.items();
60*8d415029SKyle Evans
61*8d415029SKyle Evans		if (#choices > 0) then
62*8d415029SKyle Evans			caridx = (caridx % #choices) + 1;
63*8d415029SKyle Evans			menu.setCarouselIndex(carid, caridx);
64*8d415029SKyle Evans			entry.func(caridx, choices[caridx], choices);
65*8d415029SKyle Evans		end
66*8d415029SKyle Evans	end,
67*8d415029SKyle Evans	[core.MENU_SUBMENU] = function(current_menu, entry)
68*8d415029SKyle Evans		-- recurse
69*8d415029SKyle Evans		return menu.run(entry.submenu());
70*8d415029SKyle Evans	end,
71*8d415029SKyle Evans	[core.MENU_RETURN] = function(current_menu, entry)
72*8d415029SKyle Evans		-- allow entry to have a function/side effect
73*8d415029SKyle Evans		if (entry.func ~= nil) then
74*8d415029SKyle Evans			entry.func();
75*8d415029SKyle Evans		end
76*8d415029SKyle Evans		return false;
77*8d415029SKyle Evans	end,
78*8d415029SKyle Evans};
79280e990bSKyle Evans-- loader menu tree is rooted at menu.welcome
80088b4f5fSWarner Losh
81088b4f5fSWarner Loshmenu.boot_options = {
82d8757746SKyle Evans	entries = {
83088b4f5fSWarner Losh		-- return to welcome menu
84088b4f5fSWarner Losh		{
85a7cf0562SKyle Evans			entry_type = core.MENU_RETURN,
86088b4f5fSWarner Losh			name = function()
8757099121SKyle Evans				return "Back to main menu" ..
8857099121SKyle Evans				    color.highlight(" [Backspace]");
891666dfc0SKyle Evans			end
90088b4f5fSWarner Losh		},
91088b4f5fSWarner Losh
92088b4f5fSWarner Losh		-- load defaults
93088b4f5fSWarner Losh		{
94a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
95088b4f5fSWarner Losh			name = function()
9657099121SKyle Evans				return "Load System " .. color.highlight("D") ..
9757099121SKyle Evans				    "efaults";
98088b4f5fSWarner Losh			end,
99088b4f5fSWarner Losh			func = function()
10024a1bd54SKyle Evans				core.setDefaults();
101088b4f5fSWarner Losh			end,
102088b4f5fSWarner Losh			alias = {"d", "D"}
103088b4f5fSWarner Losh		},
104088b4f5fSWarner Losh
105088b4f5fSWarner Losh		{
106a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
107088b4f5fSWarner Losh			name = function()
108088b4f5fSWarner Losh				return "";
109088b4f5fSWarner Losh			end
110088b4f5fSWarner Losh		},
111088b4f5fSWarner Losh
112088b4f5fSWarner Losh		{
113a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
114088b4f5fSWarner Losh			name = function()
115088b4f5fSWarner Losh				return "Boot Options:";
116088b4f5fSWarner Losh			end
117088b4f5fSWarner Losh		},
118088b4f5fSWarner Losh
119088b4f5fSWarner Losh		-- acpi
120088b4f5fSWarner Losh		{
121a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
122088b4f5fSWarner Losh			name = function()
123fd2b19b3SKyle Evans				return OnOff(color.highlight("A") ..
124fd2b19b3SKyle Evans				    "CPI       :", core.acpi);
125088b4f5fSWarner Losh			end,
126088b4f5fSWarner Losh			func = function()
127088b4f5fSWarner Losh				core.setACPI();
128088b4f5fSWarner Losh			end,
129088b4f5fSWarner Losh			alias = {"a", "A"}
130088b4f5fSWarner Losh		},
131088b4f5fSWarner Losh		-- safe mode
132088b4f5fSWarner Losh		{
133a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
134088b4f5fSWarner Losh			name = function()
13557099121SKyle Evans				return OnOff("Safe " .. color.highlight("M") ..
13657099121SKyle Evans				    "ode  :", core.sm);
137088b4f5fSWarner Losh			end,
138088b4f5fSWarner Losh			func = function()
139088b4f5fSWarner Losh				core.setSafeMode();
140088b4f5fSWarner Losh			end,
141088b4f5fSWarner Losh			alias = {"m", "M"}
142088b4f5fSWarner Losh		},
143088b4f5fSWarner Losh		-- single user
144088b4f5fSWarner Losh		{
145a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
146088b4f5fSWarner Losh			name = function()
147fd2b19b3SKyle Evans				return OnOff(color.highlight("S") ..
148fd2b19b3SKyle Evans				    "ingle user:", core.su);
149088b4f5fSWarner Losh			end,
150088b4f5fSWarner Losh			func = function()
151088b4f5fSWarner Losh				core.setSingleUser();
152088b4f5fSWarner Losh			end,
153088b4f5fSWarner Losh			alias = {"s", "S"}
154088b4f5fSWarner Losh		},
155088b4f5fSWarner Losh		-- verbose boot
156088b4f5fSWarner Losh		{
157a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
158088b4f5fSWarner Losh			name = function()
159fd2b19b3SKyle Evans				return OnOff(color.highlight("V") ..
160fd2b19b3SKyle Evans				    "erbose    :", core.verbose);
161088b4f5fSWarner Losh			end,
162088b4f5fSWarner Losh			func = function()
163088b4f5fSWarner Losh				core.setVerbose();
164088b4f5fSWarner Losh			end,
165088b4f5fSWarner Losh			alias = {"v", "V"}
166088b4f5fSWarner Losh		},
167d8757746SKyle Evans	},
168088b4f5fSWarner Losh};
169088b4f5fSWarner Losh
170088b4f5fSWarner Loshmenu.welcome = {
171303253e5SKyle Evans	entries = function()
172303253e5SKyle Evans		local menu_entries = menu.welcome.all_entries;
173303253e5SKyle Evans		-- Swap the first two menu items on single user boot
174303253e5SKyle Evans		if (core.isSingleUserBoot()) then
1759a0904b0SKyle Evans			-- We'll cache the swapped menu, for performance
1769a0904b0SKyle Evans			if (menu.welcome.swapped_menu ~= nil) then
1779a0904b0SKyle Evans				return menu.welcome.swapped_menu;
1789a0904b0SKyle Evans			end
1795c1b5165SKyle Evans			-- Shallow copy the table
1805c1b5165SKyle Evans			menu_entries = core.shallowCopyTable(menu_entries);
1815c1b5165SKyle Evans
1829a0904b0SKyle Evans			-- Swap the first two menu entries
1834b6da14cSKyle Evans			menu_entries[1], menu_entries[2] =
1844b6da14cSKyle Evans			    menu_entries[2], menu_entries[1];
185303253e5SKyle Evans
1869a0904b0SKyle Evans			-- Then set their names to their alternate names
1879a0904b0SKyle Evans			menu_entries[1].name, menu_entries[2].name =
1889a0904b0SKyle Evans			    menu_entries[1].alternate_name,
1899a0904b0SKyle Evans			    menu_entries[2].alternate_name;
1909a0904b0SKyle Evans			menu.welcome.swapped_menu = menu_entries;
191303253e5SKyle Evans		end
192303253e5SKyle Evans		return menu_entries;
193303253e5SKyle Evans	end,
194303253e5SKyle Evans	all_entries = {
195088b4f5fSWarner Losh		-- boot multi user
196088b4f5fSWarner Losh		{
197a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
198088b4f5fSWarner Losh			name = function()
199fd2b19b3SKyle Evans				return color.highlight("B") ..
200fd2b19b3SKyle Evans				    "oot Multi user " ..
20157099121SKyle Evans				    color.highlight("[Enter]");
202088b4f5fSWarner Losh			end,
2035c1b5165SKyle Evans			-- Not a standard menu entry function!
2045c1b5165SKyle Evans			alternate_name = function()
2055c1b5165SKyle Evans				return color.highlight("B") ..
2065c1b5165SKyle Evans				    "oot Multi user";
2075c1b5165SKyle Evans			end,
208088b4f5fSWarner Losh			func = function()
209088b4f5fSWarner Losh				core.setSingleUser(false);
210088b4f5fSWarner Losh				core.boot();
211088b4f5fSWarner Losh			end,
212b458bf0dSKyle Evans			alias = {"b", "B"}
213088b4f5fSWarner Losh		},
214088b4f5fSWarner Losh
215088b4f5fSWarner Losh		-- boot single user
216088b4f5fSWarner Losh		{
217a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
218088b4f5fSWarner Losh			name = function()
219fd2b19b3SKyle Evans				return "Boot " .. color.highlight("S") ..
220fd2b19b3SKyle Evans				    "ingle user";
221088b4f5fSWarner Losh			end,
2225c1b5165SKyle Evans			-- Not a standard menu entry function!
2235c1b5165SKyle Evans			alternate_name = function()
2245c1b5165SKyle Evans				return "Boot " .. color.highlight("S") ..
2255c1b5165SKyle Evans				    "ingle user " .. color.highlight("[Enter]");
2265c1b5165SKyle Evans			end,
227088b4f5fSWarner Losh			func = function()
228088b4f5fSWarner Losh				core.setSingleUser(true);
229088b4f5fSWarner Losh				core.boot();
230088b4f5fSWarner Losh			end,
231088b4f5fSWarner Losh			alias = {"s", "S"}
232088b4f5fSWarner Losh		},
233088b4f5fSWarner Losh
234088b4f5fSWarner Losh		-- escape to interpreter
235088b4f5fSWarner Losh		{
236a7cf0562SKyle Evans			entry_type = core.MENU_RETURN,
237088b4f5fSWarner Losh			name = function()
238fd2b19b3SKyle Evans				return color.highlight("Esc") ..
239fd2b19b3SKyle Evans				    "ape to loader prompt";
240088b4f5fSWarner Losh			end,
241ef625845SKyle Evans			func = function()
24224a1bd54SKyle Evans				loader.setenv("autoboot_delay", "NO");
243ef625845SKyle Evans			end,
24439006570SKyle Evans			alias = {core.KEYSTR_ESCAPE}
245088b4f5fSWarner Losh		},
246088b4f5fSWarner Losh
247088b4f5fSWarner Losh		-- reboot
248088b4f5fSWarner Losh		{
249a7cf0562SKyle Evans			entry_type = core.MENU_ENTRY,
250088b4f5fSWarner Losh			name = function()
251088b4f5fSWarner Losh				return color.highlight("R") .. "eboot";
252088b4f5fSWarner Losh			end,
253088b4f5fSWarner Losh			func = function()
254088b4f5fSWarner Losh				loader.perform("reboot");
255088b4f5fSWarner Losh			end,
256088b4f5fSWarner Losh			alias = {"r", "R"}
257088b4f5fSWarner Losh		},
258088b4f5fSWarner Losh
259088b4f5fSWarner Losh
260088b4f5fSWarner Losh		{
261a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
262088b4f5fSWarner Losh			name = function()
263088b4f5fSWarner Losh				return "";
264088b4f5fSWarner Losh			end
265088b4f5fSWarner Losh		},
266088b4f5fSWarner Losh
267088b4f5fSWarner Losh		{
268a7cf0562SKyle Evans			entry_type = core.MENU_SEPARATOR,
269088b4f5fSWarner Losh			name = function()
270088b4f5fSWarner Losh				return "Options:";
271088b4f5fSWarner Losh			end
272088b4f5fSWarner Losh		},
273088b4f5fSWarner Losh
274088b4f5fSWarner Losh		-- kernel options
275088b4f5fSWarner Losh		{
276a7cf0562SKyle Evans			entry_type = core.MENU_CAROUSEL_ENTRY,
277ada26c4aSKyle Evans			carousel_id = "kernel",
278ada26c4aSKyle Evans			items = core.kernelList,
279ada26c4aSKyle Evans			name = function(idx, choice, all_choices)
28024a1bd54SKyle Evans				if (#all_choices == 0) then
281b1b1f2b8SKyle Evans					return "Kernel: ";
282088b4f5fSWarner Losh				end
283b1b1f2b8SKyle Evans
284bcf48a15SKyle Evans				local is_default = (idx == 1);
285bcf48a15SKyle Evans				local kernel_name = "";
286bcf48a15SKyle Evans				local name_color;
28724a1bd54SKyle Evans				if (is_default) then
288bcf48a15SKyle Evans					name_color = color.escapef(color.GREEN);
289bcf48a15SKyle Evans					kernel_name = "default/";
290bcf48a15SKyle Evans				else
291bcf48a15SKyle Evans					name_color = color.escapef(color.BLUE);
292b1b1f2b8SKyle Evans				end
293fd2b19b3SKyle Evans				kernel_name = kernel_name .. name_color ..
294fd2b19b3SKyle Evans				    choice .. color.default();
295fd2b19b3SKyle Evans				return color.highlight("K") .. "ernel: " ..
296fd2b19b3SKyle Evans				    kernel_name .. " (" .. idx .. " of " ..
297fd2b19b3SKyle Evans				    #all_choices .. ")";
298088b4f5fSWarner Losh			end,
2995d1e2f83SKyle Evans			func = function(idx, choice, all_choices)
300fa4a2394SKyle Evans				config.selectkernel(choice);
301088b4f5fSWarner Losh			end,
302088b4f5fSWarner Losh			alias = {"k", "K"}
303088b4f5fSWarner Losh		},
304088b4f5fSWarner Losh
305088b4f5fSWarner Losh		-- boot options
306088b4f5fSWarner Losh		{
307a7cf0562SKyle Evans			entry_type = core.MENU_SUBMENU,
308088b4f5fSWarner Losh			name = function()
309fd2b19b3SKyle Evans				return "Boot " .. color.highlight("O") ..
310fd2b19b3SKyle Evans				    "ptions";
311088b4f5fSWarner Losh			end,
312088b4f5fSWarner Losh			submenu = function()
313088b4f5fSWarner Losh				return menu.boot_options;
314088b4f5fSWarner Losh			end,
315088b4f5fSWarner Losh			alias = {"o", "O"}
316d8757746SKyle Evans		},
317d8757746SKyle Evans	},
318088b4f5fSWarner Losh};
319088b4f5fSWarner Losh
320ada26c4aSKyle Evans-- The first item in every carousel is always the default item.
321ada26c4aSKyle Evansfunction menu.getCarouselIndex(id)
322ada26c4aSKyle Evans	local val = carousel_choices[id];
323ada26c4aSKyle Evans	if (val == nil) then
324ada26c4aSKyle Evans		return 1;
325ada26c4aSKyle Evans	end
326ada26c4aSKyle Evans	return val;
327ada26c4aSKyle Evansend
328ada26c4aSKyle Evans
329ada26c4aSKyle Evansfunction menu.setCarouselIndex(id, idx)
330ada26c4aSKyle Evans	carousel_choices[id] = idx;
331ada26c4aSKyle Evansend
332ada26c4aSKyle Evans
333088b4f5fSWarner Loshfunction menu.run(m)
334088b4f5fSWarner Losh
335088b4f5fSWarner Losh	if (menu.skip()) then
336088b4f5fSWarner Losh		core.autoboot();
337088b4f5fSWarner Losh		return false;
338088b4f5fSWarner Losh	end
339088b4f5fSWarner Losh
340088b4f5fSWarner Losh	if (m == nil) then
341088b4f5fSWarner Losh		m = menu.welcome;
342088b4f5fSWarner Losh	end
343088b4f5fSWarner Losh
344088b4f5fSWarner Losh	-- redraw screen
345088b4f5fSWarner Losh	screen.clear();
346088b4f5fSWarner Losh	screen.defcursor();
347088b4f5fSWarner Losh	local alias_table = drawer.drawscreen(m);
348088b4f5fSWarner Losh
3493a0a07d0SKyle Evans	menu.autoboot();
350088b4f5fSWarner Losh
351088b4f5fSWarner Losh	cont = true;
35224a1bd54SKyle Evans	while (cont) do
353abc4f7e7SKyle Evans		local key = io.getchar();
354088b4f5fSWarner Losh
355b458bf0dSKyle Evans		-- Special key behaviors
3561504bce3SKyle Evans		if ((key == core.KEY_BACKSPACE) or (key == core.KEY_DELETE)) and
3571504bce3SKyle Evans		    (m ~= menu.welcome) then
3581f5696c7SKyle Evans			break;
359fe672a15SKyle Evans		elseif (key == core.KEY_ENTER) then
360b458bf0dSKyle Evans			core.boot();
361b458bf0dSKyle Evans			-- Should not return
362abc4f7e7SKyle Evans		end
363abc4f7e7SKyle Evans
364abc4f7e7SKyle Evans		key = string.char(key)
365088b4f5fSWarner Losh		-- check to see if key is an alias
366088b4f5fSWarner Losh		local sel_entry = nil;
367088b4f5fSWarner Losh		for k, v in pairs(alias_table) do
368088b4f5fSWarner Losh			if (key == k) then
369088b4f5fSWarner Losh				sel_entry = v;
370088b4f5fSWarner Losh			end
371088b4f5fSWarner Losh		end
372088b4f5fSWarner Losh
373088b4f5fSWarner Losh		-- if we have an alias do the assigned action:
374088b4f5fSWarner Losh		if (sel_entry ~= nil) then
375*8d415029SKyle Evans			-- Get menu handler
376*8d415029SKyle Evans			local handler = menu.handlers[sel_entry.entry_type];
377*8d415029SKyle Evans			if (handler ~= nil) then
378*8d415029SKyle Evans				-- The handler's return value indicates whether
379*8d415029SKyle Evans				-- we need to exit this menu. An omitted return
380*8d415029SKyle Evans				-- value means "continue" by default.
381*8d415029SKyle Evans				cont = handler(m, sel_entry);
382*8d415029SKyle Evans				if (cont == nil) then
383*8d415029SKyle Evans					cont = true;
384aefcaa7eSKyle Evans				end
385088b4f5fSWarner Losh			end
386088b4f5fSWarner Losh			-- if we got an alias key the screen is out of date:
387088b4f5fSWarner Losh			screen.clear();
388088b4f5fSWarner Losh			screen.defcursor();
389088b4f5fSWarner Losh			alias_table = drawer.drawscreen(m);
390088b4f5fSWarner Losh		end
391088b4f5fSWarner Losh	end
392088b4f5fSWarner Losh
393088b4f5fSWarner Losh	if (m == menu.welcome) then
394088b4f5fSWarner Losh		screen.defcursor();
395088b4f5fSWarner Losh		print("Exiting menu!");
396fa4a2394SKyle Evans		config.loadelf();
397088b4f5fSWarner Losh		return false;
398088b4f5fSWarner Losh	end
399088b4f5fSWarner Losh
400088b4f5fSWarner Losh	return true;
401088b4f5fSWarner Loshend
402088b4f5fSWarner Losh
403088b4f5fSWarner Loshfunction menu.skip()
404b140d14bSKyle Evans	if (core.isSerialBoot()) then
405088b4f5fSWarner Losh		return true;
406088b4f5fSWarner Losh	end
407088b4f5fSWarner Losh	local c = string.lower(loader.getenv("console") or "");
40824a1bd54SKyle Evans	if ((c:match("^efi[ ;]") or c:match("[ ;]efi[ ;]")) ~= nil) then
409088b4f5fSWarner Losh		return true;
410088b4f5fSWarner Losh	end
411088b4f5fSWarner Losh
412088b4f5fSWarner Losh	c = string.lower(loader.getenv("beastie_disable") or "");
413088b4f5fSWarner Losh	print("beastie_disable", c);
414088b4f5fSWarner Losh	return c == "yes";
415088b4f5fSWarner Loshend
416088b4f5fSWarner Losh
417088b4f5fSWarner Loshfunction menu.autoboot()
41824a1bd54SKyle Evans	if (menu.already_autoboot == true) then
419088b4f5fSWarner Losh		return;
420088b4f5fSWarner Losh	end
421088b4f5fSWarner Losh	menu.already_autoboot = true;
422088b4f5fSWarner Losh
423088b4f5fSWarner Losh	local ab = loader.getenv("autoboot_delay");
424702b460dSKyle Evans	if (ab ~= nil) and (ab:lower() == "no") then
425702b460dSKyle Evans		return;
426702b460dSKyle Evans	elseif (tonumber(ab) == -1) then
427088b4f5fSWarner Losh		core.boot();
428088b4f5fSWarner Losh	end
429088b4f5fSWarner Losh	ab = tonumber(ab) or 10;
430088b4f5fSWarner Losh
431088b4f5fSWarner Losh	local x = loader.getenv("loader_menu_timeout_x") or 5;
432088b4f5fSWarner Losh	local y = loader.getenv("loader_menu_timeout_y") or 22;
433088b4f5fSWarner Losh
434088b4f5fSWarner Losh	local endtime = loader.time() + ab;
435088b4f5fSWarner Losh	local time;
436088b4f5fSWarner Losh
437088b4f5fSWarner Losh	repeat
438088b4f5fSWarner Losh		time = endtime - loader.time();
439088b4f5fSWarner Losh		screen.setcursor(x, y);
44057099121SKyle Evans		print("Autoboot in " .. time ..
44157099121SKyle Evans		    " seconds, hit [Enter] to boot" ..
44257099121SKyle Evans		    " or any other key to stop     ");
443088b4f5fSWarner Losh		screen.defcursor();
44424a1bd54SKyle Evans		if (io.ischar()) then
445088b4f5fSWarner Losh			local ch = io.getchar();
44624a1bd54SKyle Evans			if (ch == core.KEY_ENTER) then
447088b4f5fSWarner Losh				break;
448088b4f5fSWarner Losh			else
449088b4f5fSWarner Losh				-- erase autoboot msg
450088b4f5fSWarner Losh				screen.setcursor(0, y);
451088b4f5fSWarner Losh				print("                                        "
452088b4f5fSWarner Losh				    .. "                                        ");
453088b4f5fSWarner Losh				screen.defcursor();
454088b4f5fSWarner Losh				return;
455088b4f5fSWarner Losh			end
456088b4f5fSWarner Losh		end
457088b4f5fSWarner Losh
458088b4f5fSWarner Losh		loader.delay(50000);
4591f5696c7SKyle Evans	until time <= 0;
460088b4f5fSWarner Losh	core.boot();
461088b4f5fSWarner Losh
462088b4f5fSWarner Loshend
463088b4f5fSWarner Losh
464088b4f5fSWarner Loshfunction OnOff(str, b)
465088b4f5fSWarner Losh	if (b) then
46657099121SKyle Evans		return str .. color.escapef(color.GREEN) .. "On" ..
46757099121SKyle Evans		    color.escapef(color.WHITE);
468088b4f5fSWarner Losh	else
46957099121SKyle Evans		return str .. color.escapef(color.RED) .. "off" ..
47057099121SKyle Evans		    color.escapef(color.WHITE);
471088b4f5fSWarner Losh	end
472088b4f5fSWarner Loshend
473088b4f5fSWarner Losh
47424a1bd54SKyle Evansreturn menu;
475