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 29*aedd6be5SKyle Evanslocal config = require('config') 30fa4a2394SKyle Evans 31*aedd6be5SKyle Evanslocal core = {} 32088b4f5fSWarner Losh 336d4ed94dSKyle Evanslocal compose_loader_cmd = function(cmd_name, argstr) 346d4ed94dSKyle Evans if (argstr ~= nil) then 35*aedd6be5SKyle Evans cmd_name = cmd_name .. " " .. argstr 366d4ed94dSKyle Evans end 37*aedd6be5SKyle Evans return cmd_name 386d4ed94dSKyle Evansend 396d4ed94dSKyle Evans 406d3bcc06SKyle Evans-- Internal function 41f0cb3b6bSKyle Evans-- Parses arguments to boot and returns two values: kernel_name, argstr 42f0cb3b6bSKyle Evans-- Defaults to nil and "" respectively. 436d3bcc06SKyle Evans-- This will also parse arguments to autoboot, but the with_kernel argument 446d3bcc06SKyle Evans-- will need to be explicitly overwritten to false 456d3bcc06SKyle Evanslocal parse_boot_args = function(argv, with_kernel) 46f0cb3b6bSKyle Evans if (#argv == 0) then 47*aedd6be5SKyle Evans return nil, "" 48f0cb3b6bSKyle Evans end 496d3bcc06SKyle Evans if (with_kernel == nil) then 50*aedd6be5SKyle Evans with_kernel = true 516d3bcc06SKyle Evans end 52*aedd6be5SKyle Evans local kernel_name 53*aedd6be5SKyle Evans local argstr = "" 54f0cb3b6bSKyle Evans 55f0cb3b6bSKyle Evans for k, v in ipairs(argv) do 566d3bcc06SKyle Evans if (with_kernel) and (v:sub(1,1) ~= "-") then 57*aedd6be5SKyle Evans kernel_name = v 58f0cb3b6bSKyle Evans else 59*aedd6be5SKyle Evans argstr = argstr .. " " .. v 60f0cb3b6bSKyle Evans end 61f0cb3b6bSKyle Evans end 626d3bcc06SKyle Evans if (with_kernel) then 63*aedd6be5SKyle Evans return kernel_name, argstr 646d3bcc06SKyle Evans else 65*aedd6be5SKyle Evans return argstr 666d3bcc06SKyle Evans end 67f0cb3b6bSKyle Evansend 68f0cb3b6bSKyle Evans 69f0cb3b6bSKyle Evans-- Globals 70f0cb3b6bSKyle Evansfunction boot(...) 71*aedd6be5SKyle Evans local argv = {...} 72*aedd6be5SKyle Evans local cmd_name = "" 73*aedd6be5SKyle Evans cmd_name, argv = core.popFrontTable(argv) 74*aedd6be5SKyle Evans local kernel, argstr = parse_boot_args(argv) 75f0cb3b6bSKyle Evans if (kernel ~= nil) then 76*aedd6be5SKyle Evans loader.perform("unload") 77*aedd6be5SKyle Evans config.selectkernel(kernel) 78f0cb3b6bSKyle Evans end 79*aedd6be5SKyle Evans core.boot(argstr) 80f0cb3b6bSKyle Evansend 81f0cb3b6bSKyle Evans 826d3bcc06SKyle Evansfunction autoboot(...) 836d3bcc06SKyle Evans local argv = {...} 84*aedd6be5SKyle Evans local cmd_name = "" 85*aedd6be5SKyle Evans cmd_name, argv = core.popFrontTable(argv) 86*aedd6be5SKyle Evans local argstr = parse_boot_args(argv, false) 87*aedd6be5SKyle Evans core.autoboot(argstr) 886d3bcc06SKyle Evansend 896d3bcc06SKyle Evans 90b5746545SKyle Evans-- Module exports 91fe672a15SKyle Evans-- Commonly appearing constants 92*aedd6be5SKyle Evanscore.KEY_BACKSPACE = 8 93*aedd6be5SKyle Evanscore.KEY_ENTER = 13 94*aedd6be5SKyle Evanscore.KEY_DELETE = 127 95fe672a15SKyle Evans 96*aedd6be5SKyle Evanscore.KEYSTR_ESCAPE = "\027" 9739006570SKyle Evans 98*aedd6be5SKyle Evanscore.MENU_RETURN = "return" 99*aedd6be5SKyle Evanscore.MENU_ENTRY = "entry" 100*aedd6be5SKyle Evanscore.MENU_SEPARATOR = "separator" 101*aedd6be5SKyle Evanscore.MENU_SUBMENU = "submenu" 102*aedd6be5SKyle Evanscore.MENU_CAROUSEL_ENTRY = "carousel_entry" 103a7cf0562SKyle Evans 104088b4f5fSWarner Loshfunction core.setVerbose(b) 105088b4f5fSWarner Losh if (b == nil) then 106*aedd6be5SKyle Evans b = not core.verbose 107088b4f5fSWarner Losh end 108088b4f5fSWarner Losh 109088b4f5fSWarner Losh if (b == true) then 110*aedd6be5SKyle Evans loader.setenv("boot_verbose", "YES") 111088b4f5fSWarner Losh else 112*aedd6be5SKyle Evans loader.unsetenv("boot_verbose") 113088b4f5fSWarner Losh end 114*aedd6be5SKyle Evans core.verbose = b 115088b4f5fSWarner Loshend 116088b4f5fSWarner Losh 117088b4f5fSWarner Loshfunction core.setSingleUser(b) 118088b4f5fSWarner Losh if (b == nil) then 119*aedd6be5SKyle Evans b = not core.su 120088b4f5fSWarner Losh end 121088b4f5fSWarner Losh 122088b4f5fSWarner Losh if (b == true) then 123*aedd6be5SKyle Evans loader.setenv("boot_single", "YES") 124088b4f5fSWarner Losh else 125*aedd6be5SKyle Evans loader.unsetenv("boot_single") 126088b4f5fSWarner Losh end 127*aedd6be5SKyle Evans core.su = b 128088b4f5fSWarner Loshend 129088b4f5fSWarner Losh 1306401094fSKyle Evansfunction core.getACPIPresent(checkingSystemDefaults) 131*aedd6be5SKyle Evans local c = loader.getenv("hint.acpi.0.rsdp") 1326401094fSKyle Evans 1336401094fSKyle Evans if (c ~= nil) then 1346401094fSKyle Evans if (checkingSystemDefaults == true) then 135*aedd6be5SKyle Evans return true 1366401094fSKyle Evans end 1376401094fSKyle Evans -- Otherwise, respect disabled if it's set 138*aedd6be5SKyle Evans c = loader.getenv("hint.acpi.0.disabled") 139*aedd6be5SKyle Evans return (c == nil) or (tonumber(c) ~= 1) 1406401094fSKyle Evans end 141*aedd6be5SKyle Evans return false 1426401094fSKyle Evansend 1436401094fSKyle Evans 144088b4f5fSWarner Loshfunction core.setACPI(b) 145088b4f5fSWarner Losh if (b == nil) then 146*aedd6be5SKyle Evans b = not core.acpi 147088b4f5fSWarner Losh end 148088b4f5fSWarner Losh 149088b4f5fSWarner Losh if (b == true) then 150*aedd6be5SKyle Evans loader.setenv("acpi_load", "YES") 151*aedd6be5SKyle Evans loader.setenv("hint.acpi.0.disabled", "0") 152*aedd6be5SKyle Evans loader.unsetenv("loader.acpi_disabled_by_user") 153088b4f5fSWarner Losh else 154*aedd6be5SKyle Evans loader.unsetenv("acpi_load") 155*aedd6be5SKyle Evans loader.setenv("hint.acpi.0.disabled", "1") 156*aedd6be5SKyle Evans loader.setenv("loader.acpi_disabled_by_user", "1") 157088b4f5fSWarner Losh end 158*aedd6be5SKyle Evans core.acpi = b 159088b4f5fSWarner Loshend 160088b4f5fSWarner Losh 161088b4f5fSWarner Loshfunction core.setSafeMode(b) 162088b4f5fSWarner Losh if (b == nil) then 163*aedd6be5SKyle Evans b = not core.sm 164088b4f5fSWarner Losh end 165088b4f5fSWarner Losh if (b == true) then 166*aedd6be5SKyle Evans loader.setenv("kern.smp.disabled", "1") 167*aedd6be5SKyle Evans loader.setenv("hw.ata.ata_dma", "0") 168*aedd6be5SKyle Evans loader.setenv("hw.ata.atapi_dma", "0") 169*aedd6be5SKyle Evans loader.setenv("hw.ata.wc", "0") 170*aedd6be5SKyle Evans loader.setenv("hw.eisa_slots", "0") 171*aedd6be5SKyle Evans loader.setenv("kern.eventtimer.periodic", "1") 172*aedd6be5SKyle Evans loader.setenv("kern.geom.part.check_integrity", "0") 173088b4f5fSWarner Losh else 174*aedd6be5SKyle Evans loader.unsetenv("kern.smp.disabled") 175*aedd6be5SKyle Evans loader.unsetenv("hw.ata.ata_dma") 176*aedd6be5SKyle Evans loader.unsetenv("hw.ata.atapi_dma") 177*aedd6be5SKyle Evans loader.unsetenv("hw.ata.wc") 178*aedd6be5SKyle Evans loader.unsetenv("hw.eisa_slots") 179*aedd6be5SKyle Evans loader.unsetenv("kern.eventtimer.periodic") 180*aedd6be5SKyle Evans loader.unsetenv("kern.geom.part.check_integrity") 181088b4f5fSWarner Losh end 182*aedd6be5SKyle Evans core.sm = b 183088b4f5fSWarner Loshend 184088b4f5fSWarner Losh 185088b4f5fSWarner Loshfunction core.kernelList() 186*aedd6be5SKyle Evans local k = loader.getenv("kernel") 187*aedd6be5SKyle Evans local v = loader.getenv("kernels") or "" 188088b4f5fSWarner Losh 189*aedd6be5SKyle Evans local kernels = {} 190*aedd6be5SKyle Evans local unique = {} 191*aedd6be5SKyle Evans local i = 0 19224a1bd54SKyle Evans if (k ~= nil) then 193*aedd6be5SKyle Evans i = i + 1 194*aedd6be5SKyle Evans kernels[i] = k 195*aedd6be5SKyle Evans unique[k] = true 196088b4f5fSWarner Losh end 197088b4f5fSWarner Losh 198088b4f5fSWarner Losh for n in v:gmatch("([^; ]+)[; ]?") do 199a108046fSConrad Meyer if (unique[n] == nil) then 200*aedd6be5SKyle Evans i = i + 1 201*aedd6be5SKyle Evans kernels[i] = n 202*aedd6be5SKyle Evans unique[n] = true 203088b4f5fSWarner Losh end 204088b4f5fSWarner Losh end 205a108046fSConrad Meyer 206a108046fSConrad Meyer -- Automatically detect other bootable kernel directories using a 207a108046fSConrad Meyer -- heuristic. Any directory in /boot that contains an ordinary file 208a108046fSConrad Meyer -- named "kernel" is considered eligible. 209a108046fSConrad Meyer for file in lfs.dir("/boot") do 210*aedd6be5SKyle Evans local fname = "/boot/" .. file 211a108046fSConrad Meyer 212a108046fSConrad Meyer if (file == "." or file == "..") then 213*aedd6be5SKyle Evans goto continue 214a108046fSConrad Meyer end 215a108046fSConrad Meyer 216a108046fSConrad Meyer if (lfs.attributes(fname, "mode") ~= "directory") then 217*aedd6be5SKyle Evans goto continue 218a108046fSConrad Meyer end 219a108046fSConrad Meyer 220a108046fSConrad Meyer if (lfs.attributes(fname .. "/kernel", "mode") ~= "file") then 221*aedd6be5SKyle Evans goto continue 222a108046fSConrad Meyer end 223a108046fSConrad Meyer 224a108046fSConrad Meyer if (unique[file] == nil) then 225*aedd6be5SKyle Evans i = i + 1 226*aedd6be5SKyle Evans kernels[i] = file 227*aedd6be5SKyle Evans unique[file] = true 228a108046fSConrad Meyer end 229a108046fSConrad Meyer 230a108046fSConrad Meyer ::continue:: 231a108046fSConrad Meyer end 232*aedd6be5SKyle Evans return kernels 233088b4f5fSWarner Loshend 234088b4f5fSWarner Losh 235088b4f5fSWarner Loshfunction core.setDefaults() 236*aedd6be5SKyle Evans core.setACPI(core.getACPIPresent(true)) 237*aedd6be5SKyle Evans core.setSafeMode(false) 238*aedd6be5SKyle Evans core.setSingleUser(false) 239*aedd6be5SKyle Evans core.setVerbose(false) 240088b4f5fSWarner Loshend 241088b4f5fSWarner Losh 2426d4ed94dSKyle Evansfunction core.autoboot(argstr) 243*aedd6be5SKyle Evans config.loadelf() 244*aedd6be5SKyle Evans loader.perform(compose_loader_cmd("autoboot", argstr)) 245088b4f5fSWarner Loshend 246088b4f5fSWarner Losh 2476d4ed94dSKyle Evansfunction core.boot(argstr) 248*aedd6be5SKyle Evans config.loadelf() 249*aedd6be5SKyle Evans loader.perform(compose_loader_cmd("boot", argstr)) 250088b4f5fSWarner Loshend 251088b4f5fSWarner Losh 252e07fc39cSKyle Evansfunction core.isSingleUserBoot() 253*aedd6be5SKyle Evans local single_user = loader.getenv("boot_single") 254*aedd6be5SKyle Evans return single_user ~= nil and single_user:lower() == "yes" 255e07fc39cSKyle Evansend 256e07fc39cSKyle Evans 257b140d14bSKyle Evansfunction core.isSerialBoot() 258*aedd6be5SKyle Evans local c = loader.getenv("console") 259088b4f5fSWarner Losh 26024a1bd54SKyle Evans if (c ~= nil) then 26124a1bd54SKyle Evans if (c:find("comconsole") ~= nil) then 262*aedd6be5SKyle Evans return true 263088b4f5fSWarner Losh end 264088b4f5fSWarner Losh end 265088b4f5fSWarner Losh 266*aedd6be5SKyle Evans local s = loader.getenv("boot_serial") 26724a1bd54SKyle Evans if (s ~= nil) then 268*aedd6be5SKyle Evans return true 269088b4f5fSWarner Losh end 270088b4f5fSWarner Losh 271*aedd6be5SKyle Evans local m = loader.getenv("boot_multicons") 27224a1bd54SKyle Evans if (m ~= nil) then 273*aedd6be5SKyle Evans return true 274088b4f5fSWarner Losh end 275*aedd6be5SKyle Evans return false 276088b4f5fSWarner Loshend 277088b4f5fSWarner Losh 278c1ab36f5SKyle Evansfunction core.isSystem386() 279*aedd6be5SKyle Evans return (loader.machine_arch == "i386") 280c1ab36f5SKyle Evansend 281c1ab36f5SKyle Evans 2825c1b5165SKyle Evans-- This may be a better candidate for a 'utility' module. 2835c1b5165SKyle Evansfunction core.shallowCopyTable(tbl) 284*aedd6be5SKyle Evans local new_tbl = {} 2855c1b5165SKyle Evans for k, v in pairs(tbl) do 2865c1b5165SKyle Evans if (type(v) == "table") then 287*aedd6be5SKyle Evans new_tbl[k] = core.shallowCopyTable(v) 2885c1b5165SKyle Evans else 289*aedd6be5SKyle Evans new_tbl[k] = v 2905c1b5165SKyle Evans end 2915c1b5165SKyle Evans end 292*aedd6be5SKyle Evans return new_tbl 2935c1b5165SKyle Evansend 2945c1b5165SKyle Evans 2956d4ed94dSKyle Evans-- XXX This should go away if we get the table lib into shape for importing. 2966d4ed94dSKyle Evans-- As of now, it requires some 'os' functions, so we'll implement this in lua 2976d4ed94dSKyle Evans-- for our uses 2986d4ed94dSKyle Evansfunction core.popFrontTable(tbl) 2996d4ed94dSKyle Evans -- Shouldn't reasonably happen 3006d4ed94dSKyle Evans if (#tbl == 0) then 301*aedd6be5SKyle Evans return nil, nil 3026d4ed94dSKyle Evans elseif (#tbl == 1) then 303*aedd6be5SKyle Evans return tbl[1], {} 3046d4ed94dSKyle Evans end 3056d4ed94dSKyle Evans 306*aedd6be5SKyle Evans local first_value = tbl[1] 307*aedd6be5SKyle Evans local new_tbl = {} 3086d4ed94dSKyle Evans -- This is not a cheap operation 3096d4ed94dSKyle Evans for k, v in ipairs(tbl) do 3106d4ed94dSKyle Evans if (k > 1) then 311*aedd6be5SKyle Evans new_tbl[k - 1] = v 3126d4ed94dSKyle Evans end 3136d4ed94dSKyle Evans end 3146d4ed94dSKyle Evans 315*aedd6be5SKyle Evans return first_value, new_tbl 3166d4ed94dSKyle Evansend 3176d4ed94dSKyle Evans 3186f412147SKyle Evans-- On i386, hint.acpi.0.rsdp will be set before we're loaded. On !i386, it will 3196f412147SKyle Evans-- generally be set upon execution of the kernel. Because of this, we can't (or 3206f412147SKyle Evans-- don't really want to) detect/disable ACPI on !i386 reliably. Just set it 3216f412147SKyle Evans-- enabled if we detect it and leave well enough alone if we don't. 322c1ab36f5SKyle Evansif (core.isSystem386()) and (core.getACPIPresent(false)) then 323*aedd6be5SKyle Evans core.setACPI(true) 3246f412147SKyle Evansend 325*aedd6be5SKyle Evansreturn core 326