1088b4f5fSWarner Losh-- 2088b4f5fSWarner Losh-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org> 3088b4f5fSWarner Losh-- All rights reserved. 4088b4f5fSWarner Losh-- 5088b4f5fSWarner Losh-- Redistribution and use in source and binary forms, with or without 6088b4f5fSWarner Losh-- modification, are permitted provided that the following conditions 7088b4f5fSWarner Losh-- are met: 8088b4f5fSWarner Losh-- 1. Redistributions of source code must retain the above copyright 9088b4f5fSWarner Losh-- notice, this list of conditions and the following disclaimer. 10088b4f5fSWarner Losh-- 2. Redistributions in binary form must reproduce the above copyright 11088b4f5fSWarner Losh-- notice, this list of conditions and the following disclaimer in the 12088b4f5fSWarner Losh-- documentation and/or other materials provided with the distribution. 13088b4f5fSWarner Losh-- 14088b4f5fSWarner Losh-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15088b4f5fSWarner Losh-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16088b4f5fSWarner Losh-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17088b4f5fSWarner Losh-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18088b4f5fSWarner Losh-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19088b4f5fSWarner Losh-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20088b4f5fSWarner Losh-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21088b4f5fSWarner Losh-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22088b4f5fSWarner Losh-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23088b4f5fSWarner Losh-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24088b4f5fSWarner Losh-- SUCH DAMAGE. 25088b4f5fSWarner Losh-- 26088b4f5fSWarner Losh-- $FreeBSD$ 27088b4f5fSWarner Losh-- 28088b4f5fSWarner Losh 29088b4f5fSWarner Losh 30088b4f5fSWarner Loshlocal menu = {}; 31088b4f5fSWarner Losh 32088b4f5fSWarner Loshlocal core = require("core"); 33088b4f5fSWarner Loshlocal color = require("color"); 34088b4f5fSWarner Loshlocal config = require("config"); 35088b4f5fSWarner Loshlocal screen = require("screen"); 36088b4f5fSWarner Loshlocal drawer = require("drawer"); 37088b4f5fSWarner Losh 38088b4f5fSWarner Loshlocal OnOff; 39088b4f5fSWarner Loshlocal skip; 40088b4f5fSWarner Loshlocal run; 41088b4f5fSWarner Loshlocal autoboot; 42088b4f5fSWarner Losh 43088b4f5fSWarner Losh--loader menu tree: 44088b4f5fSWarner Losh--rooted at menu.welcome 45088b4f5fSWarner Losh--submenu declarations: 46088b4f5fSWarner Loshlocal kernel_options; 47088b4f5fSWarner Loshlocal boot_options; 48088b4f5fSWarner Loshlocal welcome; 49088b4f5fSWarner Losh 50088b4f5fSWarner Loshmenu.kernel_options = { 51088b4f5fSWarner Losh -- this table is dynamically appended to when accessed 52088b4f5fSWarner Losh -- return to welcome menu 53088b4f5fSWarner Losh { 54088b4f5fSWarner Losh entry_type = "return", 55088b4f5fSWarner Losh name = function() 56088b4f5fSWarner Losh return "Back to main menu"..color.highlight(" [Backspace]"); 57088b4f5fSWarner Losh end, 58088b4f5fSWarner Losh alias = {"\08"} 59088b4f5fSWarner Losh } 60088b4f5fSWarner Losh}; 61088b4f5fSWarner Losh 62088b4f5fSWarner Loshmenu.boot_options = { 63088b4f5fSWarner Losh -- return to welcome menu 64088b4f5fSWarner Losh { 65088b4f5fSWarner Losh entry_type = "return", 66088b4f5fSWarner Losh name = function() 67088b4f5fSWarner Losh return "Back to main menu"..color.highlight(" [Backspace]"); 68088b4f5fSWarner Losh end, 69088b4f5fSWarner Losh alias = {"\08"} 70088b4f5fSWarner Losh }, 71088b4f5fSWarner Losh 72088b4f5fSWarner Losh -- load defaults 73088b4f5fSWarner Losh { 74088b4f5fSWarner Losh entry_type = "entry", 75088b4f5fSWarner Losh name = function() 76088b4f5fSWarner Losh return "Load System "..color.highlight("D").."efaults"; 77088b4f5fSWarner Losh end, 78088b4f5fSWarner Losh func = function() 79088b4f5fSWarner Losh core.setDefaults() 80088b4f5fSWarner Losh end, 81088b4f5fSWarner Losh alias = {"d", "D"} 82088b4f5fSWarner Losh }, 83088b4f5fSWarner Losh 84088b4f5fSWarner Losh { 85088b4f5fSWarner Losh entry_type = "separator", 86088b4f5fSWarner Losh name = function() 87088b4f5fSWarner Losh return ""; 88088b4f5fSWarner Losh end 89088b4f5fSWarner Losh }, 90088b4f5fSWarner Losh 91088b4f5fSWarner Losh { 92088b4f5fSWarner Losh entry_type = "separator", 93088b4f5fSWarner Losh name = function() 94088b4f5fSWarner Losh return "Boot Options:"; 95088b4f5fSWarner Losh end 96088b4f5fSWarner Losh }, 97088b4f5fSWarner Losh 98088b4f5fSWarner Losh -- acpi 99088b4f5fSWarner Losh { 100088b4f5fSWarner Losh entry_type = "entry", 101088b4f5fSWarner Losh name = function() 102088b4f5fSWarner Losh return OnOff(color.highlight("A").."CPI :", core.acpi); 103088b4f5fSWarner Losh end, 104088b4f5fSWarner Losh func = function() 105088b4f5fSWarner Losh core.setACPI(); 106088b4f5fSWarner Losh end, 107088b4f5fSWarner Losh alias = {"a", "A"} 108088b4f5fSWarner Losh }, 109088b4f5fSWarner Losh -- safe mode 110088b4f5fSWarner Losh { 111088b4f5fSWarner Losh entry_type = "entry", 112088b4f5fSWarner Losh name = function() 113088b4f5fSWarner Losh return OnOff("Safe "..color.highlight("M").."ode :", core.sm); 114088b4f5fSWarner Losh end, 115088b4f5fSWarner Losh func = function() 116088b4f5fSWarner Losh core.setSafeMode(); 117088b4f5fSWarner Losh end, 118088b4f5fSWarner Losh alias = {"m", "M"} 119088b4f5fSWarner Losh }, 120088b4f5fSWarner Losh -- single user 121088b4f5fSWarner Losh { 122088b4f5fSWarner Losh entry_type = "entry", 123088b4f5fSWarner Losh name = function() 124088b4f5fSWarner Losh return OnOff(color.highlight("S").."ingle user:", core.su); 125088b4f5fSWarner Losh end, 126088b4f5fSWarner Losh func = function() 127088b4f5fSWarner Losh core.setSingleUser(); 128088b4f5fSWarner Losh end, 129088b4f5fSWarner Losh alias = {"s", "S"} 130088b4f5fSWarner Losh }, 131088b4f5fSWarner Losh -- verbose boot 132088b4f5fSWarner Losh { 133088b4f5fSWarner Losh entry_type = "entry", 134088b4f5fSWarner Losh name = function() 135088b4f5fSWarner Losh return OnOff(color.highlight("V").."erbose :", core.verbose); 136088b4f5fSWarner Losh end, 137088b4f5fSWarner Losh func = function() 138088b4f5fSWarner Losh core.setVerbose(); 139088b4f5fSWarner Losh end, 140088b4f5fSWarner Losh alias = {"v", "V"} 141088b4f5fSWarner Losh }, 142088b4f5fSWarner Losh}; 143088b4f5fSWarner Losh 144088b4f5fSWarner Loshmenu.welcome = { 145088b4f5fSWarner Losh -- boot multi user 146088b4f5fSWarner Losh { 147088b4f5fSWarner Losh entry_type = "entry", 148088b4f5fSWarner Losh name = function() 149088b4f5fSWarner Losh return color.highlight("B").."oot Multi user "..color.highlight("[Enter]"); 150088b4f5fSWarner Losh end, 151088b4f5fSWarner Losh func = function() 152088b4f5fSWarner Losh core.setSingleUser(false); 153088b4f5fSWarner Losh core.boot(); 154088b4f5fSWarner Losh end, 155*b458bf0dSKyle Evans alias = {"b", "B"} 156088b4f5fSWarner Losh }, 157088b4f5fSWarner Losh 158088b4f5fSWarner Losh -- boot single user 159088b4f5fSWarner Losh { 160088b4f5fSWarner Losh entry_type = "entry", 161088b4f5fSWarner Losh name = function() 162088b4f5fSWarner Losh return "Boot "..color.highlight("S").."ingle user"; 163088b4f5fSWarner Losh end, 164088b4f5fSWarner Losh func = function() 165088b4f5fSWarner Losh core.setSingleUser(true); 166088b4f5fSWarner Losh core.boot(); 167088b4f5fSWarner Losh end, 168088b4f5fSWarner Losh alias = {"s", "S"} 169088b4f5fSWarner Losh }, 170088b4f5fSWarner Losh 171088b4f5fSWarner Losh -- escape to interpreter 172088b4f5fSWarner Losh { 173088b4f5fSWarner Losh entry_type = "return", 174088b4f5fSWarner Losh name = function() 175088b4f5fSWarner Losh return color.highlight("Esc").."ape to lua interpreter"; 176088b4f5fSWarner Losh end, 177088b4f5fSWarner Losh alias = {"\027"} 178088b4f5fSWarner Losh }, 179088b4f5fSWarner Losh 180088b4f5fSWarner Losh -- reboot 181088b4f5fSWarner Losh { 182088b4f5fSWarner Losh entry_type = "entry", 183088b4f5fSWarner Losh name = function() 184088b4f5fSWarner Losh return color.highlight("R").."eboot"; 185088b4f5fSWarner Losh end, 186088b4f5fSWarner Losh func = function() 187088b4f5fSWarner Losh loader.perform("reboot"); 188088b4f5fSWarner Losh end, 189088b4f5fSWarner Losh alias = {"r", "R"} 190088b4f5fSWarner Losh }, 191088b4f5fSWarner Losh 192088b4f5fSWarner Losh 193088b4f5fSWarner Losh { 194088b4f5fSWarner Losh entry_type = "separator", 195088b4f5fSWarner Losh name = function() 196088b4f5fSWarner Losh return ""; 197088b4f5fSWarner Losh end 198088b4f5fSWarner Losh }, 199088b4f5fSWarner Losh 200088b4f5fSWarner Losh { 201088b4f5fSWarner Losh entry_type = "separator", 202088b4f5fSWarner Losh name = function() 203088b4f5fSWarner Losh return "Options:"; 204088b4f5fSWarner Losh end 205088b4f5fSWarner Losh }, 206088b4f5fSWarner Losh 207088b4f5fSWarner Losh -- kernel options 208088b4f5fSWarner Losh { 209088b4f5fSWarner Losh entry_type = "submenu", 210088b4f5fSWarner Losh name = function() 211088b4f5fSWarner Losh local kernels = core.kernelList(); 212088b4f5fSWarner Losh if #kernels == 0 then 213088b4f5fSWarner Losh return "Kernels (not available)"; 214088b4f5fSWarner Losh end 215088b4f5fSWarner Losh return color.highlight("K").."ernels"; 216088b4f5fSWarner Losh end, 217088b4f5fSWarner Losh submenu = function() 218088b4f5fSWarner Losh 219088b4f5fSWarner Losh -- dynamically build the kernel menu: 220088b4f5fSWarner Losh local kernels = core.kernelList(); 221088b4f5fSWarner Losh for k, v in ipairs(kernels) do 222088b4f5fSWarner Losh menu.kernel_options[#menu.kernel_options + 1] = { 223088b4f5fSWarner Losh entry_type = "entry", 224088b4f5fSWarner Losh name = function() 225088b4f5fSWarner Losh return v; 226088b4f5fSWarner Losh end, 227088b4f5fSWarner Losh func = function() 228088b4f5fSWarner Losh config.reload(v); 229088b4f5fSWarner Losh end, 230088b4f5fSWarner Losh alias = {} -- automatically enumerated 231088b4f5fSWarner Losh } 232088b4f5fSWarner Losh end 233088b4f5fSWarner Losh 234088b4f5fSWarner Losh return menu.kernel_options; 235088b4f5fSWarner Losh end, 236088b4f5fSWarner Losh alias = {"k", "K"} 237088b4f5fSWarner Losh }, 238088b4f5fSWarner Losh 239088b4f5fSWarner Losh -- boot options 240088b4f5fSWarner Losh { 241088b4f5fSWarner Losh entry_type = "submenu", 242088b4f5fSWarner Losh name = function() 243088b4f5fSWarner Losh return "Boot "..color.highlight("O").."ptions"; 244088b4f5fSWarner Losh end, 245088b4f5fSWarner Losh submenu = function() 246088b4f5fSWarner Losh return menu.boot_options; 247088b4f5fSWarner Losh end, 248088b4f5fSWarner Losh alias = {"o", "O"} 249088b4f5fSWarner Losh } 250088b4f5fSWarner Losh 251088b4f5fSWarner Losh}; 252088b4f5fSWarner Losh 253088b4f5fSWarner Loshfunction menu.run(m) 254088b4f5fSWarner Losh 255088b4f5fSWarner Losh if (menu.skip()) then 256088b4f5fSWarner Losh core.autoboot(); 257088b4f5fSWarner Losh return false; 258088b4f5fSWarner Losh end 259088b4f5fSWarner Losh 260088b4f5fSWarner Losh if (m == nil) then 261088b4f5fSWarner Losh m = menu.welcome; 262088b4f5fSWarner Losh end 263088b4f5fSWarner Losh 264088b4f5fSWarner Losh -- redraw screen 265088b4f5fSWarner Losh screen.clear(); 266088b4f5fSWarner Losh screen.defcursor(); 267088b4f5fSWarner Losh local alias_table = drawer.drawscreen(m); 268088b4f5fSWarner Losh 269088b4f5fSWarner Losh-- menu.autoboot(); 270088b4f5fSWarner Losh 271088b4f5fSWarner Losh cont = true; 272088b4f5fSWarner Losh while cont do 273abc4f7e7SKyle Evans local key = io.getchar(); 274088b4f5fSWarner Losh 275*b458bf0dSKyle Evans -- Special key behaviors 276abc4f7e7SKyle Evans if (key == 127) and (m ~= menu.welcome) then 277abc4f7e7SKyle Evans break 278*b458bf0dSKyle Evans elseif (key == 13) then 279*b458bf0dSKyle Evans core.boot(); 280*b458bf0dSKyle Evans -- Should not return 281abc4f7e7SKyle Evans end 282abc4f7e7SKyle Evans 283abc4f7e7SKyle Evans key = string.char(key) 284088b4f5fSWarner Losh -- check to see if key is an alias 285088b4f5fSWarner Losh local sel_entry = nil; 286088b4f5fSWarner Losh for k, v in pairs(alias_table) do 287088b4f5fSWarner Losh if (key == k) then 288088b4f5fSWarner Losh sel_entry = v; 289088b4f5fSWarner Losh end 290088b4f5fSWarner Losh end 291088b4f5fSWarner Losh 292088b4f5fSWarner Losh -- if we have an alias do the assigned action: 293088b4f5fSWarner Losh if(sel_entry ~= nil) then 294088b4f5fSWarner Losh if (sel_entry.entry_type == "entry") then 295088b4f5fSWarner Losh -- run function 296088b4f5fSWarner Losh sel_entry.func(); 297088b4f5fSWarner Losh elseif (sel_entry.entry_type == "submenu") then 298088b4f5fSWarner Losh -- recurse 299088b4f5fSWarner Losh cont = menu.run(sel_entry.submenu()); 300088b4f5fSWarner Losh elseif (sel_entry.entry_type == "return") then 301088b4f5fSWarner Losh -- break recurse 302088b4f5fSWarner Losh cont = false; 303088b4f5fSWarner Losh end 304088b4f5fSWarner Losh -- if we got an alias key the screen is out of date: 305088b4f5fSWarner Losh screen.clear(); 306088b4f5fSWarner Losh screen.defcursor(); 307088b4f5fSWarner Losh alias_table = drawer.drawscreen(m); 308088b4f5fSWarner Losh end 309088b4f5fSWarner Losh end 310088b4f5fSWarner Losh 311088b4f5fSWarner Losh if (m == menu.welcome) then 312088b4f5fSWarner Losh screen.defcursor(); 313088b4f5fSWarner Losh print("Exiting menu!"); 314088b4f5fSWarner Losh return false; 315088b4f5fSWarner Losh end 316088b4f5fSWarner Losh 317088b4f5fSWarner Losh return true; 318088b4f5fSWarner Loshend 319088b4f5fSWarner Losh 320088b4f5fSWarner Loshfunction menu.skip() 321088b4f5fSWarner Losh if core.bootserial() then 322088b4f5fSWarner Losh return true; 323088b4f5fSWarner Losh end 324088b4f5fSWarner Losh local c = string.lower(loader.getenv("console") or ""); 325088b4f5fSWarner Losh if (c:match("^efi[ ;]") or c:match("[ ;]efi[ ;]")) ~= nil then 326088b4f5fSWarner Losh return true; 327088b4f5fSWarner Losh end 328088b4f5fSWarner Losh 329088b4f5fSWarner Losh c = string.lower(loader.getenv("beastie_disable") or ""); 330088b4f5fSWarner Losh print("beastie_disable", c); 331088b4f5fSWarner Losh return c == "yes"; 332088b4f5fSWarner Loshend 333088b4f5fSWarner Losh 334088b4f5fSWarner Loshfunction menu.autoboot() 335088b4f5fSWarner Losh if menu.already_autoboot == true then 336088b4f5fSWarner Losh return; 337088b4f5fSWarner Losh end 338088b4f5fSWarner Losh menu.already_autoboot = true; 339088b4f5fSWarner Losh 340088b4f5fSWarner Losh local ab = loader.getenv("autoboot_delay"); 341088b4f5fSWarner Losh if ab == "NO" or ab == "no" then 342088b4f5fSWarner Losh core.boot(); 343088b4f5fSWarner Losh end 344088b4f5fSWarner Losh ab = tonumber(ab) or 10; 345088b4f5fSWarner Losh 346088b4f5fSWarner Losh local x = loader.getenv("loader_menu_timeout_x") or 5; 347088b4f5fSWarner Losh local y = loader.getenv("loader_menu_timeout_y") or 22; 348088b4f5fSWarner Losh 349088b4f5fSWarner Losh local endtime = loader.time() + ab; 350088b4f5fSWarner Losh local time; 351088b4f5fSWarner Losh 352088b4f5fSWarner Losh repeat 353088b4f5fSWarner Losh time = endtime - loader.time(); 354088b4f5fSWarner Losh screen.setcursor(x, y); 355088b4f5fSWarner Losh print("Autoboot in "..time.." seconds, hit [Enter] to boot" 356088b4f5fSWarner Losh .." or any other key to stop "); 357088b4f5fSWarner Losh screen.defcursor(); 358088b4f5fSWarner Losh if io.ischar() then 359088b4f5fSWarner Losh local ch = io.getchar(); 360088b4f5fSWarner Losh if ch == 13 then 361088b4f5fSWarner Losh break; 362088b4f5fSWarner Losh else 363088b4f5fSWarner Losh -- prevent autoboot when escaping to interpreter 364088b4f5fSWarner Losh loader.setenv("autoboot_delay", "NO"); 365088b4f5fSWarner Losh -- erase autoboot msg 366088b4f5fSWarner Losh screen.setcursor(0, y); 367088b4f5fSWarner Losh print(" " 368088b4f5fSWarner Losh .." "); 369088b4f5fSWarner Losh screen.defcursor(); 370088b4f5fSWarner Losh return; 371088b4f5fSWarner Losh end 372088b4f5fSWarner Losh end 373088b4f5fSWarner Losh 374088b4f5fSWarner Losh loader.delay(50000); 375088b4f5fSWarner Losh until time <= 0 376088b4f5fSWarner Losh core.boot(); 377088b4f5fSWarner Losh 378088b4f5fSWarner Loshend 379088b4f5fSWarner Losh 380088b4f5fSWarner Loshfunction OnOff(str, b) 381088b4f5fSWarner Losh if (b) then 382088b4f5fSWarner Losh return str .. color.escapef(color.GREEN).."On"..color.escapef(color.WHITE); 383088b4f5fSWarner Losh else 384088b4f5fSWarner Losh return str .. color.escapef(color.RED).."off"..color.escapef(color.WHITE); 385088b4f5fSWarner Losh end 386088b4f5fSWarner Loshend 387088b4f5fSWarner Losh 388088b4f5fSWarner Loshreturn menu 389