1088b4f5fSWarner Losh-- 24d846d26SWarner Losh-- SPDX-License-Identifier: BSD-2-Clause 372e39d71SKyle Evans-- 4088b4f5fSWarner Losh-- Copyright (c) 2015 Pedro Souza <[email protected]> 5e12ff891SKyle Evans-- Copyright (c) 2018 Kyle Evans <[email protected]> 6088b4f5fSWarner Losh-- All rights reserved. 7088b4f5fSWarner Losh-- 8088b4f5fSWarner Losh-- Redistribution and use in source and binary forms, with or without 9088b4f5fSWarner Losh-- modification, are permitted provided that the following conditions 10088b4f5fSWarner Losh-- are met: 11088b4f5fSWarner Losh-- 1. Redistributions of source code must retain the above copyright 12088b4f5fSWarner Losh-- notice, this list of conditions and the following disclaimer. 13088b4f5fSWarner Losh-- 2. Redistributions in binary form must reproduce the above copyright 14088b4f5fSWarner Losh-- notice, this list of conditions and the following disclaimer in the 15088b4f5fSWarner Losh-- documentation and/or other materials provided with the distribution. 16088b4f5fSWarner Losh-- 17088b4f5fSWarner Losh-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18088b4f5fSWarner Losh-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19088b4f5fSWarner Losh-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20088b4f5fSWarner Losh-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21088b4f5fSWarner Losh-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22088b4f5fSWarner Losh-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23088b4f5fSWarner Losh-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24088b4f5fSWarner Losh-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25088b4f5fSWarner Losh-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26088b4f5fSWarner Losh-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27088b4f5fSWarner Losh-- SUCH DAMAGE. 28088b4f5fSWarner Losh-- 29088b4f5fSWarner Losh 30aea262bfSKyle Evanslocal hook = require("hook") 31aea262bfSKyle Evans 32aedd6be5SKyle Evanslocal config = {} 33aedd6be5SKyle Evanslocal modules = {} 34aedd6be5SKyle Evanslocal carousel_choices = {} 3564c91742SKyle Evans-- Which variables we changed 3664c91742SKyle Evanslocal env_changed = {} 3764c91742SKyle Evans-- Values to restore env to (nil to unset) 3864c91742SKyle Evanslocal env_restore = {} 3925c4c7a5SKyle Evans 4072cf7db3SKyle Evanslocal MSG_FAILDIR = "Failed to load conf dir '%s': not a directory" 41fdabb5f5SKyle Evanslocal MSG_FAILEXEC = "Failed to exec '%s'" 42fdabb5f5SKyle Evanslocal MSG_FAILSETENV = "Failed to '%s' with value: %s" 43fdabb5f5SKyle Evanslocal MSG_FAILOPENCFG = "Failed to open config: '%s'" 44fdabb5f5SKyle Evanslocal MSG_FAILREADCFG = "Failed to read config: '%s'" 45fdabb5f5SKyle Evanslocal MSG_FAILPARSECFG = "Failed to parse config: '%s'" 463cb2f5f3SKyle Evanslocal MSG_FAILEXECLUA = "Failed to execute lua conf '%s': '%s'" 4757656285SKyle Evanslocal MSG_FAILPARSEVAR = "Failed to parse variable '%s': %s" 48fdabb5f5SKyle Evanslocal MSG_FAILEXBEF = "Failed to execute '%s' before loading '%s'" 49fdabb5f5SKyle Evanslocal MSG_FAILEXAF = "Failed to execute '%s' after loading '%s'" 50fdabb5f5SKyle Evanslocal MSG_MALFORMED = "Malformed line (%d):\n\t'%s'" 51fdabb5f5SKyle Evanslocal MSG_DEFAULTKERNFAIL = "No kernel set, failed to load from module_path" 52fdabb5f5SKyle Evanslocal MSG_KERNFAIL = "Failed to load kernel '%s'" 530d7bee6aSKyle Evanslocal MSG_XENKERNFAIL = "Failed to load Xen kernel '%s'" 540d7bee6aSKyle Evanslocal MSG_XENKERNLOADING = "Loading Xen kernel..." 55fdabb5f5SKyle Evanslocal MSG_KERNLOADING = "Loading kernel..." 56fdabb5f5SKyle Evanslocal MSG_MODLOADING = "Loading configured modules..." 57532dc172SKyle Evanslocal MSG_MODBLACKLIST = "Not loading blacklisted module '%s'" 58fdabb5f5SKyle Evans 5957656285SKyle Evanslocal MSG_FAILSYN_QUOTE = "Stray quote at position '%d'" 6057656285SKyle Evanslocal MSG_FAILSYN_EOLESC = "Stray escape at end of line" 6157656285SKyle Evanslocal MSG_FAILSYN_EOLVAR = "Unescaped $ at end of line" 6257656285SKyle Evanslocal MSG_FAILSYN_BADVAR = "Malformed variable expression at position '%d'" 6357656285SKyle Evans 646b2f0a3cSKyle Evans-- MODULEEXPR should more or less allow the exact same set of characters as the 656b2f0a3cSKyle Evans-- env_var entries in the pattern table. This is perhaps a good target for a 666b2f0a3cSKyle Evans-- little refactoring. 676b2f0a3cSKyle Evanslocal MODULEEXPR = '([%w%d-_.]+)' 6857656285SKyle Evanslocal QVALEXPR = '"(.*)"' 691ee89ab5SKyle Evanslocal QVALREPL = QVALEXPR:gsub('%%', '%%%%') 70b24872cfSKyle Evanslocal WORDEXPR = "([-%w%d][-%w%d_.]*)" 711ee89ab5SKyle Evanslocal WORDREPL = WORDEXPR:gsub('%%', '%%%%') 72058c692eSKyle Evans 73bf832717SKyle Evans-- Entries that should never make it into the environment; each one should have 74bf832717SKyle Evans-- a documented reason for its existence, and these should all be implementation 75bf832717SKyle Evans-- details of the config module. 76bf832717SKyle Evanslocal loader_env_restricted_table = { 77bf832717SKyle Evans -- loader_conf_files should be considered write-only, and consumers 78bf832717SKyle Evans -- should not rely on any particular value; it's a loader implementation 79bf832717SKyle Evans -- detail. Moreover, it's not a particularly useful variable to have in 80bf832717SKyle Evans -- the kenv. Save the overhead, let it get fetched other ways. 81bf832717SKyle Evans loader_conf_files = true, 82bf832717SKyle Evans} 83bf832717SKyle Evans 8464c91742SKyle Evanslocal function restoreEnv() 8564c91742SKyle Evans -- Examine changed environment variables 8664c91742SKyle Evans for k, v in pairs(env_changed) do 8764c91742SKyle Evans local restore_value = env_restore[k] 8864c91742SKyle Evans if restore_value == nil then 8964c91742SKyle Evans -- This one doesn't need restored for some reason 9064c91742SKyle Evans goto continue 9164c91742SKyle Evans end 9264c91742SKyle Evans local current_value = loader.getenv(k) 9364c91742SKyle Evans if current_value ~= v then 9464c91742SKyle Evans -- This was overwritten by some action taken on the menu 9564c91742SKyle Evans -- most likely; we'll leave it be. 9664c91742SKyle Evans goto continue 9764c91742SKyle Evans end 9864c91742SKyle Evans restore_value = restore_value.value 9964c91742SKyle Evans if restore_value ~= nil then 10064c91742SKyle Evans loader.setenv(k, restore_value) 10164c91742SKyle Evans else 10264c91742SKyle Evans loader.unsetenv(k) 10364c91742SKyle Evans end 10464c91742SKyle Evans ::continue:: 10564c91742SKyle Evans end 10664c91742SKyle Evans 10764c91742SKyle Evans env_changed = {} 10864c91742SKyle Evans env_restore = {} 10964c91742SKyle Evansend 11064c91742SKyle Evans 111bf832717SKyle Evans-- XXX This getEnv/setEnv should likely be exported at some point. We can save 112bf832717SKyle Evans-- the call back into loader.getenv for any variable that's been set or 113bf832717SKyle Evans-- overridden by any loader.conf using this implementation with little overhead 114bf832717SKyle Evans-- since we're already tracking the values. 115bf832717SKyle Evanslocal function getEnv(key) 116bf832717SKyle Evans if loader_env_restricted_table[key] ~= nil or 117bf832717SKyle Evans env_changed[key] ~= nil then 118bf832717SKyle Evans return env_changed[key] 119bf832717SKyle Evans end 120bf832717SKyle Evans 121bf832717SKyle Evans return loader.getenv(key) 122bf832717SKyle Evansend 123bf832717SKyle Evans 12464c91742SKyle Evanslocal function setEnv(key, value) 125bf832717SKyle Evans env_changed[key] = value 126bf832717SKyle Evans 127bf832717SKyle Evans if loader_env_restricted_table[key] ~= nil then 128bf832717SKyle Evans return 0 129bf832717SKyle Evans end 130bf832717SKyle Evans 13164c91742SKyle Evans -- Track the original value for this if we haven't already 13264c91742SKyle Evans if env_restore[key] == nil then 13364c91742SKyle Evans env_restore[key] = {value = loader.getenv(key)} 13464c91742SKyle Evans end 13564c91742SKyle Evans 13664c91742SKyle Evans return loader.setenv(key, value) 13764c91742SKyle Evansend 13864c91742SKyle Evans 139dbef5253SKyle Evans-- name here is one of 'name', 'type', flags', 'before', 'after', or 'error.' 140dbef5253SKyle Evans-- These are set from lines in loader.conf(5): ${key}_${name}="${value}" where 141dbef5253SKyle Evans-- ${key} is a module name. 142dbef5253SKyle Evanslocal function setKey(key, name, value) 143dbef5253SKyle Evans if modules[key] == nil then 144dbef5253SKyle Evans modules[key] = {} 145dbef5253SKyle Evans end 146dbef5253SKyle Evans modules[key][name] = value 147dbef5253SKyle Evansend 148dbef5253SKyle Evans 149deb8c8f5SKyle Evans-- Escapes the named value for use as a literal in a replacement pattern. 150deb8c8f5SKyle Evans-- e.g. dhcp.host-name gets turned into dhcp%.host%-name to remove the special 151deb8c8f5SKyle Evans-- meaning. 152deb8c8f5SKyle Evanslocal function escapeName(name) 153deb8c8f5SKyle Evans return name:gsub("([%p])", "%%%1") 154deb8c8f5SKyle Evansend 155deb8c8f5SKyle Evans 156deb8c8f5SKyle Evanslocal function processEnvVar(value) 15757656285SKyle Evans local pval, vlen = '', #value 15857656285SKyle Evans local nextpos, vdelim, vinit = 1 15957656285SKyle Evans local vpat 16057656285SKyle Evans for i = 1, vlen do 16157656285SKyle Evans if i < nextpos then 16257656285SKyle Evans goto nextc 163deb8c8f5SKyle Evans end 16457656285SKyle Evans 16557656285SKyle Evans local c = value:sub(i, i) 16657656285SKyle Evans if c == '\\' then 16757656285SKyle Evans if i == vlen then 16857656285SKyle Evans return nil, MSG_FAILSYN_EOLESC 169deb8c8f5SKyle Evans end 17057656285SKyle Evans nextpos = i + 2 17157656285SKyle Evans pval = pval .. value:sub(i + 1, i + 1) 17257656285SKyle Evans elseif c == '"' then 17357656285SKyle Evans return nil, MSG_FAILSYN_QUOTE:format(i) 17457656285SKyle Evans elseif c == "$" then 17557656285SKyle Evans if i == vlen then 17657656285SKyle Evans return nil, MSG_FAILSYN_EOLVAR 17757656285SKyle Evans else 17857656285SKyle Evans if value:sub(i + 1, i + 1) == "{" then 17957656285SKyle Evans -- Skip ${ 18057656285SKyle Evans vinit = i + 2 18157656285SKyle Evans vdelim = '}' 18257656285SKyle Evans vpat = "^([^}]+)}" 18357656285SKyle Evans else 18457656285SKyle Evans -- Skip the $ 18557656285SKyle Evans vinit = i + 1 18657656285SKyle Evans vdelim = nil 187b24872cfSKyle Evans vpat = "^([%w][-%w%d_.]*)" 18857656285SKyle Evans end 18957656285SKyle Evans 19057656285SKyle Evans local name = value:match(vpat, vinit) 19157656285SKyle Evans if not name then 19257656285SKyle Evans return nil, MSG_FAILSYN_BADVAR:format(i) 19357656285SKyle Evans else 19457656285SKyle Evans nextpos = vinit + #name 19557656285SKyle Evans if vdelim then 19657656285SKyle Evans nextpos = nextpos + 1 19757656285SKyle Evans end 19857656285SKyle Evans 19957656285SKyle Evans local repl = loader.getenv(name) or "" 20057656285SKyle Evans pval = pval .. repl 20157656285SKyle Evans end 20257656285SKyle Evans end 20357656285SKyle Evans else 20457656285SKyle Evans pval = pval .. c 20557656285SKyle Evans end 20657656285SKyle Evans ::nextc:: 20757656285SKyle Evans end 20857656285SKyle Evans 20957656285SKyle Evans return pval 210deb8c8f5SKyle Evansend 211deb8c8f5SKyle Evans 2121ee89ab5SKyle Evanslocal function checkPattern(line, pattern) 2131ee89ab5SKyle Evans local function _realCheck(_line, _pattern) 2141ee89ab5SKyle Evans return _line:match(_pattern) 2151ee89ab5SKyle Evans end 2161ee89ab5SKyle Evans 2171ee89ab5SKyle Evans if pattern:find('$VALUE') then 2181ee89ab5SKyle Evans local k, v, c 2191ee89ab5SKyle Evans k, v, c = _realCheck(line, pattern:gsub('$VALUE', QVALREPL)) 2201ee89ab5SKyle Evans if k ~= nil then 2211ee89ab5SKyle Evans return k,v, c 2221ee89ab5SKyle Evans end 2231ee89ab5SKyle Evans return _realCheck(line, pattern:gsub('$VALUE', WORDREPL)) 2241ee89ab5SKyle Evans else 2251ee89ab5SKyle Evans return _realCheck(line, pattern) 2261ee89ab5SKyle Evans end 2271ee89ab5SKyle Evansend 2281ee89ab5SKyle Evans 229058c692eSKyle Evans-- str in this table is a regex pattern. It will automatically be anchored to 230058c692eSKyle Evans-- the beginning of a line and any preceding whitespace will be skipped. The 231058c692eSKyle Evans-- pattern should have no more than two captures patterns, which correspond to 232058c692eSKyle Evans-- the two parameters (usually 'key' and 'value') that are passed to the 2331ee89ab5SKyle Evans-- process function. All trailing characters will be validated. Any $VALUE 2341ee89ab5SKyle Evans-- token included in a pattern will be tried first with a quoted value capture 2351ee89ab5SKyle Evans-- group, then a single-word value capture group. This is our kludge for Lua 2361ee89ab5SKyle Evans-- regex not supporting branching. 2379a16e110SKyle Evans-- 2389a16e110SKyle Evans-- We have two special entries in this table: the first is the first entry, 2399a16e110SKyle Evans-- a full-line comment. The second is for 'exec' handling. Both have a single 2409a16e110SKyle Evans-- capture group, but the difference is that the full-line comment pattern will 2419a16e110SKyle Evans-- match the entire line. This does not run afoul of the later end of line 2429a16e110SKyle Evans-- validation that we'll do after a match. However, the 'exec' pattern will. 2439a16e110SKyle Evans-- We document the exceptions with a special 'groups' index that indicates 2449a16e110SKyle Evans-- the number of capture groups, if not two. We'll use this later to do 2459a16e110SKyle Evans-- validation on the proper entry. 2461ee89ab5SKyle Evans-- 247e1a8835aSKyle Evanslocal pattern_table = { 248e1a8835aSKyle Evans { 2493cb2f5f3SKyle Evans luaexempt = true, 250058c692eSKyle Evans str = "(#.*)", 251e1a8835aSKyle Evans process = function(_, _) end, 2529a16e110SKyle Evans groups = 1, 253088b4f5fSWarner Losh }, 254088b4f5fSWarner Losh -- module_load="value" 255e1a8835aSKyle Evans { 2563cb2f5f3SKyle Evans name = MODULEEXPR .. "_load%s*", 2573cb2f5f3SKyle Evans val = "%s*$VALUE", 258088b4f5fSWarner Losh process = function(k, v) 2599f71d421SKyle Evans if modules[k] == nil then 260aedd6be5SKyle Evans modules[k] = {} 261088b4f5fSWarner Losh end 262aedd6be5SKyle Evans modules[k].load = v:upper() 263e9eee0f2SWarner Losh setEnv(k .. "_load", v:upper()) 264e1a8835aSKyle Evans end, 265088b4f5fSWarner Losh }, 266088b4f5fSWarner Losh -- module_name="value" 267e1a8835aSKyle Evans { 2683cb2f5f3SKyle Evans name = MODULEEXPR .. "_name%s*", 2693cb2f5f3SKyle Evans val = "%s*$VALUE", 270088b4f5fSWarner Losh process = function(k, v) 271dbef5253SKyle Evans setKey(k, "name", v) 272e9eee0f2SWarner Losh setEnv(k .. "_name", v) 273e1a8835aSKyle Evans end, 274088b4f5fSWarner Losh }, 275088b4f5fSWarner Losh -- module_type="value" 276e1a8835aSKyle Evans { 2773cb2f5f3SKyle Evans name = MODULEEXPR .. "_type%s*", 2783cb2f5f3SKyle Evans val = "%s*$VALUE", 279088b4f5fSWarner Losh process = function(k, v) 280dbef5253SKyle Evans setKey(k, "type", v) 281e9eee0f2SWarner Losh setEnv(k .. "_type", v) 282e1a8835aSKyle Evans end, 283088b4f5fSWarner Losh }, 284088b4f5fSWarner Losh -- module_flags="value" 285e1a8835aSKyle Evans { 2863cb2f5f3SKyle Evans name = MODULEEXPR .. "_flags%s*", 2873cb2f5f3SKyle Evans val = "%s*$VALUE", 288088b4f5fSWarner Losh process = function(k, v) 289dbef5253SKyle Evans setKey(k, "flags", v) 290e9eee0f2SWarner Losh setEnv(k .. "_flags", v) 291e1a8835aSKyle Evans end, 292088b4f5fSWarner Losh }, 293088b4f5fSWarner Losh -- module_before="value" 294e1a8835aSKyle Evans { 2953cb2f5f3SKyle Evans name = MODULEEXPR .. "_before%s*", 2963cb2f5f3SKyle Evans val = "%s*$VALUE", 297088b4f5fSWarner Losh process = function(k, v) 298dbef5253SKyle Evans setKey(k, "before", v) 299e9eee0f2SWarner Losh setEnv(k .. "_before", v) 300e1a8835aSKyle Evans end, 301088b4f5fSWarner Losh }, 302088b4f5fSWarner Losh -- module_after="value" 303e1a8835aSKyle Evans { 3043cb2f5f3SKyle Evans name = MODULEEXPR .. "_after%s*", 3053cb2f5f3SKyle Evans val = "%s*$VALUE", 306088b4f5fSWarner Losh process = function(k, v) 307dbef5253SKyle Evans setKey(k, "after", v) 308e9eee0f2SWarner Losh setEnv(k .. "_after", v) 309e1a8835aSKyle Evans end, 310088b4f5fSWarner Losh }, 311088b4f5fSWarner Losh -- module_error="value" 312e1a8835aSKyle Evans { 3133cb2f5f3SKyle Evans name = MODULEEXPR .. "_error%s*", 3143cb2f5f3SKyle Evans val = "%s*$VALUE", 315088b4f5fSWarner Losh process = function(k, v) 316dbef5253SKyle Evans setKey(k, "error", v) 317e9eee0f2SWarner Losh setEnv(k .. "_error", v) 318e1a8835aSKyle Evans end, 319088b4f5fSWarner Losh }, 320088b4f5fSWarner Losh -- exec="command" 321e1a8835aSKyle Evans { 3223cb2f5f3SKyle Evans luaexempt = true, 3233cb2f5f3SKyle Evans name = "exec%s*", 3243cb2f5f3SKyle Evans val = "%s*" .. QVALEXPR, 325e2df27e3SKyle Evans process = function(k, _) 3269ab2d3c5SKyle Evans if cli_execute_unparsed(k) ~= 0 then 327fdabb5f5SKyle Evans print(MSG_FAILEXEC:format(k)) 328088b4f5fSWarner Losh end 329e1a8835aSKyle Evans end, 3309a16e110SKyle Evans groups = 1, 331088b4f5fSWarner Losh }, 33257656285SKyle Evans -- env_var="value" or env_var=[word|num] 333e1a8835aSKyle Evans { 3343cb2f5f3SKyle Evans name = "([%w][%w%d-_.]*)%s*", 3353cb2f5f3SKyle Evans val = "%s*$VALUE", 336088b4f5fSWarner Losh process = function(k, v) 33757656285SKyle Evans local pv, msg = processEnvVar(v) 33857656285SKyle Evans if not pv then 33957656285SKyle Evans print(MSG_FAILPARSEVAR:format(k, msg)) 34057656285SKyle Evans return 341088b4f5fSWarner Losh end 34257656285SKyle Evans if setEnv(k, pv) ~= 0 then 34357656285SKyle Evans print(MSG_FAILSETENV:format(k, v)) 3443cb2f5f3SKyle Evans else 3453cb2f5f3SKyle Evans return pv 346088b4f5fSWarner Losh end 347e1a8835aSKyle Evans end, 348e1a8835aSKyle Evans }, 349aedd6be5SKyle Evans} 350088b4f5fSWarner Losh 351dbef5253SKyle Evanslocal function isValidComment(line) 352dbef5253SKyle Evans if line ~= nil then 353dbef5253SKyle Evans local s = line:match("^%s*#.*") 354dbef5253SKyle Evans if s == nil then 355dbef5253SKyle Evans s = line:match("^%s*$") 356dbef5253SKyle Evans end 357dbef5253SKyle Evans if s == nil then 358dbef5253SKyle Evans return false 359dbef5253SKyle Evans end 360dbef5253SKyle Evans end 361dbef5253SKyle Evans return true 362dbef5253SKyle Evansend 363dbef5253SKyle Evans 364532dc172SKyle Evanslocal function getBlacklist() 365e1f1ddebSKyle Evans local blacklist = {} 366532dc172SKyle Evans local blacklist_str = loader.getenv('module_blacklist') 367532dc172SKyle Evans if blacklist_str == nil then 368e1f1ddebSKyle Evans return blacklist 369532dc172SKyle Evans end 370532dc172SKyle Evans 371b24872cfSKyle Evans for mod in blacklist_str:gmatch("[;, ]?([-%w_]+)[;, ]?") do 372532dc172SKyle Evans blacklist[mod] = true 373532dc172SKyle Evans end 374532dc172SKyle Evans return blacklist 375532dc172SKyle Evansend 376532dc172SKyle Evans 377dbef5253SKyle Evanslocal function loadModule(mod, silent) 378dbef5253SKyle Evans local status = true 379532dc172SKyle Evans local blacklist = getBlacklist() 380dbef5253SKyle Evans local pstatus 381dbef5253SKyle Evans for k, v in pairs(mod) do 3828d21763eSKyle Evans if v.load ~= nil and v.load:lower() == "yes" then 383532dc172SKyle Evans local module_name = v.name or k 3844634bb1fSKyle Evans if not v.force and blacklist[module_name] ~= nil then 385532dc172SKyle Evans if not silent then 386532dc172SKyle Evans print(MSG_MODBLACKLIST:format(module_name)) 387532dc172SKyle Evans end 388532dc172SKyle Evans goto continue 389532dc172SKyle Evans end 3903078173cSKyle Evans if not silent then 3913078173cSKyle Evans loader.printc(module_name .. "...") 3923078173cSKyle Evans end 393dbef5253SKyle Evans local str = "load " 394dbef5253SKyle Evans if v.type ~= nil then 395dbef5253SKyle Evans str = str .. "-t " .. v.type .. " " 396dbef5253SKyle Evans end 397532dc172SKyle Evans str = str .. module_name 39835beb928SKyle Evans if v.flags ~= nil then 39935beb928SKyle Evans str = str .. " " .. v.flags 40035beb928SKyle Evans end 401dbef5253SKyle Evans if v.before ~= nil then 402dbef5253SKyle Evans pstatus = cli_execute_unparsed(v.before) == 0 403dbef5253SKyle Evans if not pstatus and not silent then 404dbef5253SKyle Evans print(MSG_FAILEXBEF:format(v.before, k)) 405dbef5253SKyle Evans end 406dbef5253SKyle Evans status = status and pstatus 407dbef5253SKyle Evans end 408dbef5253SKyle Evans 409dbef5253SKyle Evans if cli_execute_unparsed(str) ~= 0 then 410*7ffa3b0fSWarner Losh -- XXX Temporary shim: don't break the boot if 411*7ffa3b0fSWarner Losh -- loader hadn't been recompiled with this 412*7ffa3b0fSWarner Losh -- function exposed. 413*7ffa3b0fSWarner Losh if loader.command_error then 4143078173cSKyle Evans print(loader.command_error()) 415*7ffa3b0fSWarner Losh end 416dbef5253SKyle Evans if not silent then 4173078173cSKyle Evans print("failed!") 418dbef5253SKyle Evans end 419dbef5253SKyle Evans if v.error ~= nil then 420dbef5253SKyle Evans cli_execute_unparsed(v.error) 421dbef5253SKyle Evans end 422dbef5253SKyle Evans status = false 4233078173cSKyle Evans elseif v.after ~= nil then 424dbef5253SKyle Evans pstatus = cli_execute_unparsed(v.after) == 0 425dbef5253SKyle Evans if not pstatus and not silent then 426dbef5253SKyle Evans print(MSG_FAILEXAF:format(v.after, k)) 427dbef5253SKyle Evans end 4283078173cSKyle Evans if not silent then 4293078173cSKyle Evans print("ok") 4303078173cSKyle Evans end 431dbef5253SKyle Evans status = status and pstatus 432dbef5253SKyle Evans end 433dbef5253SKyle Evans end 434532dc172SKyle Evans ::continue:: 435dbef5253SKyle Evans end 436dbef5253SKyle Evans 437dbef5253SKyle Evans return status 438dbef5253SKyle Evansend 439dbef5253SKyle Evans 440322a2dddSKyle Evanslocal function readFile(name, silent) 441164b58fdSKyle Evans local f = io.open(name) 442164b58fdSKyle Evans if f == nil then 443164b58fdSKyle Evans if not silent then 444fdabb5f5SKyle Evans print(MSG_FAILOPENCFG:format(name)) 445164b58fdSKyle Evans end 446164b58fdSKyle Evans return nil 447164b58fdSKyle Evans end 448164b58fdSKyle Evans 449164b58fdSKyle Evans local text, _ = io.read(f) 450164b58fdSKyle Evans -- We might have read in the whole file, this won't be needed any more. 451164b58fdSKyle Evans io.close(f) 452164b58fdSKyle Evans 4538d21763eSKyle Evans if text == nil and not silent then 454fdabb5f5SKyle Evans print(MSG_FAILREADCFG:format(name)) 455164b58fdSKyle Evans end 456164b58fdSKyle Evans return text 457164b58fdSKyle Evansend 458164b58fdSKyle Evans 459322a2dddSKyle Evanslocal function checkNextboot() 460be2050daSKyle Evans local nextboot_file = loader.getenv("nextboot_conf") 461e307eb94SToomas Soome local nextboot_enable = loader.getenv("nextboot_enable") 462e307eb94SToomas Soome 463ddfae7e3SKyle Evans if nextboot_file == nil then 464ddfae7e3SKyle Evans return 465ddfae7e3SKyle Evans end 466ddfae7e3SKyle Evans 467e307eb94SToomas Soome -- is nextboot_enable set in nvstore? 468e307eb94SToomas Soome if nextboot_enable == "NO" then 469e307eb94SToomas Soome return 470e307eb94SToomas Soome end 471e307eb94SToomas Soome 472322a2dddSKyle Evans local text = readFile(nextboot_file, true) 473ddfae7e3SKyle Evans if text == nil then 474ddfae7e3SKyle Evans return 475ddfae7e3SKyle Evans end 476ddfae7e3SKyle Evans 477e307eb94SToomas Soome if nextboot_enable == nil and 478e307eb94SToomas Soome text:match("^nextboot_enable=\"NO\"") ~= nil then 479ddfae7e3SKyle Evans -- We're done; nextboot is not enabled 480ddfae7e3SKyle Evans return 481ddfae7e3SKyle Evans end 482ddfae7e3SKyle Evans 483ddfae7e3SKyle Evans if not config.parse(text) then 4842f3ecc87SKyle Evans print(MSG_FAILPARSECFG:format(nextboot_file)) 485ddfae7e3SKyle Evans end 486ddfae7e3SKyle Evans 487ddfae7e3SKyle Evans -- Attempt to rewrite the first line and only the first line of the 488ddfae7e3SKyle Evans -- nextboot_file. We overwrite it with nextboot_enable="NO", then 48967eae503SKyle Evans -- check for that on load. 490ddfae7e3SKyle Evans -- It's worth noting that this won't work on every filesystem, so we 491ddfae7e3SKyle Evans -- won't do anything notable if we have any errors in this process. 492ddfae7e3SKyle Evans local nfile = io.open(nextboot_file, 'w') 493ddfae7e3SKyle Evans if nfile ~= nil then 494ddfae7e3SKyle Evans -- We need the trailing space here to account for the extra 495ddfae7e3SKyle Evans -- character taken up by the string nextboot_enable="YES" 496ddfae7e3SKyle Evans -- Or new end quotation mark lands on the S, and we want to 497ddfae7e3SKyle Evans -- rewrite the entirety of the first line. 498ddfae7e3SKyle Evans io.write(nfile, "nextboot_enable=\"NO\" ") 499ddfae7e3SKyle Evans io.close(nfile) 500ddfae7e3SKyle Evans end 501e307eb94SToomas Soome loader.setenv("nextboot_enable", "NO") 502ddfae7e3SKyle Evansend 503ddfae7e3SKyle Evans 5043cb2f5f3SKyle Evanslocal function processEnv(k, v) 5053cb2f5f3SKyle Evans for _, val in ipairs(pattern_table) do 5063cb2f5f3SKyle Evans if not val.luaexempt and val.name then 5073cb2f5f3SKyle Evans local matched = k:match(val.name) 5083cb2f5f3SKyle Evans 5093cb2f5f3SKyle Evans if matched then 5103cb2f5f3SKyle Evans return val.process(matched, v) 5113cb2f5f3SKyle Evans end 5123cb2f5f3SKyle Evans end 5133cb2f5f3SKyle Evans end 5143cb2f5f3SKyle Evansend 5153cb2f5f3SKyle Evans 516b5746545SKyle Evans-- Module exports 517f0b03262SKyle Evansconfig.verbose = false 518b5746545SKyle Evans 51925c4c7a5SKyle Evans-- The first item in every carousel is always the default item. 52025c4c7a5SKyle Evansfunction config.getCarouselIndex(id) 5218d21763eSKyle Evans return carousel_choices[id] or 1 52225c4c7a5SKyle Evansend 52325c4c7a5SKyle Evans 52425c4c7a5SKyle Evansfunction config.setCarouselIndex(id, idx) 525aedd6be5SKyle Evans carousel_choices[id] = idx 52625c4c7a5SKyle Evansend 52725c4c7a5SKyle Evans 528fb7275beSKyle Evans-- Returns true if we processed the file successfully, false if we did not. 529fb7275beSKyle Evans-- If 'silent' is true, being unable to read the file is not considered a 530fb7275beSKyle Evans-- failure. 531ddfae7e3SKyle Evansfunction config.processFile(name, silent) 532062d62c9SKyle Evans if silent == nil then 533062d62c9SKyle Evans silent = false 534062d62c9SKyle Evans end 535088b4f5fSWarner Losh 536322a2dddSKyle Evans local text = readFile(name, silent) 5379f71d421SKyle Evans if text == nil then 538fb7275beSKyle Evans return silent 539088b4f5fSWarner Losh end 5403dcb7648SKyle Evans 5413cb2f5f3SKyle Evans if name:match(".lua$") then 5423cb2f5f3SKyle Evans local cfg_env = setmetatable({}, { 5433cb2f5f3SKyle Evans indices = {}, 5443cb2f5f3SKyle Evans __index = function(env, key) 5453cb2f5f3SKyle Evans if getmetatable(env).indices[key] then 5463cb2f5f3SKyle Evans return rawget(env, key) 5473cb2f5f3SKyle Evans end 5483cb2f5f3SKyle Evans 5493cb2f5f3SKyle Evans return loader.getenv(key) 5503cb2f5f3SKyle Evans end, 5513cb2f5f3SKyle Evans __newindex = function(env, key, val) 5523cb2f5f3SKyle Evans getmetatable(env).indices[key] = true 5533cb2f5f3SKyle Evans rawset(env, key, val) 5543cb2f5f3SKyle Evans end, 5553cb2f5f3SKyle Evans }) 5563cb2f5f3SKyle Evans 5573cb2f5f3SKyle Evans -- Give local modules a chance to populate the config 5583cb2f5f3SKyle Evans -- environment. 5593cb2f5f3SKyle Evans hook.runAll("config.buildenv", cfg_env) 5603cb2f5f3SKyle Evans local res, err = pcall(load(text, name, "t", cfg_env)) 5613cb2f5f3SKyle Evans if res then 5623cb2f5f3SKyle Evans for k, v in pairs(cfg_env) do 5633cb2f5f3SKyle Evans local t = type(v) 5643cb2f5f3SKyle Evans if t ~= "function" and t ~= "table" then 5653cb2f5f3SKyle Evans if t ~= "string" then 5663cb2f5f3SKyle Evans v = tostring(v) 5673cb2f5f3SKyle Evans end 5683cb2f5f3SKyle Evans local pval = processEnv(k, v) 5693cb2f5f3SKyle Evans if pval then 5703cb2f5f3SKyle Evans setEnv(k, pval) 5713cb2f5f3SKyle Evans end 5723cb2f5f3SKyle Evans end 5733cb2f5f3SKyle Evans end 5743cb2f5f3SKyle Evans else 5753cb2f5f3SKyle Evans print(MSG_FAILEXECLUA:format(name, err)) 5763cb2f5f3SKyle Evans end 5773cb2f5f3SKyle Evans 5783cb2f5f3SKyle Evans return res 5793cb2f5f3SKyle Evans else 5804adde50dSKyle Evans return config.parse(text) 5814adde50dSKyle Evans end 5823cb2f5f3SKyle Evansend 5834adde50dSKyle Evans 5844adde50dSKyle Evans-- silent runs will not return false if we fail to open the file 5854adde50dSKyle Evansfunction config.parse(text) 586aedd6be5SKyle Evans local n = 1 587aedd6be5SKyle Evans local status = true 588088b4f5fSWarner Losh 58971049173SKyle Evans for line in text:gmatch("([^\n]+)") do 5909f71d421SKyle Evans if line:match("^%s*$") == nil then 591e2df27e3SKyle Evans for _, val in ipairs(pattern_table) do 5923cb2f5f3SKyle Evans if val.str == nil then 5933cb2f5f3SKyle Evans val.str = val.name .. "=" .. val.val 5943cb2f5f3SKyle Evans end 595058c692eSKyle Evans local pattern = '^%s*' .. val.str .. '%s*(.*)'; 5969a16e110SKyle Evans local cgroups = val.groups or 2 5971ee89ab5SKyle Evans local k, v, c = checkPattern(line, pattern) 5989f71d421SKyle Evans if k ~= nil then 5999a16e110SKyle Evans -- Offset by one, drats 6009a16e110SKyle Evans if cgroups == 1 then 6019a16e110SKyle Evans c = v 6029a16e110SKyle Evans v = nil 6039a16e110SKyle Evans end 604088b4f5fSWarner Losh 605dbef5253SKyle Evans if isValidComment(c) then 606aedd6be5SKyle Evans val.process(k, v) 6079a16e110SKyle Evans goto nextline 608088b4f5fSWarner Losh end 609088b4f5fSWarner Losh 610aedd6be5SKyle Evans break 611088b4f5fSWarner Losh end 612088b4f5fSWarner Losh end 613088b4f5fSWarner Losh 614fdabb5f5SKyle Evans print(MSG_MALFORMED:format(n, line)) 615aedd6be5SKyle Evans status = false 616088b4f5fSWarner Losh end 6179a16e110SKyle Evans ::nextline:: 618aedd6be5SKyle Evans n = n + 1 619088b4f5fSWarner Losh end 620088b4f5fSWarner Losh 621aedd6be5SKyle Evans return status 622088b4f5fSWarner Loshend 623088b4f5fSWarner Losh 6243fe0ac6aSKyle Evansfunction config.readConf(file, loaded_files) 6253fe0ac6aSKyle Evans if loaded_files == nil then 6263fe0ac6aSKyle Evans loaded_files = {} 6277a5c6c8bSKyle Evans end 6287a5c6c8bSKyle Evans 6293fe0ac6aSKyle Evans if loaded_files[file] ~= nil then 6303fe0ac6aSKyle Evans return 6313fe0ac6aSKyle Evans end 6323fe0ac6aSKyle Evans 633a25531dbSStéphane Rochoy local top_level = next(loaded_files) == nil -- Are we the top-level readConf? 6343fe0ac6aSKyle Evans print("Loading " .. file) 6353fe0ac6aSKyle Evans 6363fe0ac6aSKyle Evans -- The final value of loader_conf_files is not important, so just 6373fe0ac6aSKyle Evans -- clobber it here. We'll later check if it's no longer nil and process 6383fe0ac6aSKyle Evans -- the new value for files to read. 6393fe0ac6aSKyle Evans setEnv("loader_conf_files", nil) 6403fe0ac6aSKyle Evans 6417a5c6c8bSKyle Evans -- These may or may not exist, and that's ok. Do a 6427a5c6c8bSKyle Evans -- silent parse so that we complain on parse errors but 6437a5c6c8bSKyle Evans -- not for them simply not existing. 6443fe0ac6aSKyle Evans if not config.processFile(file, true) then 6453fe0ac6aSKyle Evans print(MSG_FAILPARSECFG:format(file)) 6467a5c6c8bSKyle Evans end 6477a5c6c8bSKyle Evans 6483fe0ac6aSKyle Evans loaded_files[file] = true 6493fe0ac6aSKyle Evans 6503fe0ac6aSKyle Evans -- Going to process "loader_conf_files" extra-files 6513fe0ac6aSKyle Evans local loader_conf_files = getEnv("loader_conf_files") 6523fe0ac6aSKyle Evans if loader_conf_files ~= nil then 6533fe0ac6aSKyle Evans for name in loader_conf_files:gmatch("[%w%p]+") do 6543fe0ac6aSKyle Evans config.readConf(name, loaded_files) 6557a5c6c8bSKyle Evans end 6567a5c6c8bSKyle Evans end 65772cf7db3SKyle Evans 658a25531dbSStéphane Rochoy if top_level then 65972cf7db3SKyle Evans local loader_conf_dirs = getEnv("loader_conf_dirs") 6603eb3a802SStéphane Rochoy 6613eb3a802SStéphane Rochoy -- If product_vars is set, it must be a list of environment variable names 6623eb3a802SStéphane Rochoy -- to walk through to guess product information. The order matters as 6633eb3a802SStéphane Rochoy -- reading a config files override the previously defined values. 6643eb3a802SStéphane Rochoy -- 6653eb3a802SStéphane Rochoy -- If product information can be guessed, for each product information 6663eb3a802SStéphane Rochoy -- found, also read config files found in /boot/loader.conf.d/PRODUCT/. 6673eb3a802SStéphane Rochoy local product_vars = getEnv("product_vars") 6683eb3a802SStéphane Rochoy if product_vars then 6693eb3a802SStéphane Rochoy local product_conf_dirs = "" 6703eb3a802SStéphane Rochoy for var in product_vars:gmatch("%S+") do 6713eb3a802SStéphane Rochoy local product = getEnv(var) 6723eb3a802SStéphane Rochoy if product then 6733eb3a802SStéphane Rochoy product_conf_dirs = product_conf_dirs .. " /boot/loader.conf.d/" .. product 6743eb3a802SStéphane Rochoy end 6753eb3a802SStéphane Rochoy end 6763eb3a802SStéphane Rochoy 6773eb3a802SStéphane Rochoy if loader_conf_dirs then 6783eb3a802SStéphane Rochoy loader_conf_dirs = loader_conf_dirs .. product_conf_dirs 6793eb3a802SStéphane Rochoy else 6803eb3a802SStéphane Rochoy loader_conf_dirs = product_conf_dirs 6813eb3a802SStéphane Rochoy end 6823eb3a802SStéphane Rochoy end 6833eb3a802SStéphane Rochoy 684a25531dbSStéphane Rochoy -- Process "loader_conf_dirs" extra-directories 68572cf7db3SKyle Evans if loader_conf_dirs ~= nil then 68672cf7db3SKyle Evans for name in loader_conf_dirs:gmatch("[%w%p]+") do 68772cf7db3SKyle Evans if lfs.attributes(name, "mode") ~= "directory" then 68872cf7db3SKyle Evans print(MSG_FAILDIR:format(name)) 68972cf7db3SKyle Evans goto nextdir 69072cf7db3SKyle Evans end 6913eb3a802SStéphane Rochoy 69272cf7db3SKyle Evans for cfile in lfs.dir(name) do 69372cf7db3SKyle Evans if cfile:match(".conf$") then 69472cf7db3SKyle Evans local fpath = name .. "/" .. cfile 69572cf7db3SKyle Evans if lfs.attributes(fpath, "mode") == "file" then 69672cf7db3SKyle Evans config.readConf(fpath, loaded_files) 69772cf7db3SKyle Evans end 69872cf7db3SKyle Evans end 69972cf7db3SKyle Evans end 70072cf7db3SKyle Evans ::nextdir:: 70172cf7db3SKyle Evans end 70272cf7db3SKyle Evans end 703a25531dbSStéphane Rochoy 704a25531dbSStéphane Rochoy -- Always allow overriding with local config files, e.g., 705a25531dbSStéphane Rochoy -- /boot/loader.conf.local. 706a25531dbSStéphane Rochoy local local_loader_conf_files = getEnv("local_loader_conf_files") 707a25531dbSStéphane Rochoy if local_loader_conf_files then 708a25531dbSStéphane Rochoy for name in local_loader_conf_files:gmatch("[%w%p]+") do 709a25531dbSStéphane Rochoy config.readConf(name, loaded_files) 710a25531dbSStéphane Rochoy end 711a25531dbSStéphane Rochoy end 71272cf7db3SKyle Evans end 7137a5c6c8bSKyle Evansend 7147a5c6c8bSKyle Evans 71518c286a0SKyle Evans-- other_kernel is optionally the name of a kernel to load, if not the default 71618c286a0SKyle Evans-- or autoloaded default from the module_path 717322a2dddSKyle Evansfunction config.loadKernel(other_kernel) 718aedd6be5SKyle Evans local flags = loader.getenv("kernel_options") or "" 719aedd6be5SKyle Evans local kernel = other_kernel or loader.getenv("kernel") 720088b4f5fSWarner Losh 721322a2dddSKyle Evans local function tryLoad(names) 722088b4f5fSWarner Losh for name in names:gmatch("([^;]+)%s*;?") do 72380eb81f6SKyle Evans local r = loader.perform("load " .. name .. 72480eb81f6SKyle Evans " " .. flags) 7259f71d421SKyle Evans if r == 0 then 726aedd6be5SKyle Evans return name 727088b4f5fSWarner Losh end 728088b4f5fSWarner Losh end 729aedd6be5SKyle Evans return nil 73018c286a0SKyle Evans end 731088b4f5fSWarner Losh 7325dd1b834SKyle Evans local function getModulePath() 7335dd1b834SKyle Evans local module_path = loader.getenv("module_path") 7345dd1b834SKyle Evans local kernel_path = loader.getenv("kernel_path") 7355dd1b834SKyle Evans 7365dd1b834SKyle Evans if kernel_path == nil then 7375dd1b834SKyle Evans return module_path 7385dd1b834SKyle Evans end 7395dd1b834SKyle Evans 7405dd1b834SKyle Evans -- Strip the loaded kernel path from module_path. This currently assumes 7415dd1b834SKyle Evans -- that the kernel path will be prepended to the module_path when it's 7425dd1b834SKyle Evans -- found. 7435dd1b834SKyle Evans kernel_path = escapeName(kernel_path .. ';') 7445dd1b834SKyle Evans return module_path:gsub(kernel_path, '') 7455dd1b834SKyle Evans end 7465dd1b834SKyle Evans 747322a2dddSKyle Evans local function loadBootfile() 748aedd6be5SKyle Evans local bootfile = loader.getenv("bootfile") 749088b4f5fSWarner Losh 750088b4f5fSWarner Losh -- append default kernel name 7519f71d421SKyle Evans if bootfile == nil then 752aedd6be5SKyle Evans bootfile = "kernel" 753088b4f5fSWarner Losh else 754aedd6be5SKyle Evans bootfile = bootfile .. ";kernel" 755088b4f5fSWarner Losh end 756088b4f5fSWarner Losh 757322a2dddSKyle Evans return tryLoad(bootfile) 75824a1bd54SKyle Evans end 759088b4f5fSWarner Losh 760088b4f5fSWarner Losh -- kernel not set, try load from default module_path 7619f71d421SKyle Evans if kernel == nil then 762322a2dddSKyle Evans local res = loadBootfile() 763088b4f5fSWarner Losh 7649f71d421SKyle Evans if res ~= nil then 765d4591301SKyle Evans -- Default kernel is loaded 766aedd6be5SKyle Evans config.kernel_loaded = nil 767aedd6be5SKyle Evans return true 768088b4f5fSWarner Losh else 769fdabb5f5SKyle Evans print(MSG_DEFAULTKERNFAIL) 770aedd6be5SKyle Evans return false 771088b4f5fSWarner Losh end 772088b4f5fSWarner Losh else 77315d8e03cSKyle Evans -- Use our cached module_path, so we don't end up with multiple 77415d8e03cSKyle Evans -- automatically added kernel paths to our final module_path 7755dd1b834SKyle Evans local module_path = getModulePath() 776e2df27e3SKyle Evans local res 777088b4f5fSWarner Losh 7789f71d421SKyle Evans if other_kernel ~= nil then 779aedd6be5SKyle Evans kernel = other_kernel 78018c286a0SKyle Evans end 781088b4f5fSWarner Losh -- first try load kernel with module_path = /boot/${kernel} 782088b4f5fSWarner Losh -- then try load with module_path=${kernel} 783aedd6be5SKyle Evans local paths = {"/boot/" .. kernel, kernel} 784088b4f5fSWarner Losh 785e2df27e3SKyle Evans for _, v in pairs(paths) do 786aedd6be5SKyle Evans loader.setenv("module_path", v) 787322a2dddSKyle Evans res = loadBootfile() 788088b4f5fSWarner Losh 78915d8e03cSKyle Evans -- succeeded, add path to module_path 7909f71d421SKyle Evans if res ~= nil then 791aedd6be5SKyle Evans config.kernel_loaded = kernel 7929f71d421SKyle Evans if module_path ~= nil then 793c990f0a9SKyle Evans loader.setenv("module_path", v .. ";" .. 794aedd6be5SKyle Evans module_path) 7955dd1b834SKyle Evans loader.setenv("kernel_path", v) 796c990f0a9SKyle Evans end 797aedd6be5SKyle Evans return true 798088b4f5fSWarner Losh end 799088b4f5fSWarner Losh end 800088b4f5fSWarner Losh 801088b4f5fSWarner Losh -- failed to load with ${kernel} as a directory 802088b4f5fSWarner Losh -- try as a file 803322a2dddSKyle Evans res = tryLoad(kernel) 8049f71d421SKyle Evans if res ~= nil then 805aedd6be5SKyle Evans config.kernel_loaded = kernel 806aedd6be5SKyle Evans return true 807088b4f5fSWarner Losh else 808fdabb5f5SKyle Evans print(MSG_KERNFAIL:format(kernel)) 809aedd6be5SKyle Evans return false 810088b4f5fSWarner Losh end 811088b4f5fSWarner Losh end 812088b4f5fSWarner Loshend 813088b4f5fSWarner Losh 814322a2dddSKyle Evansfunction config.selectKernel(kernel) 815aedd6be5SKyle Evans config.kernel_selected = kernel 816fa4a2394SKyle Evansend 817088b4f5fSWarner Losh 8187aba5b2fSKyle Evansfunction config.load(file, reloading) 8199f71d421SKyle Evans if not file then 820aedd6be5SKyle Evans file = "/boot/defaults/loader.conf" 821088b4f5fSWarner Losh end 822088b4f5fSWarner Losh 8233fe0ac6aSKyle Evans config.readConf(file) 824088b4f5fSWarner Losh 825322a2dddSKyle Evans checkNextboot() 8263dcb7648SKyle Evans 8278d21763eSKyle Evans local verbose = loader.getenv("verbose_loading") or "no" 828f0b03262SKyle Evans config.verbose = verbose:lower() == "yes" 8297aba5b2fSKyle Evans if not reloading then 8307aba5b2fSKyle Evans hook.runAll("config.loaded") 8317aba5b2fSKyle Evans end 832fa4a2394SKyle Evansend 833fa4a2394SKyle Evans 834fa4a2394SKyle Evans-- Reload configuration 835fa4a2394SKyle Evansfunction config.reload(file) 836aedd6be5SKyle Evans modules = {} 83764c91742SKyle Evans restoreEnv() 8387aba5b2fSKyle Evans config.load(file, true) 839aea262bfSKyle Evans hook.runAll("config.reloaded") 840fa4a2394SKyle Evansend 841fa4a2394SKyle Evans 842fa4a2394SKyle Evansfunction config.loadelf() 8430d7bee6aSKyle Evans local xen_kernel = loader.getenv('xen_kernel') 844aedd6be5SKyle Evans local kernel = config.kernel_selected or config.kernel_loaded 84579c20f22SRyan Moeller local status 84615d8e03cSKyle Evans 8470d7bee6aSKyle Evans if xen_kernel ~= nil then 8480d7bee6aSKyle Evans print(MSG_XENKERNLOADING) 8490d7bee6aSKyle Evans if cli_execute_unparsed('load ' .. xen_kernel) ~= 0 then 8500d7bee6aSKyle Evans print(MSG_XENKERNFAIL:format(xen_kernel)) 8513078173cSKyle Evans return false 8520d7bee6aSKyle Evans end 8530d7bee6aSKyle Evans end 854fdabb5f5SKyle Evans print(MSG_KERNLOADING) 85579c20f22SRyan Moeller if not config.loadKernel(kernel) then 8563078173cSKyle Evans return false 857fa4a2394SKyle Evans end 85879c20f22SRyan Moeller hook.runAll("kernel.loaded") 859088b4f5fSWarner Losh 860fdabb5f5SKyle Evans print(MSG_MODLOADING) 8610db2ca0cSKyle Evans status = loadModule(modules, not config.verbose) 8620db2ca0cSKyle Evans hook.runAll("modules.loaded") 8630db2ca0cSKyle Evans return status 864088b4f5fSWarner Loshend 865088b4f5fSWarner Losh 8664634bb1fSKyle Evansfunction config.enableModule(modname) 8674634bb1fSKyle Evans if modules[modname] == nil then 8684634bb1fSKyle Evans modules[modname] = {} 8694634bb1fSKyle Evans elseif modules[modname].load == "YES" then 8704634bb1fSKyle Evans modules[modname].force = true 8714634bb1fSKyle Evans return true 8724634bb1fSKyle Evans end 8734634bb1fSKyle Evans 8744634bb1fSKyle Evans modules[modname].load = "YES" 8754634bb1fSKyle Evans modules[modname].force = true 8764634bb1fSKyle Evans return true 8774634bb1fSKyle Evansend 8784634bb1fSKyle Evans 8794634bb1fSKyle Evansfunction config.disableModule(modname) 8804634bb1fSKyle Evans if modules[modname] == nil then 8814634bb1fSKyle Evans return false 8824634bb1fSKyle Evans elseif modules[modname].load ~= "YES" then 8834634bb1fSKyle Evans return true 8844634bb1fSKyle Evans end 8854634bb1fSKyle Evans 8864634bb1fSKyle Evans modules[modname].load = "NO" 8874634bb1fSKyle Evans modules[modname].force = nil 8884634bb1fSKyle Evans return true 8894634bb1fSKyle Evansend 8904634bb1fSKyle Evans 8914634bb1fSKyle Evansfunction config.isModuleEnabled(modname) 8924634bb1fSKyle Evans local mod = modules[modname] 8934634bb1fSKyle Evans if not mod or mod.load ~= "YES" then 8944634bb1fSKyle Evans return false 8954634bb1fSKyle Evans end 8964634bb1fSKyle Evans 8974634bb1fSKyle Evans if mod.force then 8984634bb1fSKyle Evans return true 8994634bb1fSKyle Evans end 9004634bb1fSKyle Evans 9014634bb1fSKyle Evans local blacklist = getBlacklist() 90210aeb6cdSKyle Evans return not blacklist[modname] 9034634bb1fSKyle Evansend 9044634bb1fSKyle Evans 9057ed84fa1SKyle Evansfunction config.getModuleInfo() 9067ed84fa1SKyle Evans return { 9077ed84fa1SKyle Evans modules = modules, 9087ed84fa1SKyle Evans blacklist = getBlacklist() 9097ed84fa1SKyle Evans } 9107ed84fa1SKyle Evansend 9117ed84fa1SKyle Evans 9123cb2f5f3SKyle Evanshook.registerType("config.buildenv") 9137aba5b2fSKyle Evanshook.registerType("config.loaded") 914aea262bfSKyle Evanshook.registerType("config.reloaded") 9154bee6189SRyan Moellerhook.registerType("kernel.loaded") 9160db2ca0cSKyle Evanshook.registerType("modules.loaded") 917aedd6be5SKyle Evansreturn config 918