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 29aedd6be5SKyle Evanslocal config = require('config') 30fa4a2394SKyle Evans 31aedd6be5SKyle Evanslocal core = {} 32088b4f5fSWarner Losh 336d4ed94dSKyle Evanslocal compose_loader_cmd = function(cmd_name, argstr) 349f71d421SKyle Evans if argstr ~= nil then 35aedd6be5SKyle Evans cmd_name = cmd_name .. " " .. argstr 366d4ed94dSKyle Evans end 37aedd6be5SKyle 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) 469f71d421SKyle Evans if with_kernel == nil then 47aedd6be5SKyle Evans with_kernel = true 486d3bcc06SKyle Evans end 49*1d38e553SKyle Evans if #argv == 0 then 50*1d38e553SKyle Evans if with_kernel then 51*1d38e553SKyle Evans return nil, "" 52*1d38e553SKyle Evans else 53*1d38e553SKyle Evans return "" 54*1d38e553SKyle Evans end 55*1d38e553SKyle Evans end 56aedd6be5SKyle Evans local kernel_name 57aedd6be5SKyle Evans local argstr = "" 58f0cb3b6bSKyle Evans 59f0cb3b6bSKyle Evans for k, v in ipairs(argv) do 609f71d421SKyle Evans if with_kernel and v:sub(1,1) ~= "-" then 61aedd6be5SKyle Evans kernel_name = v 62f0cb3b6bSKyle Evans else 63aedd6be5SKyle Evans argstr = argstr .. " " .. v 64f0cb3b6bSKyle Evans end 65f0cb3b6bSKyle Evans end 669f71d421SKyle Evans if with_kernel then 67aedd6be5SKyle Evans return kernel_name, argstr 686d3bcc06SKyle Evans else 69aedd6be5SKyle Evans return argstr 706d3bcc06SKyle Evans end 71f0cb3b6bSKyle Evansend 72f0cb3b6bSKyle Evans 73f0cb3b6bSKyle Evans-- Globals 74f0cb3b6bSKyle Evansfunction boot(...) 75aedd6be5SKyle Evans local argv = {...} 76aedd6be5SKyle Evans local cmd_name = "" 77aedd6be5SKyle Evans cmd_name, argv = core.popFrontTable(argv) 78aedd6be5SKyle Evans local kernel, argstr = parse_boot_args(argv) 799f71d421SKyle Evans if kernel ~= nil then 80aedd6be5SKyle Evans loader.perform("unload") 81aedd6be5SKyle Evans config.selectkernel(kernel) 82f0cb3b6bSKyle Evans end 83aedd6be5SKyle Evans core.boot(argstr) 84f0cb3b6bSKyle Evansend 85f0cb3b6bSKyle Evans 866d3bcc06SKyle Evansfunction autoboot(...) 876d3bcc06SKyle Evans local argv = {...} 88aedd6be5SKyle Evans local cmd_name = "" 89aedd6be5SKyle Evans cmd_name, argv = core.popFrontTable(argv) 90aedd6be5SKyle Evans local argstr = parse_boot_args(argv, false) 91aedd6be5SKyle Evans core.autoboot(argstr) 926d3bcc06SKyle Evansend 936d3bcc06SKyle Evans 94b5746545SKyle Evans-- Module exports 95fe672a15SKyle Evans-- Commonly appearing constants 96aedd6be5SKyle Evanscore.KEY_BACKSPACE = 8 97aedd6be5SKyle Evanscore.KEY_ENTER = 13 98aedd6be5SKyle Evanscore.KEY_DELETE = 127 99fe672a15SKyle Evans 100aedd6be5SKyle Evanscore.KEYSTR_ESCAPE = "\027" 10139006570SKyle Evans 102aedd6be5SKyle Evanscore.MENU_RETURN = "return" 103aedd6be5SKyle Evanscore.MENU_ENTRY = "entry" 104aedd6be5SKyle Evanscore.MENU_SEPARATOR = "separator" 105aedd6be5SKyle Evanscore.MENU_SUBMENU = "submenu" 106aedd6be5SKyle Evanscore.MENU_CAROUSEL_ENTRY = "carousel_entry" 107a7cf0562SKyle Evans 108088b4f5fSWarner Loshfunction core.setVerbose(b) 1099f71d421SKyle Evans if b == nil then 110aedd6be5SKyle Evans b = not core.verbose 111088b4f5fSWarner Losh end 112088b4f5fSWarner Losh 11349550489SKyle Evans if b then 114aedd6be5SKyle Evans loader.setenv("boot_verbose", "YES") 115088b4f5fSWarner Losh else 116aedd6be5SKyle Evans loader.unsetenv("boot_verbose") 117088b4f5fSWarner Losh end 118aedd6be5SKyle Evans core.verbose = b 119088b4f5fSWarner Loshend 120088b4f5fSWarner Losh 121088b4f5fSWarner Loshfunction core.setSingleUser(b) 1229f71d421SKyle Evans if b == nil then 123aedd6be5SKyle Evans b = not core.su 124088b4f5fSWarner Losh end 125088b4f5fSWarner Losh 12649550489SKyle Evans if b then 127aedd6be5SKyle Evans loader.setenv("boot_single", "YES") 128088b4f5fSWarner Losh else 129aedd6be5SKyle Evans loader.unsetenv("boot_single") 130088b4f5fSWarner Losh end 131aedd6be5SKyle Evans core.su = b 132088b4f5fSWarner Loshend 133088b4f5fSWarner Losh 1346401094fSKyle Evansfunction core.getACPIPresent(checkingSystemDefaults) 135aedd6be5SKyle Evans local c = loader.getenv("hint.acpi.0.rsdp") 1366401094fSKyle Evans 1379f71d421SKyle Evans if c ~= nil then 13849550489SKyle Evans if checkingSystemDefaults then 139aedd6be5SKyle Evans return true 1406401094fSKyle Evans end 1416401094fSKyle Evans -- Otherwise, respect disabled if it's set 142aedd6be5SKyle Evans c = loader.getenv("hint.acpi.0.disabled") 1439f71d421SKyle Evans return c == nil or tonumber(c) ~= 1 1446401094fSKyle Evans end 145aedd6be5SKyle Evans return false 1466401094fSKyle Evansend 1476401094fSKyle Evans 148088b4f5fSWarner Loshfunction core.setACPI(b) 1499f71d421SKyle Evans if b == nil then 150aedd6be5SKyle Evans b = not core.acpi 151088b4f5fSWarner Losh end 152088b4f5fSWarner Losh 15349550489SKyle Evans if b then 154aedd6be5SKyle Evans loader.setenv("acpi_load", "YES") 155aedd6be5SKyle Evans loader.setenv("hint.acpi.0.disabled", "0") 156aedd6be5SKyle Evans loader.unsetenv("loader.acpi_disabled_by_user") 157088b4f5fSWarner Losh else 158aedd6be5SKyle Evans loader.unsetenv("acpi_load") 159aedd6be5SKyle Evans loader.setenv("hint.acpi.0.disabled", "1") 160aedd6be5SKyle Evans loader.setenv("loader.acpi_disabled_by_user", "1") 161088b4f5fSWarner Losh end 162aedd6be5SKyle Evans core.acpi = b 163088b4f5fSWarner Loshend 164088b4f5fSWarner Losh 165088b4f5fSWarner Loshfunction core.setSafeMode(b) 1669f71d421SKyle Evans if b == nil then 167aedd6be5SKyle Evans b = not core.sm 168088b4f5fSWarner Losh end 16949550489SKyle Evans if b then 170aedd6be5SKyle Evans loader.setenv("kern.smp.disabled", "1") 171aedd6be5SKyle Evans loader.setenv("hw.ata.ata_dma", "0") 172aedd6be5SKyle Evans loader.setenv("hw.ata.atapi_dma", "0") 173aedd6be5SKyle Evans loader.setenv("hw.ata.wc", "0") 174aedd6be5SKyle Evans loader.setenv("hw.eisa_slots", "0") 175aedd6be5SKyle Evans loader.setenv("kern.eventtimer.periodic", "1") 176aedd6be5SKyle Evans loader.setenv("kern.geom.part.check_integrity", "0") 177088b4f5fSWarner Losh else 178aedd6be5SKyle Evans loader.unsetenv("kern.smp.disabled") 179aedd6be5SKyle Evans loader.unsetenv("hw.ata.ata_dma") 180aedd6be5SKyle Evans loader.unsetenv("hw.ata.atapi_dma") 181aedd6be5SKyle Evans loader.unsetenv("hw.ata.wc") 182aedd6be5SKyle Evans loader.unsetenv("hw.eisa_slots") 183aedd6be5SKyle Evans loader.unsetenv("kern.eventtimer.periodic") 184aedd6be5SKyle Evans loader.unsetenv("kern.geom.part.check_integrity") 185088b4f5fSWarner Losh end 186aedd6be5SKyle Evans core.sm = b 187088b4f5fSWarner Loshend 188088b4f5fSWarner Losh 189088b4f5fSWarner Loshfunction core.kernelList() 190aedd6be5SKyle Evans local k = loader.getenv("kernel") 191aedd6be5SKyle Evans local v = loader.getenv("kernels") or "" 192088b4f5fSWarner Losh 193aedd6be5SKyle Evans local kernels = {} 194aedd6be5SKyle Evans local unique = {} 195aedd6be5SKyle Evans local i = 0 1969f71d421SKyle Evans if k ~= nil then 197aedd6be5SKyle Evans i = i + 1 198aedd6be5SKyle Evans kernels[i] = k 199aedd6be5SKyle Evans unique[k] = true 200088b4f5fSWarner Losh end 201088b4f5fSWarner Losh 202088b4f5fSWarner Losh for n in v:gmatch("([^; ]+)[; ]?") do 2039f71d421SKyle Evans if unique[n] == nil then 204aedd6be5SKyle Evans i = i + 1 205aedd6be5SKyle Evans kernels[i] = n 206aedd6be5SKyle Evans unique[n] = true 207088b4f5fSWarner Losh end 208088b4f5fSWarner Losh end 209a108046fSConrad Meyer 210a108046fSConrad Meyer -- Automatically detect other bootable kernel directories using a 211a108046fSConrad Meyer -- heuristic. Any directory in /boot that contains an ordinary file 212a108046fSConrad Meyer -- named "kernel" is considered eligible. 213a108046fSConrad Meyer for file in lfs.dir("/boot") do 214aedd6be5SKyle Evans local fname = "/boot/" .. file 215a108046fSConrad Meyer 2169f71d421SKyle Evans if file == "." or file == ".." then 217aedd6be5SKyle Evans goto continue 218a108046fSConrad Meyer end 219a108046fSConrad Meyer 2209f71d421SKyle Evans if lfs.attributes(fname, "mode") ~= "directory" then 221aedd6be5SKyle Evans goto continue 222a108046fSConrad Meyer end 223a108046fSConrad Meyer 2249f71d421SKyle Evans if lfs.attributes(fname .. "/kernel", "mode") ~= "file" then 225aedd6be5SKyle Evans goto continue 226a108046fSConrad Meyer end 227a108046fSConrad Meyer 2289f71d421SKyle Evans if unique[file] == nil then 229aedd6be5SKyle Evans i = i + 1 230aedd6be5SKyle Evans kernels[i] = file 231aedd6be5SKyle Evans unique[file] = true 232a108046fSConrad Meyer end 233a108046fSConrad Meyer 234a108046fSConrad Meyer ::continue:: 235a108046fSConrad Meyer end 236aedd6be5SKyle Evans return kernels 237088b4f5fSWarner Loshend 238088b4f5fSWarner Losh 239088b4f5fSWarner Loshfunction core.setDefaults() 240aedd6be5SKyle Evans core.setACPI(core.getACPIPresent(true)) 241aedd6be5SKyle Evans core.setSafeMode(false) 242aedd6be5SKyle Evans core.setSingleUser(false) 243aedd6be5SKyle Evans core.setVerbose(false) 244088b4f5fSWarner Loshend 245088b4f5fSWarner Losh 2466d4ed94dSKyle Evansfunction core.autoboot(argstr) 247aedd6be5SKyle Evans config.loadelf() 248aedd6be5SKyle Evans loader.perform(compose_loader_cmd("autoboot", argstr)) 249088b4f5fSWarner Loshend 250088b4f5fSWarner Losh 2516d4ed94dSKyle Evansfunction core.boot(argstr) 252aedd6be5SKyle Evans config.loadelf() 253aedd6be5SKyle Evans loader.perform(compose_loader_cmd("boot", argstr)) 254088b4f5fSWarner Loshend 255088b4f5fSWarner Losh 256e07fc39cSKyle Evansfunction core.isSingleUserBoot() 257aedd6be5SKyle Evans local single_user = loader.getenv("boot_single") 258aedd6be5SKyle Evans return single_user ~= nil and single_user:lower() == "yes" 259e07fc39cSKyle Evansend 260e07fc39cSKyle Evans 261b140d14bSKyle Evansfunction core.isSerialBoot() 262aedd6be5SKyle Evans local c = loader.getenv("console") 263088b4f5fSWarner Losh 2649f71d421SKyle Evans if c ~= nil then 2659f71d421SKyle Evans if c:find("comconsole") ~= nil then 266aedd6be5SKyle Evans return true 267088b4f5fSWarner Losh end 268088b4f5fSWarner Losh end 269088b4f5fSWarner Losh 270aedd6be5SKyle Evans local s = loader.getenv("boot_serial") 2719f71d421SKyle Evans if s ~= nil then 272aedd6be5SKyle Evans return true 273088b4f5fSWarner Losh end 274088b4f5fSWarner Losh 275aedd6be5SKyle Evans local m = loader.getenv("boot_multicons") 2769f71d421SKyle Evans if m ~= nil then 277aedd6be5SKyle Evans return true 278088b4f5fSWarner Losh end 279aedd6be5SKyle Evans return false 280088b4f5fSWarner Loshend 281088b4f5fSWarner Losh 282c1ab36f5SKyle Evansfunction core.isSystem386() 2839f71d421SKyle Evans return loader.machine_arch == "i386" 284c1ab36f5SKyle Evansend 285c1ab36f5SKyle Evans 2865c1b5165SKyle Evans-- This may be a better candidate for a 'utility' module. 2875c1b5165SKyle Evansfunction core.shallowCopyTable(tbl) 288aedd6be5SKyle Evans local new_tbl = {} 2895c1b5165SKyle Evans for k, v in pairs(tbl) do 2909f71d421SKyle Evans if type(v) == "table" then 291aedd6be5SKyle Evans new_tbl[k] = core.shallowCopyTable(v) 2925c1b5165SKyle Evans else 293aedd6be5SKyle Evans new_tbl[k] = v 2945c1b5165SKyle Evans end 2955c1b5165SKyle Evans end 296aedd6be5SKyle Evans return new_tbl 2975c1b5165SKyle Evansend 2985c1b5165SKyle Evans 2996d4ed94dSKyle Evans-- XXX This should go away if we get the table lib into shape for importing. 3006d4ed94dSKyle Evans-- As of now, it requires some 'os' functions, so we'll implement this in lua 3016d4ed94dSKyle Evans-- for our uses 3026d4ed94dSKyle Evansfunction core.popFrontTable(tbl) 3036d4ed94dSKyle Evans -- Shouldn't reasonably happen 3049f71d421SKyle Evans if #tbl == 0 then 305aedd6be5SKyle Evans return nil, nil 3069f71d421SKyle Evans elseif #tbl == 1 then 307aedd6be5SKyle Evans return tbl[1], {} 3086d4ed94dSKyle Evans end 3096d4ed94dSKyle Evans 310aedd6be5SKyle Evans local first_value = tbl[1] 311aedd6be5SKyle Evans local new_tbl = {} 3126d4ed94dSKyle Evans -- This is not a cheap operation 3136d4ed94dSKyle Evans for k, v in ipairs(tbl) do 3149f71d421SKyle Evans if k > 1 then 315aedd6be5SKyle Evans new_tbl[k - 1] = v 3166d4ed94dSKyle Evans end 3176d4ed94dSKyle Evans end 3186d4ed94dSKyle Evans 319aedd6be5SKyle Evans return first_value, new_tbl 3206d4ed94dSKyle Evansend 3216d4ed94dSKyle Evans 3226f412147SKyle Evans-- On i386, hint.acpi.0.rsdp will be set before we're loaded. On !i386, it will 3236f412147SKyle Evans-- generally be set upon execution of the kernel. Because of this, we can't (or 3246f412147SKyle Evans-- don't really want to) detect/disable ACPI on !i386 reliably. Just set it 3256f412147SKyle Evans-- enabled if we detect it and leave well enough alone if we don't. 3269f71d421SKyle Evansif core.isSystem386() and core.getACPIPresent(false) then 327aedd6be5SKyle Evans core.setACPI(true) 3286f412147SKyle Evansend 329aedd6be5SKyle Evansreturn core 330