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