Add the lua scripts from the lua-bootloader SoC

These are the .lua files from from Pedro Souza's 2014 Summer of Code
project. Rui Paulo, Pedro Arthur and Wojciech A. Koszek also
contributed.

Obtained from: https://wiki.freebsd.org/SummerOfCode2014/LuaLoader
Sponsored by: Google Summer of Code

Improve the SoC lua menu code to bring it in line with forth
menu functionality

Submitted by: Zakary Nafziger
Sponsored by: FreeBSD Foundation

Use loader.setenv and loader.unsetenv instead of loader.perform

Convert from include("/boot/foo.lua") to foo = require("foo");
to bring in line with latest lua module conventions.

Enforce a uniform style for the new .lua files:
	o hard tab indenation for 8 spaces
	o don't have if foo then bar; else bas; end on one line

MFC After: 1 month
Relnotes: yes
Differential Review: https://reviews.freebsd.org/D14295
This commit is contained in:
Warner Losh 2018-02-12 15:32:00 +00:00
parent 7cafeaa1fd
commit 088b4f5f32
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=329167
10 changed files with 1521 additions and 0 deletions

View File

@ -10,6 +10,7 @@ SUBDIR+= forth
.endif
.if ${MK_LOADER_LUA} != "no"
SUBDIR+= liblua
SUBDIR+= lua
.endif
SUBDIR+= man

15
stand/lua/Makefile Normal file
View File

@ -0,0 +1,15 @@
# $FreeBSD$
.include <bsd.init.mk>
BINDIR= /boot/lua
FILES= color.lua \
config.lua \
core.lua \
drawer.lua \
loader.lua \
menu.lua \
password.lua \
screen.lua
.include <bsd.prog.mk>

99
stand/lua/color.lua Normal file
View File

@ -0,0 +1,99 @@
--
-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-- SUCH DAMAGE.
--
-- $FreeBSD$
--
local color = {};
local core = require("core");
color.BLACK = 0;
color.RED = 1;
color.GREEN = 2;
color.YELLOW = 3;
color.BLUE = 4;
color.MAGENTA = 5;
color.CYAN = 6;
color.WHITE = 7;
color.DEFAULT = 0;
color.BRIGHT = 1;
color.DIM = 2;
function color.isEnabled()
local c = loader.getenv("loader_color");
if c ~= nil then
if c:lower() == "no" or c == "0" then
return false;
end
end
return not core.bootserial();
end
color.disabled = not color.isEnabled();
function color.escapef(c)
if color.disabled then
return c;
end
return "\027[3"..c.."m";
end
function color.escapeb(c)
if color.disabled then
return c;
end
return "\027[4"..c.."m";
end
function color.escape(fg, bg, att)
if color.disabled then
return "";
end
if not att then
att = ""
else
att = att..";";
end
return "\027["..att.."3"..fg..";4"..bg.."m";
end
function color.default()
if color.disabled then
return "";
end
return "\027[0;37;40m";
end
function color.highlight(str)
if color.disabled then
return str;
end
return "\027[1m"..str.."\027[0m";
end
return color

371
stand/lua/config.lua Normal file
View File

@ -0,0 +1,371 @@
--
-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-- SUCH DAMAGE.
--
-- $FreeBSD$
--
local config = {};
local modules = {};
function config.setKey(k, n, v)
if modules[k] == nil then
modules[k] = {};
end
modules[k][n] = v;
end
local pattern_table = {
[1] = {
str = "^%s*(#.*)",
process = function(k, v) end
},
-- module_load="value"
[2] = {
str = "^%s*([%w_]+)_load%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
process = function(k, v)
if modules[k] == nil then
modules[k] = {};
end
modules[k].load = string.upper(v);
end
},
-- module_name="value"
[3] = {
str = "^%s*([%w_]+)_name%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
process = function(k, v)
config.setKey(k, "name", v);
end
},
-- module_type="value"
[4] = {
str = "^%s*([%w_]+)_type%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
process = function(k, v)
config.setKey(k, "type", v);
end
},
-- module_flags="value"
[5] = {
str = "^%s*([%w_]+)_flags%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
process = function(k, v)
config.setKey(k, "flags", v);
end
},
-- module_before="value"
[6] = {
str = "^%s*([%w_]+)_before%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
process = function(k, v)
config.setKey(k, "before", v);
end
},
-- module_after="value"
[7] = {
str = "^%s*([%w_]+)_after%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
process = function(k, v)
config.setKey(k, "after", v);
end
},
-- module_error="value"
[8] = {
str = "^%s*([%w_]+)_error%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
process = function(k, v)
config.setKey(k, "error", v);
end
},
-- exec="command"
[9] = {
str = "^%s*exec%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
process = function(k, v)
if loader.perform(k) ~= 0 then
print("Failed to exec '"..k.."'");
end
end
},
-- env_var="value"
[10] = {
str = "^%s*([%w%p]+)%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
process = function(k, v)
if loader.setenv(k, v) ~= 0 then
print("Failed to set '"..k.."' with value: "..v.."");
end
end
},
-- env_var=num
[11] = {
str = "^%s*([%w%p]+)%s*=%s*(%d+)%s*(.*)",
process = function(k, v)
if loader.setenv(k, v) ~= 0 then
print("Failed to set '"..k.."' with value: "..v.."");
end
end
}
};
function config.isValidComment(c)
if c ~= nil then
local s = string.match(c, "^%s*#.*");
if s == nil then
s = string.match(c, "^%s*$");
end
if s == nil then
return false;
end
end
return true;
end
function config.loadmod(mod, silent)
local status = true;
for k, v in pairs(mod) do
if v.load == "YES" then
local str = "load ";
if v.flags ~= nil then
str = str .. v.flags .. " ";
end
if v.type ~= nil then
str = str .. "-t " .. v.type .. " ";
end
if v.name ~= nil then
str = str .. v.name;
else
str = str .. k;
end
if v.before ~= nil then
if loader.perform(v.before) ~= 0 then
if not silent then
print("Failed to execute '"..v.before.."' before loading '"..k.."'");
end
status = false;
end
end
if loader.perform(str) ~= 0 then
if not silent then
print("Failed to execute '" .. str .. "'");
end
if v.error ~= nil then
loader.perform(v.error);
end
status = false;
end
if v.after ~= nil then
if loader.perform(v.after) ~= 0 then
if not silent then
print("Failed to execute '"..v.after.."' after loading '"..k.."'");
end
status = false;
end
end
else
--if not silent then print("Skiping module '".. k .. "'"); end
end
end
return status;
end
function config.parse(name, silent)
local f = io.open(name);
if f == nil then
if not silent then
print("Failed to open config: '" .. name.."'");
end
return false;
end
local text;
local r;
text, r = io.read(f);
if text == nil then
if not silent then
print("Failed to read config: '" .. name.."'");
end
return false;
end
local n = 1;
local status = true;
for line in string.gmatch(text, "([^\n]+)") do
if string.match(line, "^%s*$") == nil then
local found = false;
for i, val in ipairs(pattern_table) do
local k, v, c = string.match(line, val.str);
if k ~= nil then
found = true;
if config.isValidComment(c) then
val.process(k, v);
else
print("Malformed line ("..n.."):\n\t'"..line.."'");
status = false;
end
break;
end
end
if found == false then
print("Malformed line ("..n.."):\n\t'"..line.."'");
status = false;
end
end
n = n + 1;
end
return status;
end
function config.loadkernel()
local flags = loader.getenv("kernel_options") or "";
local kernel = loader.getenv("kernel");
local try_load = function (names)
for name in names:gmatch("([^;]+)%s*;?") do
r = loader.perform("load "..flags.." "..name);
if r == 0 then
return name;
end
end
return nil;
end;
local load_bootfile = function()
local bootfile = loader.getenv("bootfile");
-- append default kernel name
if not bootfile then
bootfile = "kernel";
else
bootfile = bootfile..";kernel";
end
return try_load(bootfile);
end;
-- kernel not set, try load from default module_path
if kernel == nil then
local res = load_bootfile();
if res ~= nil then
return true;
else
print("Failed to load kernel '"..res.."'");
return false;
end
else
local module_path = loader.getenv("module_path");
local res = nil;
-- first try load kernel with module_path = /boot/${kernel}
-- then try load with module_path=${kernel}
local paths = {"/boot/"..kernel, kernel};
for k,v in pairs(paths) do
loader.setenv("module_path", v);
res = load_bootfile();
-- succeeded add path to module_path
if res ~= nil then
loader.setenv("module_path", v..";"..module_path);
return true;
end
end
-- failed to load with ${kernel} as a directory
-- try as a file
res = try_load(kernel);
if res ~= nil then
return true;
else
print("Failed to load kernel '"..res.."'");
return false;
end
end
end
function config.load(file)
if not file then
file = "/boot/defaults/loader.conf";
end
if not config.parse(file) then
-- print("Failed to parse configuration: '"..file.."'");
end
local f = loader.getenv("loader_conf_files");
if f ~= nil then
for name in string.gmatch(f, "([%w%p]+)%s*") do
if not config.parse(name) then
-- print("Failed to parse configuration: '"..name.."'");
end
end
end
print("Loading kernel...");
config.loadkernel();
print("Loading configurations...");
if not config.loadmod(modules) then
print("Could not load configurations!");
end
end
function config.reload(kernel)
local res = 1;
-- unload all modules
print("Unloading modules...");
loader.perform("unload");
if kernel ~= nil then
res = loader.perform("load "..kernel);
if res == 0 then
print("Kernel '"..kernel.."' loaded!");
end
end
-- failed to load kernel or it is nil
-- then load default
if res == 1 then
print("Loading default kernel...");
config.loadkernel();
end
-- load modules
config.loadmod(modules);
end
return config

154
stand/lua/core.lua Normal file
View File

@ -0,0 +1,154 @@
--
-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-- SUCH DAMAGE.
--
-- $FreeBSD$
--
local core = {};
function core.setVerbose(b)
if (b == nil) then
b = not core.verbose;
end
if (b == true) then
loader.setenv("boot_verbose", "YES");
else
loader.unsetenv("boot_verbose");
end
core.verbose = b;
end
function core.setSingleUser(b)
if (b == nil) then
b = not core.su;
end
if (b == true) then
loader.setenv("boot_single", "YES");
else
loader.unsetenv("boot_single");
end
core.su = b;
end
function core.setACPI(b)
if (b == nil) then
b = not core.acpi;
end
if (b == true) then
loader.setenv("acpi_load", "YES");
loader.setenv("hint.acpi.0.disabled", "0");
loader.unsetenv("loader.acpi_disabled_by_user");
else
loader.unsetenv("acpi_load");
loader.setenv("hint.acpi.0.disabled", "1");
loader.setenv("loader.acpi_disabled_by_user", "1");
end
core.acpi = b;
end
function core.setSafeMode(b)
if (b == nil) then
b = not core.sm;
end
if (b == true) then
loader.setenv("kern.smp.disabled", "1");
loader.setenv("hw.ata.ata_dma", "0");
loader.setenv("hw.ata.atapi_dma", "0");
loader.setenv("hw.ata.wc", "0");
loader.setenv("hw.eisa_slots", "0");
loader.setenv("kern.eventtimer.periodic", "1");
loader.setenv("kern.geom.part.check_integrity", "0");
else
loader.unsetenv("kern.smp.disabled");
loader.unsetenv("hw.ata.ata_dma");
loader.unsetenv("hw.ata.atapi_dma");
loader.unsetenv("hw.ata.wc");
loader.unsetenv("hw.eisa_slots");
loader.unsetenv("kern.eventtimer.periodic");
loader.unsetenv("kern.geom.part.check_integrity");
end
core.sm = b;
end
function core.kernelList()
local k = loader.getenv("kernel");
local v = loader.getenv("kernels") or "";
local kernels = {};
local i = 0;
if k ~= nil then
i = i + 1;
kernels[i] = k;
end
for n in v:gmatch("([^; ]+)[; ]?") do
if n ~= k then
i = i + 1;
kernels[i] = n;
end
end
return kernels;
end
function core.setDefaults()
core.setACPI(true);
core.setSafeMode(false);
core.setSingleUser(false);
core.setVerbose(false);
end
function core.autoboot()
loader.perform("autoboot");
end
function core.boot()
loader.perform("boot");
end
function core.bootserial()
local c = loader.getenv("console");
if c ~= nil then
if c:find("comconsole") ~= nil then
return true;
end
end
local s = loader.getenv("boot_serial");
if s ~= nil then
return true;
end
local m = loader.getenv("boot_multicons");
if m ~= nil then
return true;
end
return false;
end
return core

309
stand/lua/drawer.lua Normal file
View File

@ -0,0 +1,309 @@
--
-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-- SUCH DAMAGE.
--
-- $FreeBSD$
--
local drawer = {};
local color = require("color");
local screen = require("screen");
drawer.brand_position = {x = 2, y = 1};
drawer.fbsd_logo = {
" ______ ____ _____ _____ ",
" | ____| | _ \\ / ____| __ \\ ",
" | |___ _ __ ___ ___ | |_) | (___ | | | |",
" | ___| '__/ _ \\/ _ \\| _ < \\___ \\| | | |",
" | | | | | __/ __/| |_) |____) | |__| |",
" | | | | | | || | | |",
" |_| |_| \\___|\\___||____/|_____/|_____/ "
};
drawer.logo_position = {x = 46, y = 1};
drawer.beastie_color = {
" \027[31m, ,",
" /( )`",
" \\ \\___ / |",
" /- \027[37m_\027[31m `-/ '",
" (\027[37m/\\/ \\\027[31m \\ /\\",
" \027[37m/ / |\027[31m ` \\",
" \027[34mO O \027[37m) \027[31m/ |",
" \027[37m`-^--'\027[31m`< '",
" (_.) _ ) /",
" `.___/` /",
" `-----' /",
" \027[33m<----.\027[31m __ / __ \\",
" \027[33m<----|====\027[31mO)))\027[33m==\027[31m) \\) /\027[33m====|",
" \027[33m<----'\027[31m `--' `.__,' \\",
" | |",
" \\ / /\\",
" \027[36m______\027[31m( (_ / \\______/",
" \027[36m,' ,-----' |",
" `--{__________)\027[37m"
};
drawer.beastie = {
" , ,",
" /( )`",
" \\ \\___ / |",
" /- _ `-/ '",
" (/\\/ \\ \\ /\\",
" / / | ` \\",
" O O ) / |",
" `-^--'`< '",
" (_.) _ ) /",
" `.___/` /",
" `-----' /",
" <----. __ / __ \\",
" <----|====O)))==) \\) /====|",
" <----' `--' `.__,' \\",
" | |",
" \\ / /\\",
" ______( (_ / \\______/",
" ,' ,-----' |",
" `--{__________)"
};
drawer.fbsd_logo_shift = {x = 5, y = 4};
drawer.fbsd_logo_v = {
" ______",
" | ____| __ ___ ___ ",
" | |__ | '__/ _ \\/ _ \\",
" | __|| | | __/ __/",
" | | | | | | |",
" |_| |_| \\___|\\___|",
" ____ _____ _____",
" | _ \\ / ____| __ \\",
" | |_) | (___ | | | |",
" | _ < \\___ \\| | | |",
" | |_) |____) | |__| |",
" | | | |",
" |____/|_____/|_____/"
};
drawer.orb_shift = {x = 2, y = 4};
drawer.orb_color = {
" \027[31m``` \027[31;1m`\027[31m",
" s` `.....---...\027[31;1m....--.``` -/\027[31m",
" +o .--` \027[31;1m/y:` +.\027[31m",
" yo`:. \027[31;1m:o `+-\027[31m",
" y/ \027[31;1m-/` -o/\027[31m",
" .- \027[31;1m::/sy+:.\027[31m",
" / \027[31;1m`-- /\027[31m",
" `: \027[31;1m:`\027[31m",
" `: \027[31;1m:`\027[31m",
" / \027[31;1m/\027[31m",
" .- \027[31;1m-.\027[31m",
" -- \027[31;1m-.\027[31m",
" `:` \027[31;1m`:`",
" \027[31;1m.-- `--.",
" .---.....----.\027[37m"
};
drawer.orb = {
" ``` `",
" s` `.....---.......--.``` -/",
" +o .--` /y:` +.",
" yo`:. :o `+-",
" y/ -/` -o/",
" .- ::/sy+:.",
" / `-- /",
" `: :`",
" `: :`",
" / /",
" .- -.",
" -- -.",
" `:` `:`",
" .-- `--.",
" .---.....----."
};
drawer.none = {""};
drawer.none_shift = {x = 17, y = 0};
drawer.menu_position = {x = 6, y = 11};
drawer.box_pos_dim = {x = 3, y = 10, w = 41, h = 11};
function drawer.drawscreen(menu_opts)
-- drawlogo() must go first.
-- it determines the positions of other elements
drawer.drawlogo();
drawer.drawbrand();
drawer.drawbox();
return drawer.drawmenu(menu_opts);
end
function drawer.drawmenu(m)
x = drawer.menu_position.x;
y = drawer.menu_position.y;
-- print the menu and build the alias table
local alias_table = {};
local entry_num = 0;
for line_num, e in ipairs(m) do
if (e.entry_type ~= "separator") then
entry_num = entry_num + 1;
screen.setcursor(x, y + line_num);
print(entry_num .. ". "..e.name());
-- fill the alias table
alias_table[tostring(entry_num)] = e;
for n, a in ipairs(e.alias) do
alias_table[a] = e;
end
else
screen.setcursor(x, y + line_num);
print(e.name());
end
end
return alias_table;
end
function drawer.drawbox()
x = drawer.box_pos_dim.x;
y = drawer.box_pos_dim.y;
w = drawer.box_pos_dim.w;
h = drawer.box_pos_dim.h;
local hl = string.char(0xCD);
local vl = string.char(0xBA);
local tl = string.char(0xC9);
local bl = string.char(0xC8);
local tr = string.char(0xBB);
local br = string.char(0xBC);
screen.setcursor(x, y); print(tl);
screen.setcursor(x, y+h); print(bl);
screen.setcursor(x+w, y); print(tr);
screen.setcursor(x+w, y+h); print(br);
for i = 1, w-1 do
screen.setcursor(x+i, y);
print(hl);
screen.setcursor(x+i, y+h);
print(hl);
end
for i = 1, h-1 do
screen.setcursor(x, y+i);
print(vl);
screen.setcursor(x+w, y+i);
print(vl);
end
screen.setcursor(x+(w/2)-9, y);
print("Welcome to FreeBSD");
end
function drawer.draw(x, y, logo)
for i = 1, #logo do
screen.setcursor(x, y + i);
print(logo[i]);
end
end
function drawer.drawbrand()
local x = tonumber(loader.getenv("loader_brand_x"));
local y = tonumber(loader.getenv("loader_brand_y"));
if not x then
x = drawer.brand_position.x;
end
if not y then
y = drawer.brand_position.y;
end
local logo = load("return " .. tostring(loader.getenv("loader_brand")))();
if not logo then
logo = drawer.fbsd_logo;
end
drawer.draw(x, y, logo);
end
function drawer.drawlogo()
local x = tonumber(loader.getenv("loader_logo_x"));
local y = tonumber(loader.getenv("loader_logo_y"));
if not x then
x = drawer.logo_position.x;
end
if not y then
y = drawer.logo_position.y;
end
local logo = loader.getenv("loader_logo");
local s = {x = 0, y = 0};
local colored = color.isEnabled();
if logo == "beastie" then
if colored then
logo = drawer.beastie_color;
end
elseif logo == "beastiebw" then
logo = drawer.beastie;
elseif logo == "fbsdbw" then
logo = drawer.fbsd_logo_v;
s = drawer.fbsd_logo_shift;
elseif logo == "orb" then
if colored then
logo = drawer.orb_color;
end
s = drawer.orb_shift;
elseif logo == "orbbw" then
logo = drawer.orb;
s = drawer.orb_shift;
elseif logo == "tribute" then
logo = drawer.fbsd_logo;
elseif logo == "tributebw" then
logo = drawer.fbsd_logo;
elseif logo == "none" then
--centre brand and text if no logo
drawer.brand_position.x = drawer.brand_position.x + drawer.none_shift.x;
drawer.brand_position.y = drawer.brand_position.y + drawer.none_shift.y;
drawer.menu_position.x = drawer.menu_position.x + drawer.none_shift.x;
drawer.menu_position.y = drawer.menu_position.y + drawer.none_shift.y;
drawer.box_pos_dim.x = drawer.box_pos_dim.x + drawer.none_shift.x;
drawer.box_pos_dim.y = drawer.box_pos_dim.y + drawer.none_shift.y;
--prevent redraws from moving menu further
drawer.none_shift.x = 0;
drawer.none_shift.y = 0;
logo = drawer.none;
end
if not logo then
if colored then
logo = drawer.orb_color;
else
logo = drawer.orb;
end
end
drawer.draw(x + s.x, y + s.y, logo);
end
return drawer

35
stand/lua/loader.lua Normal file
View File

@ -0,0 +1,35 @@
--
-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-- SUCH DAMAGE.
--
-- $FreeBSD$
--
config = require("config");
menu = require("menu");
password = require("password");
config.load();
password.check();
menu.run();

379
stand/lua/menu.lua Normal file
View File

@ -0,0 +1,379 @@
--
-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-- SUCH DAMAGE.
--
-- $FreeBSD$
--
local menu = {};
local core = require("core");
local color = require("color");
local config = require("config");
local screen = require("screen");
local drawer = require("drawer");
local OnOff;
local skip;
local run;
local autoboot;
--loader menu tree:
--rooted at menu.welcome
--submenu declarations:
local kernel_options;
local boot_options;
local welcome;
menu.kernel_options = {
-- this table is dynamically appended to when accessed
-- return to welcome menu
{
entry_type = "return",
name = function()
return "Back to main menu"..color.highlight(" [Backspace]");
end,
alias = {"\08"}
}
};
menu.boot_options = {
-- return to welcome menu
{
entry_type = "return",
name = function()
return "Back to main menu"..color.highlight(" [Backspace]");
end,
alias = {"\08"}
},
-- load defaults
{
entry_type = "entry",
name = function()
return "Load System "..color.highlight("D").."efaults";
end,
func = function()
core.setDefaults()
end,
alias = {"d", "D"}
},
{
entry_type = "separator",
name = function()
return "";
end
},
{
entry_type = "separator",
name = function()
return "Boot Options:";
end
},
-- acpi
{
entry_type = "entry",
name = function()
return OnOff(color.highlight("A").."CPI :", core.acpi);
end,
func = function()
core.setACPI();
end,
alias = {"a", "A"}
},
-- safe mode
{
entry_type = "entry",
name = function()
return OnOff("Safe "..color.highlight("M").."ode :", core.sm);
end,
func = function()
core.setSafeMode();
end,
alias = {"m", "M"}
},
-- single user
{
entry_type = "entry",
name = function()
return OnOff(color.highlight("S").."ingle user:", core.su);
end,
func = function()
core.setSingleUser();
end,
alias = {"s", "S"}
},
-- verbose boot
{
entry_type = "entry",
name = function()
return OnOff(color.highlight("V").."erbose :", core.verbose);
end,
func = function()
core.setVerbose();
end,
alias = {"v", "V"}
},
};
menu.welcome = {
-- boot multi user
{
entry_type = "entry",
name = function()
return color.highlight("B").."oot Multi user "..color.highlight("[Enter]");
end,
func = function()
core.setSingleUser(false);
core.boot();
end,
alias = {"b", "B", "\013"}
},
-- boot single user
{
entry_type = "entry",
name = function()
return "Boot "..color.highlight("S").."ingle user";
end,
func = function()
core.setSingleUser(true);
core.boot();
end,
alias = {"s", "S"}
},
-- escape to interpreter
{
entry_type = "return",
name = function()
return color.highlight("Esc").."ape to lua interpreter";
end,
alias = {"\027"}
},
-- reboot
{
entry_type = "entry",
name = function()
return color.highlight("R").."eboot";
end,
func = function()
loader.perform("reboot");
end,
alias = {"r", "R"}
},
{
entry_type = "separator",
name = function()
return "";
end
},
{
entry_type = "separator",
name = function()
return "Options:";
end
},
-- kernel options
{
entry_type = "submenu",
name = function()
local kernels = core.kernelList();
if #kernels == 0 then
return "Kernels (not available)";
end
return color.highlight("K").."ernels";
end,
submenu = function()
-- dynamically build the kernel menu:
local kernels = core.kernelList();
for k, v in ipairs(kernels) do
menu.kernel_options[#menu.kernel_options + 1] = {
entry_type = "entry",
name = function()
return v;
end,
func = function()
config.reload(v);
end,
alias = {} -- automatically enumerated
}
end
return menu.kernel_options;
end,
alias = {"k", "K"}
},
-- boot options
{
entry_type = "submenu",
name = function()
return "Boot "..color.highlight("O").."ptions";
end,
submenu = function()
return menu.boot_options;
end,
alias = {"o", "O"}
}
};
function menu.run(m)
if (menu.skip()) then
core.autoboot();
return false;
end
if (m == nil) then
m = menu.welcome;
end
-- redraw screen
screen.clear();
screen.defcursor();
local alias_table = drawer.drawscreen(m);
-- menu.autoboot();
cont = true;
while cont do
local key = string.char(io.getchar());
-- check to see if key is an alias
local sel_entry = nil;
for k, v in pairs(alias_table) do
if (key == k) then
sel_entry = v;
end
end
-- if we have an alias do the assigned action:
if(sel_entry ~= nil) then
if (sel_entry.entry_type == "entry") then
-- run function
sel_entry.func();
elseif (sel_entry.entry_type == "submenu") then
-- recurse
cont = menu.run(sel_entry.submenu());
elseif (sel_entry.entry_type == "return") then
-- break recurse
cont = false;
end
-- if we got an alias key the screen is out of date:
screen.clear();
screen.defcursor();
alias_table = drawer.drawscreen(m);
end
end
if (m == menu.welcome) then
screen.defcursor();
print("Exiting menu!");
return false;
end
return true;
end
function menu.skip()
if core.bootserial() then
return true;
end
local c = string.lower(loader.getenv("console") or "");
if (c:match("^efi[ ;]") or c:match("[ ;]efi[ ;]")) ~= nil then
return true;
end
c = string.lower(loader.getenv("beastie_disable") or "");
print("beastie_disable", c);
return c == "yes";
end
function menu.autoboot()
if menu.already_autoboot == true then
return;
end
menu.already_autoboot = true;
local ab = loader.getenv("autoboot_delay");
if ab == "NO" or ab == "no" then
core.boot();
end
ab = tonumber(ab) or 10;
local x = loader.getenv("loader_menu_timeout_x") or 5;
local y = loader.getenv("loader_menu_timeout_y") or 22;
local endtime = loader.time() + ab;
local time;
repeat
time = endtime - loader.time();
screen.setcursor(x, y);
print("Autoboot in "..time.." seconds, hit [Enter] to boot"
.." or any other key to stop ");
screen.defcursor();
if io.ischar() then
local ch = io.getchar();
if ch == 13 then
break;
else
-- prevent autoboot when escaping to interpreter
loader.setenv("autoboot_delay", "NO");
-- erase autoboot msg
screen.setcursor(0, y);
print(" "
.." ");
screen.defcursor();
return;
end
end
loader.delay(50000);
until time <= 0
core.boot();
end
function OnOff(str, b)
if (b) then
return str .. color.escapef(color.GREEN).."On"..color.escapef(color.WHITE);
else
return str .. color.escapef(color.RED).."off"..color.escapef(color.WHITE);
end
end
return menu

85
stand/lua/password.lua Normal file
View File

@ -0,0 +1,85 @@
--
-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-- SUCH DAMAGE.
--
-- $FreeBSD$
--
local password = {};
local core = require("core");
local screen = require("screen");
function password.read()
local str = "";
local n = 0;
repeat
ch = io.getchar();
if ch == 13 then
break;
end
if ch == 8 then
if n > 0 then
n = n - 1;
-- loader.printc("\008 \008");
str = string.sub(str, 1, n);
end
else
-- loader.printc("*");
str = str .. string.char(ch);
n = n + 1;
end
until n == 16
return str;
end
function password.check()
screen.defcursor();
local function compare(prompt, pwd)
if (pwd == nil) then
return;
end
while true do
loader.printc(prompt);
if (pwd == password.read()) then
break;
end
print("\n\nloader: incorrect password!\n");
loader.delay(3*1000*1000);
end
end
local boot_pwd = loader.getenv("bootlock_password");
compare("Boot password: ", boot_pwd);
local pwd = loader.getenv("password");
if (pwd ~=nil) then
core.autoboot();
end
compare("Password: ", pwd);
end
return password

73
stand/lua/screen.lua Normal file
View File

@ -0,0 +1,73 @@
--
-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-- SUCH DAMAGE.
--
-- $FreeBSD$
--
local screen = {};
local color = require("color");
local core = require("core");
function screen.clear()
if core.bootserial() then
return;
end
loader.printc("\027[H\027[J");
end
function screen.setcursor(x, y)
if core.bootserial() then
return;
end
loader.printc("\027["..y..";"..x.."H");
end
function screen.setforeground(c)
if color.disabled then
return c;
end
loader.printc("\027[3"..c.."m");
end
function screen.setbackground(c)
if color.disabled then
return c;
end
loader.printc("\027[4"..c.."m");
end
function screen.defcolor()
loader.printc(color.default());
end
function screen.defcursor()
if core.bootserial() then
return;
end
loader.printc("\027[25;0H");
end
return screen