Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/lua/cli.lua
101564 views
1
--
2
-- SPDX-License-Identifier: BSD-2-Clause
3
--
4
-- Copyright (c) 2018 Kyle Evans <[email protected]>
5
--
6
-- Redistribution and use in source and binary forms, with or without
7
-- modification, are permitted provided that the following conditions
8
-- are met:
9
-- 1. Redistributions of source code must retain the above copyright
10
-- notice, this list of conditions and the following disclaimer.
11
-- 2. Redistributions in binary form must reproduce the above copyright
12
-- notice, this list of conditions and the following disclaimer in the
13
-- documentation and/or other materials provided with the distribution.
14
--
15
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
-- SUCH DAMAGE.
26
--
27
28
local config = require("config")
29
local core = require("core")
30
31
local cli = {}
32
33
-- Internal function
34
-- Parses arguments to boot and returns two values: kernel_name, argstr
35
-- Defaults to nil and "" respectively.
36
-- This will also parse arguments to autoboot, but the with_kernel argument
37
-- will need to be explicitly overwritten to false
38
local function parseBootArgs(argv, with_kernel)
39
if with_kernel == nil then
40
with_kernel = true
41
end
42
if #argv == 0 then
43
if with_kernel then
44
return nil, ""
45
else
46
return ""
47
end
48
end
49
local kernel_name
50
local argstr = ""
51
52
for _, v in ipairs(argv) do
53
if with_kernel and v:sub(1,1) ~= "-" then
54
kernel_name = v
55
else
56
argstr = argstr .. " " .. v
57
end
58
end
59
if with_kernel then
60
return kernel_name, argstr
61
else
62
return argstr
63
end
64
end
65
66
local function setModule(module, loading)
67
if loading and config.enableModule(module) then
68
print(module .. " will be loaded")
69
elseif not loading and config.disableModule(module) then
70
print(module .. " will not be loaded")
71
end
72
end
73
74
-- Declares a global function cli_execute that attempts to dispatch the
75
-- arguments passed as a lua function. This gives lua a chance to intercept
76
-- builtin CLI commands like "boot"
77
-- This function intentionally does not follow our general naming guideline for
78
-- functions. This is global pollution, but the clearly separated 'cli' looks
79
-- more like a module indicator to serve as a hint of where to look for the
80
-- corresponding definition.
81
function cli_execute(...)
82
local argv = {...}
83
-- Just in case...
84
if #argv == 0 then
85
return loader.command(...)
86
end
87
88
local cmd_name = argv[1]
89
local cmd = cli[cmd_name]
90
if cmd ~= nil and type(cmd) == "function" then
91
-- Pass argv wholesale into cmd. We could omit argv[0] since the
92
-- traditional reasons for including it don't necessarily apply,
93
-- it may not be totally redundant if we want to have one global
94
-- handling multiple commands
95
return cmd(...)
96
else
97
return loader.command(...)
98
end
99
100
end
101
102
function cli_execute_unparsed(str)
103
return cli_execute(loader.parse(str))
104
end
105
106
-- Module exports
107
108
function cli.boot(...)
109
local _, argv = cli.arguments(...)
110
local kernel, argstr = parseBootArgs(argv)
111
if kernel ~= nil then
112
loader.perform("unload")
113
config.selectKernel(kernel)
114
end
115
core.boot(argstr)
116
end
117
118
function cli.autoboot(...)
119
local _, argv = cli.arguments(...)
120
local argstr = parseBootArgs(argv, false)
121
core.autoboot(argstr)
122
end
123
124
cli['boot-conf'] = function(...)
125
local _, argv = cli.arguments(...)
126
local kernel, argstr = parseBootArgs(argv)
127
if kernel ~= nil then
128
loader.perform("unload")
129
config.selectKernel(kernel)
130
end
131
core.autoboot(argstr)
132
end
133
134
cli['read-conf'] = function(...)
135
local _, argv = cli.arguments(...)
136
config.readConf(assert(core.popFrontTable(argv)))
137
end
138
139
cli['reload-conf'] = function()
140
config.reload()
141
end
142
143
cli["enable-module"] = function(...)
144
local _, argv = cli.arguments(...)
145
if #argv == 0 then
146
print("usage error: enable-module module")
147
return
148
end
149
150
setModule(argv[1], true)
151
end
152
153
cli["disable-module"] = function(...)
154
local _, argv = cli.arguments(...)
155
if #argv == 0 then
156
print("usage error: disable-module module")
157
return
158
end
159
160
setModule(argv[1], false)
161
end
162
163
cli["toggle-module"] = function(...)
164
local _, argv = cli.arguments(...)
165
if #argv == 0 then
166
print("usage error: toggle-module module")
167
return
168
end
169
170
local module = argv[1]
171
setModule(module, not config.isModuleEnabled(module))
172
end
173
174
cli["show-module-options"] = function()
175
local module_info = config.getModuleInfo()
176
local modules = module_info['modules']
177
local blacklist = module_info['blacklist']
178
local lines = {}
179
180
for module, info in pairs(modules) do
181
if #lines > 0 then
182
lines[#lines + 1] = ""
183
end
184
185
lines[#lines + 1] = "Name: " .. module
186
if info.name then
187
lines[#lines + 1] = "Path: " .. info.name
188
end
189
190
if info.type then
191
lines[#lines + 1] = "Type: " .. info.type
192
end
193
194
if info.flags then
195
lines[#lines + 1] = "Flags: " .. info.flags
196
end
197
198
if info.before then
199
lines[#lines + 1] = "Before load: " .. info.before
200
end
201
202
if info.after then
203
lines[#lines + 1] = "After load: " .. info.after
204
end
205
206
if info.error then
207
lines[#lines + 1] = "Error: " .. info.error
208
end
209
210
local status
211
if blacklist[module] and not info.force then
212
status = "Blacklisted"
213
elseif info.load == "YES" then
214
status = "Load"
215
else
216
status = "Don't load"
217
end
218
219
lines[#lines + 1] = "Status: " .. status
220
end
221
222
pager.open()
223
for _, v in ipairs(lines) do
224
pager.output(v .. "\n")
225
end
226
pager.close()
227
end
228
229
cli["disable-device"] = function(...)
230
local _, argv = cli.arguments(...)
231
local d, u
232
233
if #argv == 0 then
234
print("usage error: disable-device device")
235
return
236
end
237
238
if #argv > 1 then
239
print("Too many arguments")
240
print("usage error: disable-device device")
241
return
242
end
243
244
d, u = string.match(argv[1], "(%w*%a)(%d+)")
245
if d ~= nil and u ~= nil then
246
loader.setenv("hint." .. d .. "." .. u .. ".disabled", "1")
247
else
248
print("Cannot parse " .. argv[1] .." into driver and unit number.")
249
end
250
end
251
252
-- Used for splitting cli varargs into cmd_name and the rest of argv
253
function cli.arguments(...)
254
local argv = {...}
255
local cmd_name
256
cmd_name, argv = core.popFrontTable(argv)
257
return cmd_name, argv
258
end
259
260
return cli
261
262