1e37f4622SKyle Evans-- 24d846d26SWarner Losh-- SPDX-License-Identifier: BSD-2-Clause 372e39d71SKyle Evans-- 4e37f4622SKyle Evans-- Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org> 5e37f4622SKyle Evans-- 6e37f4622SKyle Evans-- Redistribution and use in source and binary forms, with or without 7e37f4622SKyle Evans-- modification, are permitted provided that the following conditions 8e37f4622SKyle Evans-- are met: 9e37f4622SKyle Evans-- 1. Redistributions of source code must retain the above copyright 10e37f4622SKyle Evans-- notice, this list of conditions and the following disclaimer. 11e37f4622SKyle Evans-- 2. Redistributions in binary form must reproduce the above copyright 12e37f4622SKyle Evans-- notice, this list of conditions and the following disclaimer in the 13e37f4622SKyle Evans-- documentation and/or other materials provided with the distribution. 14e37f4622SKyle Evans-- 15e37f4622SKyle Evans-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16e37f4622SKyle Evans-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17e37f4622SKyle Evans-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18e37f4622SKyle Evans-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19e37f4622SKyle Evans-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20e37f4622SKyle Evans-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21e37f4622SKyle Evans-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22e37f4622SKyle Evans-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23e37f4622SKyle Evans-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24e37f4622SKyle Evans-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25e37f4622SKyle Evans-- SUCH DAMAGE. 26e37f4622SKyle Evans-- 27e37f4622SKyle Evans 283e6c7d54SKyle Evanslocal config = require("config") 293e6c7d54SKyle Evanslocal core = require("core") 30e37f4622SKyle Evans 31e37f4622SKyle Evanslocal cli = {} 32e37f4622SKyle Evans 33*b38a82c7SWarner Loshif not pager then 34*b38a82c7SWarner Losh -- shim for the pager module that just doesn't do it. 35*b38a82c7SWarner Losh -- XXX Remove after 12.2 goes EoL. 36*b38a82c7SWarner Losh pager = { 37*b38a82c7SWarner Losh open = function() end, 38*b38a82c7SWarner Losh close = function() end, 39*b38a82c7SWarner Losh output = function(str) 40*b38a82c7SWarner Losh printc(str) 41*b38a82c7SWarner Losh end, 42*b38a82c7SWarner Losh } 43*b38a82c7SWarner Loshend 44*b38a82c7SWarner Losh 45e37f4622SKyle Evans-- Internal function 46e37f4622SKyle Evans-- Parses arguments to boot and returns two values: kernel_name, argstr 47e37f4622SKyle Evans-- Defaults to nil and "" respectively. 48e37f4622SKyle Evans-- This will also parse arguments to autoboot, but the with_kernel argument 49e37f4622SKyle Evans-- will need to be explicitly overwritten to false 50322a2dddSKyle Evanslocal function parseBootArgs(argv, with_kernel) 51e37f4622SKyle Evans if with_kernel == nil then 52e37f4622SKyle Evans with_kernel = true 53e37f4622SKyle Evans end 54e37f4622SKyle Evans if #argv == 0 then 55e37f4622SKyle Evans if with_kernel then 56e37f4622SKyle Evans return nil, "" 57e37f4622SKyle Evans else 58e37f4622SKyle Evans return "" 59e37f4622SKyle Evans end 60e37f4622SKyle Evans end 61e37f4622SKyle Evans local kernel_name 62e37f4622SKyle Evans local argstr = "" 63e37f4622SKyle Evans 64e2df27e3SKyle Evans for _, v in ipairs(argv) do 65e37f4622SKyle Evans if with_kernel and v:sub(1,1) ~= "-" then 66e37f4622SKyle Evans kernel_name = v 67e37f4622SKyle Evans else 68e37f4622SKyle Evans argstr = argstr .. " " .. v 69e37f4622SKyle Evans end 70e37f4622SKyle Evans end 71e37f4622SKyle Evans if with_kernel then 72e37f4622SKyle Evans return kernel_name, argstr 73e37f4622SKyle Evans else 74e37f4622SKyle Evans return argstr 75e37f4622SKyle Evans end 76e37f4622SKyle Evansend 77e37f4622SKyle Evans 784634bb1fSKyle Evanslocal function setModule(module, loading) 794634bb1fSKyle Evans if loading and config.enableModule(module) then 804634bb1fSKyle Evans print(module .. " will be loaded") 814634bb1fSKyle Evans elseif not loading and config.disableModule(module) then 824634bb1fSKyle Evans print(module .. " will not be loaded") 834634bb1fSKyle Evans end 844634bb1fSKyle Evansend 854634bb1fSKyle Evans 86e37f4622SKyle Evans-- Declares a global function cli_execute that attempts to dispatch the 87e37f4622SKyle Evans-- arguments passed as a lua function. This gives lua a chance to intercept 88e37f4622SKyle Evans-- builtin CLI commands like "boot" 8922ae8ae1SKyle Evans-- This function intentionally does not follow our general naming guideline for 9022ae8ae1SKyle Evans-- functions. This is global pollution, but the clearly separated 'cli' looks 9122ae8ae1SKyle Evans-- more like a module indicator to serve as a hint of where to look for the 9222ae8ae1SKyle Evans-- corresponding definition. 93e37f4622SKyle Evansfunction cli_execute(...) 94e37f4622SKyle Evans local argv = {...} 95e37f4622SKyle Evans -- Just in case... 96e37f4622SKyle Evans if #argv == 0 then 97c6d9f133SKyle Evans return loader.command(...) 98e37f4622SKyle Evans end 99e37f4622SKyle Evans 100e37f4622SKyle Evans local cmd_name = argv[1] 1012e4dad82SKyle Evans local cmd = cli[cmd_name] 102e37f4622SKyle Evans if cmd ~= nil and type(cmd) == "function" then 103e37f4622SKyle Evans -- Pass argv wholesale into cmd. We could omit argv[0] since the 104e37f4622SKyle Evans -- traditional reasons for including it don't necessarily apply, 105e37f4622SKyle Evans -- it may not be totally redundant if we want to have one global 106e37f4622SKyle Evans -- handling multiple commands 107c6d9f133SKyle Evans return cmd(...) 108e37f4622SKyle Evans else 109c6d9f133SKyle Evans return loader.command(...) 110e37f4622SKyle Evans end 111e37f4622SKyle Evans 112e37f4622SKyle Evansend 113e37f4622SKyle Evans 114ca3b8c9fSKyle Evansfunction cli_execute_unparsed(str) 115f6e00525SKyle Evans return cli_execute(loader.parse(str)) 116697f127dSKyle Evansend 117697f127dSKyle Evans 118eca5ca66SKyle Evans-- Module exports 119eca5ca66SKyle Evans 1202e4dad82SKyle Evansfunction cli.boot(...) 121e2df27e3SKyle Evans local _, argv = cli.arguments(...) 122322a2dddSKyle Evans local kernel, argstr = parseBootArgs(argv) 1232e4dad82SKyle Evans if kernel ~= nil then 1242e4dad82SKyle Evans loader.perform("unload") 125322a2dddSKyle Evans config.selectKernel(kernel) 1262e4dad82SKyle Evans end 1272e4dad82SKyle Evans core.boot(argstr) 1282e4dad82SKyle Evansend 1292e4dad82SKyle Evans 1302e4dad82SKyle Evansfunction cli.autoboot(...) 131e2df27e3SKyle Evans local _, argv = cli.arguments(...) 132322a2dddSKyle Evans local argstr = parseBootArgs(argv, false) 1332e4dad82SKyle Evans core.autoboot(argstr) 1342e4dad82SKyle Evansend 1352e4dad82SKyle Evans 13683f7a74cSKyle Evanscli['boot-conf'] = function(...) 13783f7a74cSKyle Evans local _, argv = cli.arguments(...) 13883f7a74cSKyle Evans local kernel, argstr = parseBootArgs(argv) 13983f7a74cSKyle Evans if kernel ~= nil then 14083f7a74cSKyle Evans loader.perform("unload") 14183f7a74cSKyle Evans config.selectKernel(kernel) 14283f7a74cSKyle Evans end 14383f7a74cSKyle Evans core.autoboot(argstr) 14483f7a74cSKyle Evansend 14583f7a74cSKyle Evans 146e40d2a04SKyle Evanscli['read-conf'] = function(...) 147e40d2a04SKyle Evans local _, argv = cli.arguments(...) 1483fe0ac6aSKyle Evans config.readConf(assert(core.popFrontTable(argv))) 149e40d2a04SKyle Evansend 150e40d2a04SKyle Evans 15194510c29SKyle Evanscli['reload-conf'] = function() 152af876563SKyle Evans config.reload() 153af876563SKyle Evansend 154af876563SKyle Evans 1554634bb1fSKyle Evanscli["enable-module"] = function(...) 1564634bb1fSKyle Evans local _, argv = cli.arguments(...) 1574634bb1fSKyle Evans if #argv == 0 then 1584634bb1fSKyle Evans print("usage error: enable-module module") 1594634bb1fSKyle Evans return 1604634bb1fSKyle Evans end 1614634bb1fSKyle Evans 1624634bb1fSKyle Evans setModule(argv[1], true) 1634634bb1fSKyle Evansend 1644634bb1fSKyle Evans 1654634bb1fSKyle Evanscli["disable-module"] = function(...) 1664634bb1fSKyle Evans local _, argv = cli.arguments(...) 1674634bb1fSKyle Evans if #argv == 0 then 1684634bb1fSKyle Evans print("usage error: disable-module module") 1694634bb1fSKyle Evans return 1704634bb1fSKyle Evans end 1714634bb1fSKyle Evans 1724634bb1fSKyle Evans setModule(argv[1], false) 1734634bb1fSKyle Evansend 1744634bb1fSKyle Evans 1754634bb1fSKyle Evanscli["toggle-module"] = function(...) 1764634bb1fSKyle Evans local _, argv = cli.arguments(...) 1774634bb1fSKyle Evans if #argv == 0 then 1784634bb1fSKyle Evans print("usage error: toggle-module module") 1794634bb1fSKyle Evans return 1804634bb1fSKyle Evans end 1814634bb1fSKyle Evans 1824634bb1fSKyle Evans local module = argv[1] 1834634bb1fSKyle Evans setModule(module, not config.isModuleEnabled(module)) 1844634bb1fSKyle Evansend 1854634bb1fSKyle Evans 1867ed84fa1SKyle Evanscli["show-module-options"] = function() 1877ed84fa1SKyle Evans local module_info = config.getModuleInfo() 1887ed84fa1SKyle Evans local modules = module_info['modules'] 1897ed84fa1SKyle Evans local blacklist = module_info['blacklist'] 1907ed84fa1SKyle Evans local lines = {} 1917ed84fa1SKyle Evans 1927ed84fa1SKyle Evans for module, info in pairs(modules) do 1937ed84fa1SKyle Evans if #lines > 0 then 1947ed84fa1SKyle Evans lines[#lines + 1] = "" 1957ed84fa1SKyle Evans end 1967ed84fa1SKyle Evans 1977ed84fa1SKyle Evans lines[#lines + 1] = "Name: " .. module 1987ed84fa1SKyle Evans if info.name then 1997ed84fa1SKyle Evans lines[#lines + 1] = "Path: " .. info.name 2007ed84fa1SKyle Evans end 2017ed84fa1SKyle Evans 2027ed84fa1SKyle Evans if info.type then 2037ed84fa1SKyle Evans lines[#lines + 1] = "Type: " .. info.type 2047ed84fa1SKyle Evans end 2057ed84fa1SKyle Evans 2067ed84fa1SKyle Evans if info.flags then 2077ed84fa1SKyle Evans lines[#lines + 1] = "Flags: " .. info.flags 2087ed84fa1SKyle Evans end 2097ed84fa1SKyle Evans 2107ed84fa1SKyle Evans if info.before then 2117ed84fa1SKyle Evans lines[#lines + 1] = "Before load: " .. info.before 2127ed84fa1SKyle Evans end 2137ed84fa1SKyle Evans 2147ed84fa1SKyle Evans if info.after then 2157ed84fa1SKyle Evans lines[#lines + 1] = "After load: " .. info.after 2167ed84fa1SKyle Evans end 2177ed84fa1SKyle Evans 2187ed84fa1SKyle Evans if info.error then 2197ed84fa1SKyle Evans lines[#lines + 1] = "Error: " .. info.error 2207ed84fa1SKyle Evans end 2217ed84fa1SKyle Evans 2227ed84fa1SKyle Evans local status 2237ed84fa1SKyle Evans if blacklist[module] and not info.force then 2247ed84fa1SKyle Evans status = "Blacklisted" 2257ed84fa1SKyle Evans elseif info.load == "YES" then 2267ed84fa1SKyle Evans status = "Load" 2277ed84fa1SKyle Evans else 2287ed84fa1SKyle Evans status = "Don't load" 2297ed84fa1SKyle Evans end 2307ed84fa1SKyle Evans 2317ed84fa1SKyle Evans lines[#lines + 1] = "Status: " .. status 2327ed84fa1SKyle Evans end 2337ed84fa1SKyle Evans 2347ed84fa1SKyle Evans pager.open() 23529842cb3SKyle Evans for _, v in ipairs(lines) do 2367ed84fa1SKyle Evans pager.output(v .. "\n") 2377ed84fa1SKyle Evans end 2387ed84fa1SKyle Evans pager.close() 2397ed84fa1SKyle Evansend 2407ed84fa1SKyle Evans 24107c4b78dSWarner Loshcli["disable-device"] = function(...) 24207c4b78dSWarner Losh local _, argv = cli.arguments(...) 24307c4b78dSWarner Losh local d, u 24407c4b78dSWarner Losh 24507c4b78dSWarner Losh if #argv == 0 then 24607c4b78dSWarner Losh print("usage error: disable-device device") 24707c4b78dSWarner Losh return 24807c4b78dSWarner Losh end 24907c4b78dSWarner Losh 25007c4b78dSWarner Losh d, u = string.match(argv[1], "(%w*%a)(%d+)") 25107c4b78dSWarner Losh if d ~= nil then 25207c4b78dSWarner Losh loader.setenv("hint." .. d .. "." .. u .. ".disabled", "1") 25307c4b78dSWarner Losh end 25407c4b78dSWarner Loshend 25507c4b78dSWarner Losh 2562e4dad82SKyle Evans-- Used for splitting cli varargs into cmd_name and the rest of argv 257eca5ca66SKyle Evansfunction cli.arguments(...) 258eca5ca66SKyle Evans local argv = {...} 259e2df27e3SKyle Evans local cmd_name 260eca5ca66SKyle Evans cmd_name, argv = core.popFrontTable(argv) 261eca5ca66SKyle Evans return cmd_name, argv 262eca5ca66SKyle Evansend 263eca5ca66SKyle Evans 264e37f4622SKyle Evansreturn cli 265