1e37f4622SKyle Evans-- 272e39d71SKyle Evans-- SPDX-License-Identifier: BSD-2-Clause-FreeBSD 372e39d71SKyle Evans-- 4e37f4622SKyle Evans-- Copyright (c) 2018 Kyle Evans <[email protected]> 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-- $FreeBSD$ 28e37f4622SKyle Evans-- 29e37f4622SKyle Evans 303e6c7d54SKyle Evanslocal config = require("config") 313e6c7d54SKyle Evanslocal core = require("core") 32e37f4622SKyle Evans 33e37f4622SKyle Evanslocal cli = {} 34e37f4622SKyle Evans 357ed84fa1SKyle Evansif not pager then 367ed84fa1SKyle Evans -- shim for the pager module that just doesn't do it. 377ed84fa1SKyle Evans -- XXX Remove after 12.2 goes EoL. 387ed84fa1SKyle Evans pager = { 397ed84fa1SKyle Evans open = function() end, 407ed84fa1SKyle Evans close = function() end, 417ed84fa1SKyle Evans output = function(str) 427ed84fa1SKyle Evans printc(str) 437ed84fa1SKyle Evans end, 447ed84fa1SKyle Evans } 457ed84fa1SKyle Evansend 467ed84fa1SKyle Evans 47e37f4622SKyle Evans-- Internal function 48e37f4622SKyle Evans-- Parses arguments to boot and returns two values: kernel_name, argstr 49e37f4622SKyle Evans-- Defaults to nil and "" respectively. 50e37f4622SKyle Evans-- This will also parse arguments to autoboot, but the with_kernel argument 51e37f4622SKyle Evans-- will need to be explicitly overwritten to false 52322a2dddSKyle Evanslocal function parseBootArgs(argv, with_kernel) 53e37f4622SKyle Evans if with_kernel == nil then 54e37f4622SKyle Evans with_kernel = true 55e37f4622SKyle Evans end 56e37f4622SKyle Evans if #argv == 0 then 57e37f4622SKyle Evans if with_kernel then 58e37f4622SKyle Evans return nil, "" 59e37f4622SKyle Evans else 60e37f4622SKyle Evans return "" 61e37f4622SKyle Evans end 62e37f4622SKyle Evans end 63e37f4622SKyle Evans local kernel_name 64e37f4622SKyle Evans local argstr = "" 65e37f4622SKyle Evans 66e2df27e3SKyle Evans for _, v in ipairs(argv) do 67e37f4622SKyle Evans if with_kernel and v:sub(1,1) ~= "-" then 68e37f4622SKyle Evans kernel_name = v 69e37f4622SKyle Evans else 70e37f4622SKyle Evans argstr = argstr .. " " .. v 71e37f4622SKyle Evans end 72e37f4622SKyle Evans end 73e37f4622SKyle Evans if with_kernel then 74e37f4622SKyle Evans return kernel_name, argstr 75e37f4622SKyle Evans else 76e37f4622SKyle Evans return argstr 77e37f4622SKyle Evans end 78e37f4622SKyle Evansend 79e37f4622SKyle Evans 804634bb1fSKyle Evanslocal function setModule(module, loading) 814634bb1fSKyle Evans if loading and config.enableModule(module) then 824634bb1fSKyle Evans print(module .. " will be loaded") 834634bb1fSKyle Evans elseif not loading and config.disableModule(module) then 844634bb1fSKyle Evans print(module .. " will not be loaded") 854634bb1fSKyle Evans end 864634bb1fSKyle Evansend 874634bb1fSKyle Evans 88e37f4622SKyle Evans-- Declares a global function cli_execute that attempts to dispatch the 89e37f4622SKyle Evans-- arguments passed as a lua function. This gives lua a chance to intercept 90e37f4622SKyle Evans-- builtin CLI commands like "boot" 9122ae8ae1SKyle Evans-- This function intentionally does not follow our general naming guideline for 9222ae8ae1SKyle Evans-- functions. This is global pollution, but the clearly separated 'cli' looks 9322ae8ae1SKyle Evans-- more like a module indicator to serve as a hint of where to look for the 9422ae8ae1SKyle Evans-- corresponding definition. 95e37f4622SKyle Evansfunction cli_execute(...) 96e37f4622SKyle Evans local argv = {...} 97e37f4622SKyle Evans -- Just in case... 98e37f4622SKyle Evans if #argv == 0 then 99c6d9f133SKyle Evans return loader.command(...) 100e37f4622SKyle Evans end 101e37f4622SKyle Evans 102e37f4622SKyle Evans local cmd_name = argv[1] 1032e4dad82SKyle Evans local cmd = cli[cmd_name] 104e37f4622SKyle Evans if cmd ~= nil and type(cmd) == "function" then 105e37f4622SKyle Evans -- Pass argv wholesale into cmd. We could omit argv[0] since the 106e37f4622SKyle Evans -- traditional reasons for including it don't necessarily apply, 107e37f4622SKyle Evans -- it may not be totally redundant if we want to have one global 108e37f4622SKyle Evans -- handling multiple commands 109c6d9f133SKyle Evans return cmd(...) 110e37f4622SKyle Evans else 111c6d9f133SKyle Evans return loader.command(...) 112e37f4622SKyle Evans end 113e37f4622SKyle Evans 114e37f4622SKyle Evansend 115e37f4622SKyle Evans 116ca3b8c9fSKyle Evansfunction cli_execute_unparsed(str) 117f6e00525SKyle Evans return cli_execute(loader.parse(str)) 118697f127dSKyle Evansend 119697f127dSKyle Evans 120eca5ca66SKyle Evans-- Module exports 121eca5ca66SKyle Evans 1222e4dad82SKyle Evansfunction cli.boot(...) 123e2df27e3SKyle Evans local _, argv = cli.arguments(...) 124322a2dddSKyle Evans local kernel, argstr = parseBootArgs(argv) 1252e4dad82SKyle Evans if kernel ~= nil then 1262e4dad82SKyle Evans loader.perform("unload") 127322a2dddSKyle Evans config.selectKernel(kernel) 1282e4dad82SKyle Evans end 1292e4dad82SKyle Evans core.boot(argstr) 1302e4dad82SKyle Evansend 1312e4dad82SKyle Evans 1322e4dad82SKyle Evansfunction cli.autoboot(...) 133e2df27e3SKyle Evans local _, argv = cli.arguments(...) 134322a2dddSKyle Evans local argstr = parseBootArgs(argv, false) 1352e4dad82SKyle Evans core.autoboot(argstr) 1362e4dad82SKyle Evansend 1372e4dad82SKyle Evans 13883f7a74cSKyle Evanscli['boot-conf'] = function(...) 13983f7a74cSKyle Evans local _, argv = cli.arguments(...) 14083f7a74cSKyle Evans local kernel, argstr = parseBootArgs(argv) 14183f7a74cSKyle Evans if kernel ~= nil then 14283f7a74cSKyle Evans loader.perform("unload") 14383f7a74cSKyle Evans config.selectKernel(kernel) 14483f7a74cSKyle Evans end 14583f7a74cSKyle Evans core.autoboot(argstr) 14683f7a74cSKyle Evansend 14783f7a74cSKyle Evans 148e40d2a04SKyle Evanscli['read-conf'] = function(...) 149e40d2a04SKyle Evans local _, argv = cli.arguments(...) 1503fe0ac6aSKyle Evans config.readConf(assert(core.popFrontTable(argv))) 151e40d2a04SKyle Evansend 152e40d2a04SKyle Evans 15394510c29SKyle Evanscli['reload-conf'] = function() 154af876563SKyle Evans config.reload() 155af876563SKyle Evansend 156af876563SKyle Evans 1574634bb1fSKyle Evanscli["enable-module"] = function(...) 1584634bb1fSKyle Evans local _, argv = cli.arguments(...) 1594634bb1fSKyle Evans if #argv == 0 then 1604634bb1fSKyle Evans print("usage error: enable-module module") 1614634bb1fSKyle Evans return 1624634bb1fSKyle Evans end 1634634bb1fSKyle Evans 1644634bb1fSKyle Evans setModule(argv[1], true) 1654634bb1fSKyle Evansend 1664634bb1fSKyle Evans 1674634bb1fSKyle Evanscli["disable-module"] = function(...) 1684634bb1fSKyle Evans local _, argv = cli.arguments(...) 1694634bb1fSKyle Evans if #argv == 0 then 1704634bb1fSKyle Evans print("usage error: disable-module module") 1714634bb1fSKyle Evans return 1724634bb1fSKyle Evans end 1734634bb1fSKyle Evans 1744634bb1fSKyle Evans setModule(argv[1], false) 1754634bb1fSKyle Evansend 1764634bb1fSKyle Evans 1774634bb1fSKyle Evanscli["toggle-module"] = function(...) 1784634bb1fSKyle Evans local _, argv = cli.arguments(...) 1794634bb1fSKyle Evans if #argv == 0 then 1804634bb1fSKyle Evans print("usage error: toggle-module module") 1814634bb1fSKyle Evans return 1824634bb1fSKyle Evans end 1834634bb1fSKyle Evans 1844634bb1fSKyle Evans local module = argv[1] 1854634bb1fSKyle Evans setModule(module, not config.isModuleEnabled(module)) 1864634bb1fSKyle Evansend 1874634bb1fSKyle Evans 1887ed84fa1SKyle Evanscli["show-module-options"] = function() 1897ed84fa1SKyle Evans local module_info = config.getModuleInfo() 1907ed84fa1SKyle Evans local modules = module_info['modules'] 1917ed84fa1SKyle Evans local blacklist = module_info['blacklist'] 1927ed84fa1SKyle Evans local lines = {} 1937ed84fa1SKyle Evans 1947ed84fa1SKyle Evans for module, info in pairs(modules) do 1957ed84fa1SKyle Evans if #lines > 0 then 1967ed84fa1SKyle Evans lines[#lines + 1] = "" 1977ed84fa1SKyle Evans end 1987ed84fa1SKyle Evans 1997ed84fa1SKyle Evans lines[#lines + 1] = "Name: " .. module 2007ed84fa1SKyle Evans if info.name then 2017ed84fa1SKyle Evans lines[#lines + 1] = "Path: " .. info.name 2027ed84fa1SKyle Evans end 2037ed84fa1SKyle Evans 2047ed84fa1SKyle Evans if info.type then 2057ed84fa1SKyle Evans lines[#lines + 1] = "Type: " .. info.type 2067ed84fa1SKyle Evans end 2077ed84fa1SKyle Evans 2087ed84fa1SKyle Evans if info.flags then 2097ed84fa1SKyle Evans lines[#lines + 1] = "Flags: " .. info.flags 2107ed84fa1SKyle Evans end 2117ed84fa1SKyle Evans 2127ed84fa1SKyle Evans if info.before then 2137ed84fa1SKyle Evans lines[#lines + 1] = "Before load: " .. info.before 2147ed84fa1SKyle Evans end 2157ed84fa1SKyle Evans 2167ed84fa1SKyle Evans if info.after then 2177ed84fa1SKyle Evans lines[#lines + 1] = "After load: " .. info.after 2187ed84fa1SKyle Evans end 2197ed84fa1SKyle Evans 2207ed84fa1SKyle Evans if info.error then 2217ed84fa1SKyle Evans lines[#lines + 1] = "Error: " .. info.error 2227ed84fa1SKyle Evans end 2237ed84fa1SKyle Evans 2247ed84fa1SKyle Evans local status 2257ed84fa1SKyle Evans if blacklist[module] and not info.force then 2267ed84fa1SKyle Evans status = "Blacklisted" 2277ed84fa1SKyle Evans elseif info.load == "YES" then 2287ed84fa1SKyle Evans status = "Load" 2297ed84fa1SKyle Evans else 2307ed84fa1SKyle Evans status = "Don't load" 2317ed84fa1SKyle Evans end 2327ed84fa1SKyle Evans 2337ed84fa1SKyle Evans lines[#lines + 1] = "Status: " .. status 2347ed84fa1SKyle Evans end 2357ed84fa1SKyle Evans 2367ed84fa1SKyle Evans pager.open() 23729842cb3SKyle Evans for _, v in ipairs(lines) do 2387ed84fa1SKyle Evans pager.output(v .. "\n") 2397ed84fa1SKyle Evans end 2407ed84fa1SKyle Evans pager.close() 2417ed84fa1SKyle Evansend 2427ed84fa1SKyle Evans 243*25b4b24eSWarner Loshcli["disable-device"] = function(...) 244*25b4b24eSWarner Losh local _, argv = cli.arguments(...) 245*25b4b24eSWarner Losh local d, u 246*25b4b24eSWarner Losh 247*25b4b24eSWarner Losh if #argv == 0 then 248*25b4b24eSWarner Losh print("usage error: disable-device device") 249*25b4b24eSWarner Losh return 250*25b4b24eSWarner Losh end 251*25b4b24eSWarner Losh 252*25b4b24eSWarner Losh d, u = string.match(argv[1], "(%w*%a)(%d+)") 253*25b4b24eSWarner Losh if d ~= nil then 254*25b4b24eSWarner Losh loader.setenv("hint." .. d .. "." .. u .. ".disabled", "1") 255*25b4b24eSWarner Losh end 256*25b4b24eSWarner Loshend 257*25b4b24eSWarner Losh 2582e4dad82SKyle Evans-- Used for splitting cli varargs into cmd_name and the rest of argv 259eca5ca66SKyle Evansfunction cli.arguments(...) 260eca5ca66SKyle Evans local argv = {...} 261e2df27e3SKyle Evans local cmd_name 262eca5ca66SKyle Evans cmd_name, argv = core.popFrontTable(argv) 263eca5ca66SKyle Evans return cmd_name, argv 264eca5ca66SKyle Evansend 265eca5ca66SKyle Evans 266e37f4622SKyle Evansreturn cli 267