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 45280e990bSKyle Evans-- loader menu tree is rooted at menu.welcome 46088b4f5fSWarner Losh 47088b4f5fSWarner Loshmenu.boot_options = { 48d8757746SKyle Evans entries = { 49088b4f5fSWarner Losh -- return to welcome menu 50088b4f5fSWarner Losh { 51a7cf0562SKyle Evans entry_type = core.MENU_RETURN, 52088b4f5fSWarner Losh name = function() 5357099121SKyle Evans return "Back to main menu" .. 5457099121SKyle Evans color.highlight(" [Backspace]"); 551666dfc0SKyle Evans end 56088b4f5fSWarner Losh }, 57088b4f5fSWarner Losh 58088b4f5fSWarner Losh -- load defaults 59088b4f5fSWarner Losh { 60a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 61088b4f5fSWarner Losh name = function() 6257099121SKyle Evans return "Load System " .. color.highlight("D") .. 6357099121SKyle Evans "efaults"; 64088b4f5fSWarner Losh end, 65088b4f5fSWarner Losh func = function() 6624a1bd54SKyle Evans core.setDefaults(); 67088b4f5fSWarner Losh end, 68088b4f5fSWarner Losh alias = {"d", "D"} 69088b4f5fSWarner Losh }, 70088b4f5fSWarner Losh 71088b4f5fSWarner Losh { 72a7cf0562SKyle Evans entry_type = core.MENU_SEPARATOR, 73088b4f5fSWarner Losh name = function() 74088b4f5fSWarner Losh return ""; 75088b4f5fSWarner Losh end 76088b4f5fSWarner Losh }, 77088b4f5fSWarner Losh 78088b4f5fSWarner Losh { 79a7cf0562SKyle Evans entry_type = core.MENU_SEPARATOR, 80088b4f5fSWarner Losh name = function() 81088b4f5fSWarner Losh return "Boot Options:"; 82088b4f5fSWarner Losh end 83088b4f5fSWarner Losh }, 84088b4f5fSWarner Losh 85088b4f5fSWarner Losh -- acpi 86088b4f5fSWarner Losh { 87a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 88088b4f5fSWarner Losh name = function() 89fd2b19b3SKyle Evans return OnOff(color.highlight("A") .. 90fd2b19b3SKyle Evans "CPI :", core.acpi); 91088b4f5fSWarner Losh end, 92088b4f5fSWarner Losh func = function() 93088b4f5fSWarner Losh core.setACPI(); 94088b4f5fSWarner Losh end, 95088b4f5fSWarner Losh alias = {"a", "A"} 96088b4f5fSWarner Losh }, 97088b4f5fSWarner Losh -- safe mode 98088b4f5fSWarner Losh { 99a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 100088b4f5fSWarner Losh name = function() 10157099121SKyle Evans return OnOff("Safe " .. color.highlight("M") .. 10257099121SKyle Evans "ode :", core.sm); 103088b4f5fSWarner Losh end, 104088b4f5fSWarner Losh func = function() 105088b4f5fSWarner Losh core.setSafeMode(); 106088b4f5fSWarner Losh end, 107088b4f5fSWarner Losh alias = {"m", "M"} 108088b4f5fSWarner Losh }, 109088b4f5fSWarner Losh -- single user 110088b4f5fSWarner Losh { 111a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 112088b4f5fSWarner Losh name = function() 113fd2b19b3SKyle Evans return OnOff(color.highlight("S") .. 114fd2b19b3SKyle Evans "ingle user:", core.su); 115088b4f5fSWarner Losh end, 116088b4f5fSWarner Losh func = function() 117088b4f5fSWarner Losh core.setSingleUser(); 118088b4f5fSWarner Losh end, 119088b4f5fSWarner Losh alias = {"s", "S"} 120088b4f5fSWarner Losh }, 121088b4f5fSWarner Losh -- verbose boot 122088b4f5fSWarner Losh { 123a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 124088b4f5fSWarner Losh name = function() 125fd2b19b3SKyle Evans return OnOff(color.highlight("V") .. 126fd2b19b3SKyle Evans "erbose :", core.verbose); 127088b4f5fSWarner Losh end, 128088b4f5fSWarner Losh func = function() 129088b4f5fSWarner Losh core.setVerbose(); 130088b4f5fSWarner Losh end, 131088b4f5fSWarner Losh alias = {"v", "V"} 132088b4f5fSWarner Losh }, 133d8757746SKyle Evans }, 134088b4f5fSWarner Losh}; 135088b4f5fSWarner Losh 136088b4f5fSWarner Loshmenu.welcome = { 137303253e5SKyle Evans entries = function() 138303253e5SKyle Evans local menu_entries = menu.welcome.all_entries; 139303253e5SKyle Evans -- Swap the first two menu items on single user boot 140303253e5SKyle Evans if (core.isSingleUserBoot()) then 141*9a0904b0SKyle Evans -- We'll cache the swapped menu, for performance 142*9a0904b0SKyle Evans if (menu.welcome.swapped_menu ~= nil) then 143*9a0904b0SKyle Evans return menu.welcome.swapped_menu; 144*9a0904b0SKyle Evans end 1455c1b5165SKyle Evans -- Shallow copy the table 1465c1b5165SKyle Evans menu_entries = core.shallowCopyTable(menu_entries); 1475c1b5165SKyle Evans 148*9a0904b0SKyle Evans -- Swap the first two menu entries 149*9a0904b0SKyle Evans menu_entries[1], menu_entries[2] = menu_entries[2], 150*9a0904b0SKyle Evans menu_entries[1]; 151303253e5SKyle Evans 152*9a0904b0SKyle Evans -- Then set their names to their alternate names 153*9a0904b0SKyle Evans menu_entries[1].name, menu_entries[2].name = 154*9a0904b0SKyle Evans menu_entries[1].alternate_name, 155*9a0904b0SKyle Evans menu_entries[2].alternate_name; 156*9a0904b0SKyle Evans menu.welcome.swapped_menu = menu_entries; 157303253e5SKyle Evans end 158303253e5SKyle Evans return menu_entries; 159303253e5SKyle Evans end, 160303253e5SKyle Evans all_entries = { 161088b4f5fSWarner Losh -- boot multi user 162088b4f5fSWarner Losh { 163a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 164088b4f5fSWarner Losh name = function() 165fd2b19b3SKyle Evans return color.highlight("B") .. 166fd2b19b3SKyle Evans "oot Multi user " .. 16757099121SKyle Evans color.highlight("[Enter]"); 168088b4f5fSWarner Losh end, 1695c1b5165SKyle Evans -- Not a standard menu entry function! 1705c1b5165SKyle Evans alternate_name = function() 1715c1b5165SKyle Evans return color.highlight("B") .. 1725c1b5165SKyle Evans "oot Multi user"; 1735c1b5165SKyle Evans end, 174088b4f5fSWarner Losh func = function() 175088b4f5fSWarner Losh core.setSingleUser(false); 176088b4f5fSWarner Losh core.boot(); 177088b4f5fSWarner Losh end, 178b458bf0dSKyle Evans alias = {"b", "B"} 179088b4f5fSWarner Losh }, 180088b4f5fSWarner Losh 181088b4f5fSWarner Losh -- boot single user 182088b4f5fSWarner Losh { 183a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 184088b4f5fSWarner Losh name = function() 185fd2b19b3SKyle Evans return "Boot " .. color.highlight("S") .. 186fd2b19b3SKyle Evans "ingle user"; 187088b4f5fSWarner Losh end, 1885c1b5165SKyle Evans -- Not a standard menu entry function! 1895c1b5165SKyle Evans alternate_name = function() 1905c1b5165SKyle Evans return "Boot " .. color.highlight("S") .. 1915c1b5165SKyle Evans "ingle user " .. color.highlight("[Enter]"); 1925c1b5165SKyle Evans end, 193088b4f5fSWarner Losh func = function() 194088b4f5fSWarner Losh core.setSingleUser(true); 195088b4f5fSWarner Losh core.boot(); 196088b4f5fSWarner Losh end, 197088b4f5fSWarner Losh alias = {"s", "S"} 198088b4f5fSWarner Losh }, 199088b4f5fSWarner Losh 200088b4f5fSWarner Losh -- escape to interpreter 201088b4f5fSWarner Losh { 202a7cf0562SKyle Evans entry_type = core.MENU_RETURN, 203088b4f5fSWarner Losh name = function() 204fd2b19b3SKyle Evans return color.highlight("Esc") .. 205fd2b19b3SKyle Evans "ape to loader prompt"; 206088b4f5fSWarner Losh end, 207ef625845SKyle Evans func = function() 20824a1bd54SKyle Evans loader.setenv("autoboot_delay", "NO"); 209ef625845SKyle Evans end, 21039006570SKyle Evans alias = {core.KEYSTR_ESCAPE} 211088b4f5fSWarner Losh }, 212088b4f5fSWarner Losh 213088b4f5fSWarner Losh -- reboot 214088b4f5fSWarner Losh { 215a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 216088b4f5fSWarner Losh name = function() 217088b4f5fSWarner Losh return color.highlight("R") .. "eboot"; 218088b4f5fSWarner Losh end, 219088b4f5fSWarner Losh func = function() 220088b4f5fSWarner Losh loader.perform("reboot"); 221088b4f5fSWarner Losh end, 222088b4f5fSWarner Losh alias = {"r", "R"} 223088b4f5fSWarner Losh }, 224088b4f5fSWarner Losh 225088b4f5fSWarner Losh 226088b4f5fSWarner Losh { 227a7cf0562SKyle Evans entry_type = core.MENU_SEPARATOR, 228088b4f5fSWarner Losh name = function() 229088b4f5fSWarner Losh return ""; 230088b4f5fSWarner Losh end 231088b4f5fSWarner Losh }, 232088b4f5fSWarner Losh 233088b4f5fSWarner Losh { 234a7cf0562SKyle Evans entry_type = core.MENU_SEPARATOR, 235088b4f5fSWarner Losh name = function() 236088b4f5fSWarner Losh return "Options:"; 237088b4f5fSWarner Losh end 238088b4f5fSWarner Losh }, 239088b4f5fSWarner Losh 240088b4f5fSWarner Losh -- kernel options 241088b4f5fSWarner Losh { 242a7cf0562SKyle Evans entry_type = core.MENU_CAROUSEL_ENTRY, 243ada26c4aSKyle Evans carousel_id = "kernel", 244ada26c4aSKyle Evans items = core.kernelList, 245ada26c4aSKyle Evans name = function(idx, choice, all_choices) 24624a1bd54SKyle Evans if (#all_choices == 0) then 247b1b1f2b8SKyle Evans return "Kernel: "; 248088b4f5fSWarner Losh end 249b1b1f2b8SKyle Evans 250bcf48a15SKyle Evans local is_default = (idx == 1); 251bcf48a15SKyle Evans local kernel_name = ""; 252bcf48a15SKyle Evans local name_color; 25324a1bd54SKyle Evans if (is_default) then 254bcf48a15SKyle Evans name_color = color.escapef(color.GREEN); 255bcf48a15SKyle Evans kernel_name = "default/"; 256bcf48a15SKyle Evans else 257bcf48a15SKyle Evans name_color = color.escapef(color.BLUE); 258b1b1f2b8SKyle Evans end 259fd2b19b3SKyle Evans kernel_name = kernel_name .. name_color .. 260fd2b19b3SKyle Evans choice .. color.default(); 261fd2b19b3SKyle Evans return color.highlight("K") .. "ernel: " .. 262fd2b19b3SKyle Evans kernel_name .. " (" .. idx .. " of " .. 263fd2b19b3SKyle Evans #all_choices .. ")"; 264088b4f5fSWarner Losh end, 2655d1e2f83SKyle Evans func = function(idx, choice, all_choices) 266fa4a2394SKyle Evans config.selectkernel(choice); 267088b4f5fSWarner Losh end, 268088b4f5fSWarner Losh alias = {"k", "K"} 269088b4f5fSWarner Losh }, 270088b4f5fSWarner Losh 271088b4f5fSWarner Losh -- boot options 272088b4f5fSWarner Losh { 273a7cf0562SKyle Evans entry_type = core.MENU_SUBMENU, 274088b4f5fSWarner Losh name = function() 275fd2b19b3SKyle Evans return "Boot " .. color.highlight("O") .. 276fd2b19b3SKyle Evans "ptions"; 277088b4f5fSWarner Losh end, 278088b4f5fSWarner Losh submenu = function() 279088b4f5fSWarner Losh return menu.boot_options; 280088b4f5fSWarner Losh end, 281088b4f5fSWarner Losh alias = {"o", "O"} 282d8757746SKyle Evans }, 283d8757746SKyle Evans }, 284088b4f5fSWarner Losh}; 285088b4f5fSWarner Losh 286ada26c4aSKyle Evans-- The first item in every carousel is always the default item. 287ada26c4aSKyle Evansfunction menu.getCarouselIndex(id) 288ada26c4aSKyle Evans local val = carousel_choices[id]; 289ada26c4aSKyle Evans if (val == nil) then 290ada26c4aSKyle Evans return 1; 291ada26c4aSKyle Evans end 292ada26c4aSKyle Evans return val; 293ada26c4aSKyle Evansend 294ada26c4aSKyle Evans 295ada26c4aSKyle Evansfunction menu.setCarouselIndex(id, idx) 296ada26c4aSKyle Evans carousel_choices[id] = idx; 297ada26c4aSKyle Evansend 298ada26c4aSKyle Evans 299088b4f5fSWarner Loshfunction menu.run(m) 300088b4f5fSWarner Losh 301088b4f5fSWarner Losh if (menu.skip()) then 302088b4f5fSWarner Losh core.autoboot(); 303088b4f5fSWarner Losh return false; 304088b4f5fSWarner Losh end 305088b4f5fSWarner Losh 306088b4f5fSWarner Losh if (m == nil) then 307088b4f5fSWarner Losh m = menu.welcome; 308088b4f5fSWarner Losh end 309088b4f5fSWarner Losh 310088b4f5fSWarner Losh -- redraw screen 311088b4f5fSWarner Losh screen.clear(); 312088b4f5fSWarner Losh screen.defcursor(); 313088b4f5fSWarner Losh local alias_table = drawer.drawscreen(m); 314088b4f5fSWarner Losh 3153a0a07d0SKyle Evans menu.autoboot(); 316088b4f5fSWarner Losh 317088b4f5fSWarner Losh cont = true; 31824a1bd54SKyle Evans while (cont) do 319abc4f7e7SKyle Evans local key = io.getchar(); 320088b4f5fSWarner Losh 321b458bf0dSKyle Evans -- Special key behaviors 3221504bce3SKyle Evans if ((key == core.KEY_BACKSPACE) or (key == core.KEY_DELETE)) and 3231504bce3SKyle Evans (m ~= menu.welcome) then 3241f5696c7SKyle Evans break; 325fe672a15SKyle Evans elseif (key == core.KEY_ENTER) then 326b458bf0dSKyle Evans core.boot(); 327b458bf0dSKyle Evans -- Should not return 328abc4f7e7SKyle Evans end 329abc4f7e7SKyle Evans 330abc4f7e7SKyle Evans key = string.char(key) 331088b4f5fSWarner Losh -- check to see if key is an alias 332088b4f5fSWarner Losh local sel_entry = nil; 333088b4f5fSWarner Losh for k, v in pairs(alias_table) do 334088b4f5fSWarner Losh if (key == k) then 335088b4f5fSWarner Losh sel_entry = v; 336088b4f5fSWarner Losh end 337088b4f5fSWarner Losh end 338088b4f5fSWarner Losh 339088b4f5fSWarner Losh -- if we have an alias do the assigned action: 340088b4f5fSWarner Losh if (sel_entry ~= nil) then 341a7cf0562SKyle Evans if (sel_entry.entry_type == core.MENU_ENTRY) then 342088b4f5fSWarner Losh -- run function 343088b4f5fSWarner Losh sel_entry.func(); 344a7cf0562SKyle Evans elseif (sel_entry.entry_type == core.MENU_CAROUSEL_ENTRY) then 345ada26c4aSKyle Evans -- carousel (rotating) functionality 346ada26c4aSKyle Evans local carid = sel_entry.carousel_id; 347ada26c4aSKyle Evans local caridx = menu.getCarouselIndex(carid); 348ada26c4aSKyle Evans local choices = sel_entry.items(); 349ada26c4aSKyle Evans 350aefcaa7eSKyle Evans if (#choices > 0) then 351ada26c4aSKyle Evans caridx = (caridx % #choices) + 1; 352ada26c4aSKyle Evans menu.setCarouselIndex(carid, caridx); 3535d1e2f83SKyle Evans sel_entry.func(caridx, choices[caridx], 35484f82e46SKyle Evans choices); 355aefcaa7eSKyle Evans end 356a7cf0562SKyle Evans elseif (sel_entry.entry_type == core.MENU_SUBMENU) then 357088b4f5fSWarner Losh -- recurse 358088b4f5fSWarner Losh cont = menu.run(sel_entry.submenu()); 359a7cf0562SKyle Evans elseif (sel_entry.entry_type == core.MENU_RETURN) then 360ef625845SKyle Evans -- allow entry to have a function/side effect 361ef625845SKyle Evans if (sel_entry.func ~= nil) then 362ef625845SKyle Evans sel_entry.func(); 363ef625845SKyle Evans end 364088b4f5fSWarner Losh -- break recurse 365088b4f5fSWarner Losh cont = false; 366088b4f5fSWarner Losh end 367088b4f5fSWarner Losh -- if we got an alias key the screen is out of date: 368088b4f5fSWarner Losh screen.clear(); 369088b4f5fSWarner Losh screen.defcursor(); 370088b4f5fSWarner Losh alias_table = drawer.drawscreen(m); 371088b4f5fSWarner Losh end 372088b4f5fSWarner Losh end 373088b4f5fSWarner Losh 374088b4f5fSWarner Losh if (m == menu.welcome) then 375088b4f5fSWarner Losh screen.defcursor(); 376088b4f5fSWarner Losh print("Exiting menu!"); 377fa4a2394SKyle Evans config.loadelf(); 378088b4f5fSWarner Losh return false; 379088b4f5fSWarner Losh end 380088b4f5fSWarner Losh 381088b4f5fSWarner Losh return true; 382088b4f5fSWarner Loshend 383088b4f5fSWarner Losh 384088b4f5fSWarner Loshfunction menu.skip() 385b140d14bSKyle Evans if (core.isSerialBoot()) then 386088b4f5fSWarner Losh return true; 387088b4f5fSWarner Losh end 388088b4f5fSWarner Losh local c = string.lower(loader.getenv("console") or ""); 38924a1bd54SKyle Evans if ((c:match("^efi[ ;]") or c:match("[ ;]efi[ ;]")) ~= nil) then 390088b4f5fSWarner Losh return true; 391088b4f5fSWarner Losh end 392088b4f5fSWarner Losh 393088b4f5fSWarner Losh c = string.lower(loader.getenv("beastie_disable") or ""); 394088b4f5fSWarner Losh print("beastie_disable", c); 395088b4f5fSWarner Losh return c == "yes"; 396088b4f5fSWarner Loshend 397088b4f5fSWarner Losh 398088b4f5fSWarner Loshfunction menu.autoboot() 39924a1bd54SKyle Evans if (menu.already_autoboot == true) then 400088b4f5fSWarner Losh return; 401088b4f5fSWarner Losh end 402088b4f5fSWarner Losh menu.already_autoboot = true; 403088b4f5fSWarner Losh 404088b4f5fSWarner Losh local ab = loader.getenv("autoboot_delay"); 405702b460dSKyle Evans if (ab ~= nil) and (ab:lower() == "no") then 406702b460dSKyle Evans return; 407702b460dSKyle Evans elseif (tonumber(ab) == -1) then 408088b4f5fSWarner Losh core.boot(); 409088b4f5fSWarner Losh end 410088b4f5fSWarner Losh ab = tonumber(ab) or 10; 411088b4f5fSWarner Losh 412088b4f5fSWarner Losh local x = loader.getenv("loader_menu_timeout_x") or 5; 413088b4f5fSWarner Losh local y = loader.getenv("loader_menu_timeout_y") or 22; 414088b4f5fSWarner Losh 415088b4f5fSWarner Losh local endtime = loader.time() + ab; 416088b4f5fSWarner Losh local time; 417088b4f5fSWarner Losh 418088b4f5fSWarner Losh repeat 419088b4f5fSWarner Losh time = endtime - loader.time(); 420088b4f5fSWarner Losh screen.setcursor(x, y); 42157099121SKyle Evans print("Autoboot in " .. time .. 42257099121SKyle Evans " seconds, hit [Enter] to boot" .. 42357099121SKyle Evans " or any other key to stop "); 424088b4f5fSWarner Losh screen.defcursor(); 42524a1bd54SKyle Evans if (io.ischar()) then 426088b4f5fSWarner Losh local ch = io.getchar(); 42724a1bd54SKyle Evans if (ch == core.KEY_ENTER) then 428088b4f5fSWarner Losh break; 429088b4f5fSWarner Losh else 430088b4f5fSWarner Losh -- erase autoboot msg 431088b4f5fSWarner Losh screen.setcursor(0, y); 432088b4f5fSWarner Losh print(" " 433088b4f5fSWarner Losh .. " "); 434088b4f5fSWarner Losh screen.defcursor(); 435088b4f5fSWarner Losh return; 436088b4f5fSWarner Losh end 437088b4f5fSWarner Losh end 438088b4f5fSWarner Losh 439088b4f5fSWarner Losh loader.delay(50000); 4401f5696c7SKyle Evans until time <= 0; 441088b4f5fSWarner Losh core.boot(); 442088b4f5fSWarner Losh 443088b4f5fSWarner Loshend 444088b4f5fSWarner Losh 445088b4f5fSWarner Loshfunction OnOff(str, b) 446088b4f5fSWarner Losh if (b) then 44757099121SKyle Evans return str .. color.escapef(color.GREEN) .. "On" .. 44857099121SKyle Evans color.escapef(color.WHITE); 449088b4f5fSWarner Losh else 45057099121SKyle Evans return str .. color.escapef(color.RED) .. "off" .. 45157099121SKyle Evans color.escapef(color.WHITE); 452088b4f5fSWarner Losh end 453088b4f5fSWarner Loshend 454088b4f5fSWarner Losh 45524a1bd54SKyle Evansreturn menu; 456