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 53*7efc058fSKyle Evanslocal bootenvSet = function(env) 54*7efc058fSKyle Evans loader.setenv("vfs.root.mountfrom", env) 55*7efc058fSKyle Evans loader.setenv("currdev", env .. ":") 56*7efc058fSKyle Evans config.reload() 57*7efc058fSKyle Evansend 58*7efc058fSKyle Evans 59b5746545SKyle Evans-- Module exports 608d415029SKyle Evansmenu.handlers = { 618d415029SKyle Evans -- Menu handlers take the current menu and selected entry as parameters, 628d415029SKyle Evans -- and should return a boolean indicating whether execution should 638d415029SKyle Evans -- continue or not. The return value may be omitted if this entry should 648d415029SKyle Evans -- have no bearing on whether we continue or not, indicating that we 658d415029SKyle Evans -- should just continue after execution. 668d415029SKyle Evans [core.MENU_ENTRY] = function(current_menu, entry) 678d415029SKyle Evans -- run function 68aedd6be5SKyle Evans entry.func() 698d415029SKyle Evans end, 708d415029SKyle Evans [core.MENU_CAROUSEL_ENTRY] = function(current_menu, entry) 718d415029SKyle Evans -- carousel (rotating) functionality 72aedd6be5SKyle Evans local carid = entry.carousel_id 73aedd6be5SKyle Evans local caridx = config.getCarouselIndex(carid) 744f437f9eSKyle Evans local choices = entry.items 754f437f9eSKyle Evans if type(choices) == "function" then 764f437f9eSKyle Evans choices = choices() 774f437f9eSKyle Evans end 789f71d421SKyle Evans if #choices > 0 then 79aedd6be5SKyle Evans caridx = (caridx % #choices) + 1 80aedd6be5SKyle Evans config.setCarouselIndex(carid, caridx) 81aedd6be5SKyle Evans entry.func(caridx, choices[caridx], choices) 828d415029SKyle Evans end 838d415029SKyle Evans end, 848d415029SKyle Evans [core.MENU_SUBMENU] = function(current_menu, entry) 858d415029SKyle Evans -- recurse 869a28f948SKyle Evans return menu.run(entry.submenu) 878d415029SKyle Evans end, 888d415029SKyle Evans [core.MENU_RETURN] = function(current_menu, entry) 898d415029SKyle Evans -- allow entry to have a function/side effect 909f71d421SKyle Evans if entry.func ~= nil then 91aedd6be5SKyle Evans entry.func() 928d415029SKyle Evans end 93aedd6be5SKyle Evans return false 948d415029SKyle Evans end, 95aedd6be5SKyle Evans} 96280e990bSKyle Evans-- loader menu tree is rooted at menu.welcome 97088b4f5fSWarner Losh 98*7efc058fSKyle Evansmenu.boot_environments = { 99*7efc058fSKyle Evans entries = { 100*7efc058fSKyle Evans -- return to welcome menu 101*7efc058fSKyle Evans { 102*7efc058fSKyle Evans entry_type = core.MENU_RETURN, 103*7efc058fSKyle Evans name = "Back to main menu" .. 104*7efc058fSKyle Evans color.highlight(" [Backspace]"), 105*7efc058fSKyle Evans }, 106*7efc058fSKyle Evans { 107*7efc058fSKyle Evans entry_type = core.MENU_CAROUSEL_ENTRY, 108*7efc058fSKyle Evans carousel_id = "be_active", 109*7efc058fSKyle Evans items = core.bootenvList, 110*7efc058fSKyle Evans name = function(idx, choice, all_choices) 111*7efc058fSKyle Evans if #all_choices == 0 then 112*7efc058fSKyle Evans return "Active: " 113*7efc058fSKyle Evans end 114*7efc058fSKyle Evans 115*7efc058fSKyle Evans local is_default = (idx == 1) 116*7efc058fSKyle Evans local bootenv_name = "" 117*7efc058fSKyle Evans local name_color 118*7efc058fSKyle Evans if is_default then 119*7efc058fSKyle Evans name_color = color.escapef(color.GREEN) 120*7efc058fSKyle Evans else 121*7efc058fSKyle Evans name_color = color.escapef(color.BLUE) 122*7efc058fSKyle Evans end 123*7efc058fSKyle Evans bootenv_name = bootenv_name .. name_color .. 124*7efc058fSKyle Evans choice .. color.default() 125*7efc058fSKyle Evans return color.highlight("A").."ctive: " .. 126*7efc058fSKyle Evans bootenv_name .. " (" .. idx .. " of " .. 127*7efc058fSKyle Evans #all_choices .. ")" 128*7efc058fSKyle Evans end, 129*7efc058fSKyle Evans func = function(idx, choice, all_choices) 130*7efc058fSKyle Evans bootenvSet(choice) 131*7efc058fSKyle Evans end, 132*7efc058fSKyle Evans alias = {"a", "A"}, 133*7efc058fSKyle Evans }, 134*7efc058fSKyle Evans { 135*7efc058fSKyle Evans entry_type = core.MENU_ENTRY, 136*7efc058fSKyle Evans name = function() 137*7efc058fSKyle Evans return color.highlight("b") .. "ootfs: " .. 138*7efc058fSKyle Evans core.bootenvDefault() 139*7efc058fSKyle Evans end, 140*7efc058fSKyle Evans func = function() 141*7efc058fSKyle Evans -- Reset active boot environment to the default 142*7efc058fSKyle Evans config.setCarouselIndex("be_active", 1) 143*7efc058fSKyle Evans bootenvSet(core.bootenvDefault()) 144*7efc058fSKyle Evans end, 145*7efc058fSKyle Evans alias = {"b", "B"}, 146*7efc058fSKyle Evans }, 147*7efc058fSKyle Evans }, 148*7efc058fSKyle Evans} 149*7efc058fSKyle Evans 150088b4f5fSWarner Loshmenu.boot_options = { 151d8757746SKyle Evans entries = { 152088b4f5fSWarner Losh -- return to welcome menu 153088b4f5fSWarner Losh { 154a7cf0562SKyle Evans entry_type = core.MENU_RETURN, 155a51f9f0cSKyle Evans name = "Back to main menu" .. 156a51f9f0cSKyle Evans color.highlight(" [Backspace]"), 157088b4f5fSWarner Losh }, 158088b4f5fSWarner Losh -- load defaults 159088b4f5fSWarner Losh { 160a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 161a51f9f0cSKyle Evans name = "Load System " .. color.highlight("D") .. 162a51f9f0cSKyle Evans "efaults", 163a51f9f0cSKyle Evans func = core.setDefaults, 164088b4f5fSWarner Losh alias = {"d", "D"} 165088b4f5fSWarner Losh }, 166088b4f5fSWarner Losh { 167a7cf0562SKyle Evans entry_type = core.MENU_SEPARATOR, 168088b4f5fSWarner Losh }, 169088b4f5fSWarner Losh { 170a7cf0562SKyle Evans entry_type = core.MENU_SEPARATOR, 171a51f9f0cSKyle Evans name = "Boot Options:", 172088b4f5fSWarner Losh }, 173088b4f5fSWarner Losh -- acpi 174088b4f5fSWarner Losh { 175a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 176c1ab36f5SKyle Evans visible = core.isSystem386, 177088b4f5fSWarner Losh name = function() 178fd2b19b3SKyle Evans return OnOff(color.highlight("A") .. 179aedd6be5SKyle Evans "CPI :", core.acpi) 180088b4f5fSWarner Losh end, 181a51f9f0cSKyle Evans func = core.setACPI, 182088b4f5fSWarner Losh alias = {"a", "A"} 183088b4f5fSWarner Losh }, 184088b4f5fSWarner Losh -- safe mode 185088b4f5fSWarner Losh { 186a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 187088b4f5fSWarner Losh name = function() 18857099121SKyle Evans return OnOff("Safe " .. color.highlight("M") .. 189aedd6be5SKyle Evans "ode :", core.sm) 190088b4f5fSWarner Losh end, 191a51f9f0cSKyle Evans func = core.setSafeMode, 192088b4f5fSWarner Losh alias = {"m", "M"} 193088b4f5fSWarner Losh }, 194088b4f5fSWarner Losh -- single user 195088b4f5fSWarner Losh { 196a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 197088b4f5fSWarner Losh name = function() 198fd2b19b3SKyle Evans return OnOff(color.highlight("S") .. 199aedd6be5SKyle Evans "ingle user:", core.su) 200088b4f5fSWarner Losh end, 201a51f9f0cSKyle Evans func = core.setSingleUser, 202088b4f5fSWarner Losh alias = {"s", "S"} 203088b4f5fSWarner Losh }, 204088b4f5fSWarner Losh -- verbose boot 205088b4f5fSWarner Losh { 206a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 207088b4f5fSWarner Losh name = function() 208fd2b19b3SKyle Evans return OnOff(color.highlight("V") .. 209aedd6be5SKyle Evans "erbose :", core.verbose) 210088b4f5fSWarner Losh end, 211a51f9f0cSKyle Evans func = core.setVerbose, 212088b4f5fSWarner Losh alias = {"v", "V"} 213088b4f5fSWarner Losh }, 214d8757746SKyle Evans }, 215aedd6be5SKyle Evans} 216088b4f5fSWarner Losh 217088b4f5fSWarner Loshmenu.welcome = { 218303253e5SKyle Evans entries = function() 219aedd6be5SKyle Evans local menu_entries = menu.welcome.all_entries 220303253e5SKyle Evans -- Swap the first two menu items on single user boot 2219f71d421SKyle Evans if core.isSingleUserBoot() then 2229a0904b0SKyle Evans -- We'll cache the swapped menu, for performance 2239f71d421SKyle Evans if menu.welcome.swapped_menu ~= nil then 224aedd6be5SKyle Evans return menu.welcome.swapped_menu 2259a0904b0SKyle Evans end 2265c1b5165SKyle Evans -- Shallow copy the table 227aedd6be5SKyle Evans menu_entries = core.shallowCopyTable(menu_entries) 2285c1b5165SKyle Evans 2299a0904b0SKyle Evans -- Swap the first two menu entries 2304b6da14cSKyle Evans menu_entries[1], menu_entries[2] = 231aedd6be5SKyle Evans menu_entries[2], menu_entries[1] 232303253e5SKyle Evans 2339a0904b0SKyle Evans -- Then set their names to their alternate names 2349a0904b0SKyle Evans menu_entries[1].name, menu_entries[2].name = 2359a0904b0SKyle Evans menu_entries[1].alternate_name, 236aedd6be5SKyle Evans menu_entries[2].alternate_name 237aedd6be5SKyle Evans menu.welcome.swapped_menu = menu_entries 238303253e5SKyle Evans end 239aedd6be5SKyle Evans return menu_entries 240303253e5SKyle Evans end, 241303253e5SKyle Evans all_entries = { 242088b4f5fSWarner Losh -- boot multi user 243088b4f5fSWarner Losh { 244a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 245a51f9f0cSKyle Evans name = color.highlight("B") .. "oot Multi user " .. 246a51f9f0cSKyle Evans color.highlight("[Enter]"), 2475c1b5165SKyle Evans -- Not a standard menu entry function! 248a51f9f0cSKyle Evans alternate_name = color.highlight("B") .. 249a51f9f0cSKyle Evans "oot Multi user", 250088b4f5fSWarner Losh func = function() 251aedd6be5SKyle Evans core.setSingleUser(false) 252aedd6be5SKyle Evans core.boot() 253088b4f5fSWarner Losh end, 254b458bf0dSKyle Evans alias = {"b", "B"} 255088b4f5fSWarner Losh }, 256088b4f5fSWarner Losh -- boot single user 257088b4f5fSWarner Losh { 258a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 259a51f9f0cSKyle Evans name = "Boot " .. color.highlight("S") .. "ingle user", 2605c1b5165SKyle Evans -- Not a standard menu entry function! 261a51f9f0cSKyle Evans alternate_name = "Boot " .. color.highlight("S") .. 262a51f9f0cSKyle Evans "ingle user " .. color.highlight("[Enter]"), 263088b4f5fSWarner Losh func = function() 264aedd6be5SKyle Evans core.setSingleUser(true) 265aedd6be5SKyle Evans core.boot() 266088b4f5fSWarner Losh end, 267088b4f5fSWarner Losh alias = {"s", "S"} 268088b4f5fSWarner Losh }, 269088b4f5fSWarner Losh -- escape to interpreter 270088b4f5fSWarner Losh { 271a7cf0562SKyle Evans entry_type = core.MENU_RETURN, 272a51f9f0cSKyle Evans name = color.highlight("Esc") .. "ape to loader prompt", 273ef625845SKyle Evans func = function() 274aedd6be5SKyle Evans loader.setenv("autoboot_delay", "NO") 275ef625845SKyle Evans end, 27639006570SKyle Evans alias = {core.KEYSTR_ESCAPE} 277088b4f5fSWarner Losh }, 278088b4f5fSWarner Losh -- reboot 279088b4f5fSWarner Losh { 280a7cf0562SKyle Evans entry_type = core.MENU_ENTRY, 281a51f9f0cSKyle Evans name = color.highlight("R") .. "eboot", 282088b4f5fSWarner Losh func = function() 283aedd6be5SKyle Evans loader.perform("reboot") 284088b4f5fSWarner Losh end, 285088b4f5fSWarner Losh alias = {"r", "R"} 286088b4f5fSWarner Losh }, 287088b4f5fSWarner Losh { 288a7cf0562SKyle Evans entry_type = core.MENU_SEPARATOR, 289088b4f5fSWarner Losh }, 290088b4f5fSWarner Losh { 291a7cf0562SKyle Evans entry_type = core.MENU_SEPARATOR, 292a51f9f0cSKyle Evans name = "Options:", 293088b4f5fSWarner Losh }, 294088b4f5fSWarner Losh -- kernel options 295088b4f5fSWarner Losh { 296a7cf0562SKyle Evans entry_type = core.MENU_CAROUSEL_ENTRY, 297ada26c4aSKyle Evans carousel_id = "kernel", 298ada26c4aSKyle Evans items = core.kernelList, 299ada26c4aSKyle Evans name = function(idx, choice, all_choices) 3009f71d421SKyle Evans if #all_choices == 0 then 301aedd6be5SKyle Evans return "Kernel: " 302088b4f5fSWarner Losh end 303b1b1f2b8SKyle Evans 304aedd6be5SKyle Evans local is_default = (idx == 1) 305aedd6be5SKyle Evans local kernel_name = "" 306aedd6be5SKyle Evans local name_color 3079f71d421SKyle Evans if is_default then 308aedd6be5SKyle Evans name_color = color.escapef(color.GREEN) 309aedd6be5SKyle Evans kernel_name = "default/" 310bcf48a15SKyle Evans else 311aedd6be5SKyle Evans name_color = color.escapef(color.BLUE) 312b1b1f2b8SKyle Evans end 313fd2b19b3SKyle Evans kernel_name = kernel_name .. name_color .. 314aedd6be5SKyle Evans choice .. color.default() 315fd2b19b3SKyle Evans return color.highlight("K") .. "ernel: " .. 316fd2b19b3SKyle Evans kernel_name .. " (" .. idx .. " of " .. 317aedd6be5SKyle Evans #all_choices .. ")" 318088b4f5fSWarner Losh end, 3195d1e2f83SKyle Evans func = function(idx, choice, all_choices) 320aedd6be5SKyle Evans config.selectkernel(choice) 321088b4f5fSWarner Losh end, 322088b4f5fSWarner Losh alias = {"k", "K"} 323088b4f5fSWarner Losh }, 324088b4f5fSWarner Losh -- boot options 325088b4f5fSWarner Losh { 326a7cf0562SKyle Evans entry_type = core.MENU_SUBMENU, 327a51f9f0cSKyle Evans name = "Boot " .. color.highlight("O") .. "ptions", 3289a28f948SKyle Evans submenu = menu.boot_options, 329088b4f5fSWarner Losh alias = {"o", "O"} 330d8757746SKyle Evans }, 331*7efc058fSKyle Evans -- boot environments 332*7efc058fSKyle Evans { 333*7efc058fSKyle Evans entry_type = core.MENU_SUBMENU, 334*7efc058fSKyle Evans visible = function() 335*7efc058fSKyle Evans return core.isZFSBoot() and 336*7efc058fSKyle Evans #core.bootenvList() > 1 337*7efc058fSKyle Evans end, 338*7efc058fSKyle Evans name = "Boot " .. color.highlight("E") .. "nvironments", 339*7efc058fSKyle Evans submenu = menu.boot_environments, 340*7efc058fSKyle Evans alias = {"e", "E"}, 341*7efc058fSKyle Evans }, 342d8757746SKyle Evans }, 343aedd6be5SKyle Evans} 344088b4f5fSWarner Losh 34520a81676SKyle Evansmenu.default = menu.welcome 34620a81676SKyle Evans 347088b4f5fSWarner Loshfunction menu.run(m) 348088b4f5fSWarner Losh 3499f71d421SKyle Evans if menu.skip() then 350aedd6be5SKyle Evans core.autoboot() 351aedd6be5SKyle Evans return false 352088b4f5fSWarner Losh end 353088b4f5fSWarner Losh 3549f71d421SKyle Evans if m == nil then 35520a81676SKyle Evans m = menu.default 356088b4f5fSWarner Losh end 357088b4f5fSWarner Losh 358088b4f5fSWarner Losh -- redraw screen 359aedd6be5SKyle Evans screen.clear() 360aedd6be5SKyle Evans screen.defcursor() 361aedd6be5SKyle Evans local alias_table = drawer.drawscreen(m) 362088b4f5fSWarner Losh 36312b95c84SKyle Evans -- Might return nil, that's ok 36412b95c84SKyle Evans local autoboot_key = menu.autoboot() 365088b4f5fSWarner Losh 366aedd6be5SKyle Evans cont = true 3679f71d421SKyle Evans while cont do 36812b95c84SKyle Evans local key = autoboot_key or io.getchar() 36912b95c84SKyle Evans autoboot_key = nil 370088b4f5fSWarner Losh 371b458bf0dSKyle Evans -- Special key behaviors 3729f71d421SKyle Evans if (key == core.KEY_BACKSPACE or key == core.KEY_DELETE) and 37320a81676SKyle Evans m ~= menu.default then 374aedd6be5SKyle Evans break 3759f71d421SKyle Evans elseif key == core.KEY_ENTER then 376aedd6be5SKyle Evans core.boot() 377b458bf0dSKyle Evans -- Should not return 378abc4f7e7SKyle Evans end 379abc4f7e7SKyle Evans 380abc4f7e7SKyle Evans key = string.char(key) 381088b4f5fSWarner Losh -- check to see if key is an alias 382aedd6be5SKyle Evans local sel_entry = nil 383088b4f5fSWarner Losh for k, v in pairs(alias_table) do 3849f71d421SKyle Evans if key == k then 385aedd6be5SKyle Evans sel_entry = v 386088b4f5fSWarner Losh end 387088b4f5fSWarner Losh end 388088b4f5fSWarner Losh 389088b4f5fSWarner Losh -- if we have an alias do the assigned action: 3909f71d421SKyle Evans if sel_entry ~= nil then 3918d415029SKyle Evans -- Get menu handler 392aedd6be5SKyle Evans local handler = menu.handlers[sel_entry.entry_type] 3939f71d421SKyle Evans if handler ~= nil then 3948d415029SKyle Evans -- The handler's return value indicates whether 3958d415029SKyle Evans -- we need to exit this menu. An omitted return 3968d415029SKyle Evans -- value means "continue" by default. 397aedd6be5SKyle Evans cont = handler(m, sel_entry) 3989f71d421SKyle Evans if cont == nil then 399aedd6be5SKyle Evans cont = true 400aefcaa7eSKyle Evans end 401088b4f5fSWarner Losh end 402088b4f5fSWarner Losh -- if we got an alias key the screen is out of date: 403aedd6be5SKyle Evans screen.clear() 404aedd6be5SKyle Evans screen.defcursor() 405aedd6be5SKyle Evans alias_table = drawer.drawscreen(m) 406088b4f5fSWarner Losh end 407088b4f5fSWarner Losh end 408088b4f5fSWarner Losh 40920a81676SKyle Evans if m == menu.default then 410aedd6be5SKyle Evans screen.defcursor() 411aedd6be5SKyle Evans print("Exiting menu!") 412aedd6be5SKyle Evans return false 413088b4f5fSWarner Losh end 414088b4f5fSWarner Losh 415aedd6be5SKyle Evans return true 416088b4f5fSWarner Loshend 417088b4f5fSWarner Losh 418088b4f5fSWarner Loshfunction menu.skip() 4199f71d421SKyle Evans if core.isSerialBoot() then 420aedd6be5SKyle Evans return true 421088b4f5fSWarner Losh end 422aedd6be5SKyle Evans local c = string.lower(loader.getenv("console") or "") 4239f71d421SKyle Evans if c:match("^efi[ ;]") ~= nil or c:match("[ ;]efi[ ;]") ~= nil then 424aedd6be5SKyle Evans return true 425088b4f5fSWarner Losh end 426088b4f5fSWarner Losh 427aedd6be5SKyle Evans c = string.lower(loader.getenv("beastie_disable") or "") 428aedd6be5SKyle Evans print("beastie_disable", c) 429aedd6be5SKyle Evans return c == "yes" 430088b4f5fSWarner Loshend 431088b4f5fSWarner Losh 432088b4f5fSWarner Loshfunction menu.autoboot() 43349550489SKyle Evans if menu.already_autoboot then 43412b95c84SKyle Evans return nil 435088b4f5fSWarner Losh end 436aedd6be5SKyle Evans menu.already_autoboot = true 437088b4f5fSWarner Losh 438aedd6be5SKyle Evans local ab = loader.getenv("autoboot_delay") 4399f71d421SKyle Evans if ab ~= nil and ab:lower() == "no" then 44012b95c84SKyle Evans return nil 4419f71d421SKyle Evans elseif tonumber(ab) == -1 then 442aedd6be5SKyle Evans core.boot() 443088b4f5fSWarner Losh end 444aedd6be5SKyle Evans ab = tonumber(ab) or 10 445088b4f5fSWarner Losh 446aedd6be5SKyle Evans local x = loader.getenv("loader_menu_timeout_x") or 5 447aedd6be5SKyle Evans local y = loader.getenv("loader_menu_timeout_y") or 22 448088b4f5fSWarner Losh 449aedd6be5SKyle Evans local endtime = loader.time() + ab 450aedd6be5SKyle Evans local time 451088b4f5fSWarner Losh 452088b4f5fSWarner Losh repeat 453aedd6be5SKyle Evans time = endtime - loader.time() 454aedd6be5SKyle Evans screen.setcursor(x, y) 45557099121SKyle Evans print("Autoboot in " .. time .. 45657099121SKyle Evans " seconds, hit [Enter] to boot" .. 457aedd6be5SKyle Evans " or any other key to stop ") 458aedd6be5SKyle Evans screen.defcursor() 4599f71d421SKyle Evans if io.ischar() then 460aedd6be5SKyle Evans local ch = io.getchar() 4619f71d421SKyle Evans if ch == core.KEY_ENTER then 462aedd6be5SKyle Evans break 463088b4f5fSWarner Losh else 464088b4f5fSWarner Losh -- erase autoboot msg 465aedd6be5SKyle Evans screen.setcursor(0, y) 466088b4f5fSWarner Losh print(" " 467aedd6be5SKyle Evans .. " ") 468aedd6be5SKyle Evans screen.defcursor() 46912b95c84SKyle Evans return ch 470088b4f5fSWarner Losh end 471088b4f5fSWarner Losh end 472088b4f5fSWarner Losh 473aedd6be5SKyle Evans loader.delay(50000) 474aedd6be5SKyle Evans until time <= 0 475aedd6be5SKyle Evans core.boot() 476088b4f5fSWarner Losh 477088b4f5fSWarner Loshend 478088b4f5fSWarner Losh 479aedd6be5SKyle Evansreturn menu 480