Page MenuHomeFreeBSD

D55936.diff
No OneTemporary

D55936.diff

diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk
--- a/share/mk/src.opts.mk
+++ b/share/mk/src.opts.mk
@@ -128,13 +128,14 @@
LLVM_COV \
LLVM_CXXFILT \
LOADER_BIOS_TEXTONLY \
+ LOADER_EFIBOOTMGRMENU \
LOADER_GELI \
+ LOADER_IA32 \
LOADER_KBOOT \
LOADER_LUA \
LOADER_OFW \
LOADER_PXEBOOT \
LOADER_UBOOT \
- LOADER_IA32 \
LOCALES \
LOCATE \
LPR \
diff --git a/stand/common/interp_lua.c b/stand/common/interp_lua.c
--- a/stand/common/interp_lua.c
+++ b/stand/common/interp_lua.c
@@ -40,6 +40,7 @@
#include <lerrno.h>
#include <lfs.h>
#include <lutils.h>
+#include <lefibootmgr.h>
struct interp_lua_softc {
lua_State *luap;
@@ -92,6 +93,9 @@
{"io", luaopen_io},
{"lfs", luaopen_lfs},
{"loader", luaopen_loader},
+#ifdef __amd64__
+ {"efibootmgr", luaopen_efibootmgr},
+#endif
{"pager", luaopen_pager},
{NULL, NULL}
};
diff --git a/stand/defs.mk b/stand/defs.mk
--- a/stand/defs.mk
+++ b/stand/defs.mk
@@ -69,7 +69,7 @@
BINDIR?= /boot
# LUAPATH is where we search for and install lua scripts.
-LUAPATH?= /boot/lua
+LUAPATH?= /EFI/FreeBSD/lua
FLUASRC?= ${SRCTOP}/libexec/flua
FLUALIB?= ${SRCTOP}/libexec/flua
diff --git a/stand/efi/loader/Makefile b/stand/efi/loader/Makefile
--- a/stand/efi/loader/Makefile
+++ b/stand/efi/loader/Makefile
@@ -99,6 +99,14 @@
# Always add MI sources
.include "${BOOTSRC}/loader.mk"
+MK_LOADER_EFIBOOTMGRMENU?= no
+.if ${MK_LOADER_LUA} != "no" && ${MK_LOADER_EFIBOOTMGRMENU} != "no"
+SRCS+= efibootmgrmenu.c
+CFLAGS+= -DEFI_LOADER_EFIBOOTMGRMENU -DEFI_LOADER_EFIBOOTMGRMENU_DEBUG
+CFLAGS+= -I${LUASRC} -I${LIBLUASRC}
+LDADD+= lua
+.endif
+
CLEANFILES+= 8x16.c
8x16.c: ${SRCTOP}/contrib/terminus/ter-u16b.bdf
diff --git a/stand/efi/loader/efibootmgrmenu.h b/stand/efi/loader/efibootmgrmenu.h
new file mode 100644
--- /dev/null
+++ b/stand/efi/loader/efibootmgrmenu.h
@@ -0,0 +1,6 @@
+#ifndef EFI_LOADER_EFIBOOTMGRMENU_H
+#define EFI_LOADER_EFIBOOTMGRMENU_H
+
+void efibootmgrmenu(void);
+
+#endif
diff --git a/stand/efi/loader/efibootmgrmenu.c b/stand/efi/loader/efibootmgrmenu.c
new file mode 100644
--- /dev/null
+++ b/stand/efi/loader/efibootmgrmenu.c
@@ -0,0 +1,15 @@
+#include <bootstrap.h>
+
+/*
+ * Build a menu to pick the partition to boot from using the UEFI Boot Manager
+ * policy [1].
+ *
+ * [1] https://uefi.org/specs/UEFI/2.10/03_Boot_Manager.html
+ */
+void
+efibootmgrmenu(void)
+{
+ setenv("loader_lua", "EFI/FreeBSD/lua/efibootmgrmenu.lua", 1);
+ interact();
+ /* NOTREACHED */
+}
diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c
--- a/stand/efi/loader/main.c
+++ b/stand/efi/loader/main.c
@@ -79,6 +79,9 @@
#include <acpi_detect.h>
#include "loader_efi.h"
+#ifdef EFI_LOADER_EFIBOOTMGRMENU
+#include "efibootmgrmenu.h"
+#endif
struct arch_switch archsw = { /* MI/MD interface boundary */
.arch_autoload = efi_autoload,
@@ -1474,6 +1477,10 @@
ve_efi_init();
#endif
+#ifdef EFI_LOADER_EFIBOOTMGRMENU
+ efibootmgrmenu();
+#endif
+
/*
* Try and find a good currdev based on the image that was booted.
* It might be desirable here to have a short pause to allow falling
diff --git a/stand/liblua/Makefile b/stand/liblua/Makefile
--- a/stand/liblua/Makefile
+++ b/stand/liblua/Makefile
@@ -24,6 +24,12 @@
SRCS+= lerrno.c lpager.c lstd.c lutils.c
SRCS+= gfx_utils.c
+# EFI Boot Manager Support
+.if ${MACHINE_ARCH} == "amd64" && ${MK_EFI} != "no"
+SRCS+= lefibootmgr.c
+CFLAGS.lefibootmgr.c+= -I${EDK2INC} -I${EFIINC}
+.endif
+
.PATH: ${FLUASRC}/lfs
SRCS+= lfs.c
.PATH: ${FLUALIB}/libhash
diff --git a/stand/liblua/lefibootmgr.h b/stand/liblua/lefibootmgr.h
new file mode 100644
--- /dev/null
+++ b/stand/liblua/lefibootmgr.h
@@ -0,0 +1,3 @@
+#include <lua.h>
+
+int luaopen_efibootmgr(lua_State *);
diff --git a/stand/liblua/lefibootmgr.c b/stand/liblua/lefibootmgr.c
new file mode 100644
--- /dev/null
+++ b/stand/liblua/lefibootmgr.c
@@ -0,0 +1,131 @@
+#include <efi.h>
+#include <efilib.h>
+
+#include "lua.h"
+#include "lauxlib.h"
+
+static const struct luaL_Reg efibootmgrlib[] = {
+ { NULL, NULL },
+};
+
+int
+luaopen_efibootmgr(lua_State *L)
+{
+ EFI_STATUS rv;
+ size_t boot_order_sz, sz;
+ UINT16 boot_current, boot_order[100];
+ char boot_info[4096], buf[80];
+ int timeout;
+
+ luaL_newlib(L, efibootmgrlib);
+
+ /*
+ * Expose Timeout as an integer.
+ */
+ sz = sizeof(timeout);
+ rv = efi_global_getenv("Timeout", &timeout, &sz);
+ if (rv == EFI_SUCCESS)
+ lua_pushinteger(L, timeout);
+ else
+ lua_pushinteger(L, 10);
+ lua_setfield(L, -2, "timeout");
+
+ /*
+ * Expose BootCurrent as an integer, e.g., 6 for Boot0006.
+ */
+ boot_current = 0;
+ sz = sizeof(boot_current);
+ rv = efi_global_getenv("BootCurrent", &boot_current, &sz);
+ if (rv == EFI_SUCCESS) {
+ char buf[80];
+
+ snprintf(buf, sizeof(buf), "Boot%04X", boot_current);
+ sz = sizeof(boot_info);
+ rv = efi_global_getenv(buf, &boot_info, &sz);
+ if (rv == EFI_SUCCESS)
+ ;
+ lua_pushinteger(L, boot_current);
+ lua_setfield(L, -2, "boot_current");
+ }
+
+ /*
+ * Expose BootOrder as follow:
+ * efibootmgr.boot_order[1..n]
+ * .bootnum The boot number as an integer, e.g., 6 for Boot0006.
+ */
+ sz = sizeof(boot_order);
+ rv = efi_global_getenv("BootOrder", &boot_order, &boot_order_sz);
+ if (rv == EFI_SUCCESS) {
+ size_t boot_order_nitems = boot_order_sz / sizeof(boot_order[0]);
+
+ lua_createtable(L, boot_order_nitems, 0);
+ for (size_t o = 0; o < boot_order_nitems; o++) {
+ char buf[256], boot_info[4096];
+ EFI_LOAD_OPTION *load_option;
+ CHAR16 *description;
+ size_t description_sz;
+ EFI_DEVICE_PATH_PROTOCOL *file_path_list;
+ CHAR16 *devpath;
+#if 0
+ UINT8 *optional_data;
+ size_t optional_data_sz;
+#endif
+
+ snprintf(buf, sizeof(buf), "Boot%04X", boot_order[o]);
+ sz = sizeof(boot_info);
+ rv = efi_global_getenv(buf, &boot_info, &sz);
+ if (rv != EFI_SUCCESS) {
+ printf("WARNING: unable to read load option %s\n", buf);
+ continue;
+ }
+ load_option = (EFI_LOAD_OPTION *)boot_info;
+
+ lua_createtable(L, 1, 0);
+
+ /* bootnum */
+ lua_pushinteger(L, boot_order[o]);
+ lua_setfield(L, -2, "bootnum");
+
+ /* attributes, is_active, is_hidden */
+ lua_pushinteger(L, load_option->Attributes);
+ lua_setfield(L, -2, "attributes");
+ lua_pushboolean(L, load_option->Attributes & LOAD_OPTION_ACTIVE);
+ lua_setfield(L, -2, "is_active");
+ lua_pushboolean(L, load_option->Attributes & LOAD_OPTION_HIDDEN);
+ lua_setfield(L, -2, "is_hidden");
+
+ /* description */
+ description = (CHAR16 *)(boot_info +
+ sizeof(load_option->Attributes) +
+ sizeof(load_option->FilePathListLength));
+ cpy16to8(description, buf, sizeof(buf));
+ lua_pushstring(L, buf);
+ lua_setfield(L, -2, "description");
+
+ /* devpath from file_path_list[0] */
+
+ /* FIXME Find a better approach to get StrSize(CHAR16 *) */
+ cpy16to8(description, buf, sizeof(buf));
+ description_sz = (strlen(buf) + 1) * sizeof(CHAR16);
+
+ file_path_list = (EFI_DEVICE_PATH *)((UINT8 *)description +
+ description_sz);
+ devpath = efi_devpath_name(&file_path_list[0]);
+ cpy16to8(devpath, buf, sizeof(buf));
+ lua_pushstring(L, buf);
+ lua_setfield(L, -2, "devpath");
+
+#if 0
+ /* optional_data */
+ optional_data = (UINT8 *)((UINT8 *)file_path_list +
+ load_option->FilePathListLength);
+ optional_data_sz = sz - (optional_data - (UINT8 *)load_option);
+ /* TODO Find a way to expose the optional data. */
+#endif
+
+ lua_rawseti(L, -2, o + 1);
+ }
+ lua_setfield(L, -2, "boot_order");
+ }
+ return (1);
+}
diff --git a/stand/lua/color.lua b/stand/lua/color.lua
--- a/stand/lua/color.lua
+++ b/stand/lua/color.lua
@@ -105,13 +105,21 @@
return color.escape(color.DEFAULT, color.DEFAULT)
end
-function color.highlight(str)
+function color.mstr(mode, str)
if color.disabled then
return str
end
-- We need to reset attributes as well as color scheme here, just in
-- case the terminal defaults don't match what we're expecting.
- return core.KEYSTR_CSI .. "1m" .. str .. core.KEYSTR_CSI .. "22m"
+ return core.KEYSTR_CSI .. mode .. "m" .. str .. core.KEYSTR_CSI .. "22m"
+end
+
+function color.highlight(str)
+ return color.mstr(color.BRIGHT, str)
+end
+
+function color.dim(str)
+ return color.mstr(color.DIM, str)
end
recalcDisabled()
diff --git a/stand/lua/efibootmgrmenu.lua b/stand/lua/efibootmgrmenu.lua
new file mode 100644
--- /dev/null
+++ b/stand/lua/efibootmgrmenu.lua
@@ -0,0 +1,138 @@
+-- XXX
+printc("package.path: " .. package.path .. "\n")
+printc("loader.lua_path: " .. loader.lua_path .. "\n")
+
+local core = require("core")
+local color = require("color")
+
+DEBUG = true
+DELAY = 5 -- seconds
+SHOW_ACTIVE = true
+SHOW_HIDDEN = true
+
+-- Load option attributes bits:
+LOAD_OPTION_ACTIVE = 0x00000001
+LOAD_OPTION_FORCE_RECONNECT = 0x00000002
+LOAD_OPTION_HIDDEN = 0x00000008
+LOAD_OPTION_CATEGORY = 0x00001f00
+LOAD_OPTION_CATEGORY_BOOT = 0x00000000
+LOAD_OPTION_CATEGORY_APP = 0x00000100
+
+function print_menu()
+ for o = 1,#efibootmgr.boot_order,1 do
+ local load_option = efibootmgr.boot_order[o]
+ local bootnum = load_option.bootnum
+ local is_current = bootnum == efibootmgr.boot_current
+ local is_active = load_option.is_active
+ local is_hidden = load_option.is_hidden
+ local description = load_option.description
+
+ local show = false
+ if SHOW_ACTIVE and is_active then
+ show = true
+ end
+ if SHOW_HIDDEN then
+ if is_hidden then
+ show = true
+ end
+ elseif is_hidden then
+ show = false
+ end
+ if not show then
+ goto continue
+ end
+
+ line = ""
+
+ if o <= 9 then
+ line = line .. "[" .. o .. "] "
+ else
+ line = line .. " "
+ end
+
+ label = ""
+
+ if is_current then
+ line = line .. "+"
+ else
+ line = line .. " "
+ end
+
+ line = line .. string.format("Boot%04x ", bootnum)
+ if is_hidden then
+ line = line .. description
+ else
+ line = line .. color.highlight(description)
+ end
+
+ if is_active then
+ line = line .. "*"
+ end
+
+ if is_hidden then
+ printc(color.dim(line))
+ else
+ printc(line)
+ end
+ printc("\n")
+
+ if DEBUG then
+ printc(" attributes: 0x" .. string.format("%x", load_option.attributes) .. "<")
+ if load_option.attributes & LOAD_OPTION_ACTIVE == LOAD_OPTION_ACTIVE then
+ printc("ACTIVE,")
+ end
+ if load_option.attributes & LOAD_OPTION_HIDDEN == LOAD_OPTION_HIDDEN then
+ printc("HIDDEN,")
+ end
+ if load_option.attributes & LOAD_OPTION_FORCE_RECONNECT == LOAD_OPTION_FORCE_RECONNECT then
+ printc("FORCE_RECONNECT,")
+ end
+ if load_option.attributes & LOAD_OPTION_CATEGORY == LOAD_OPTION_CATEGORY_BOOT then
+ printc("CATEGORY_BOOT,")
+ end
+ if load_option.attributes & LOAD_OPTION_CATEGORY == LOAD_OPTION_CATEGORY_APP then
+ printc("CATEGORY_APP,")
+ end
+ printc(">\n")
+ printc(" devpath: " .. load_option.devpath .. "\n")
+ end
+ ::continue::
+ end
+end
+
+function boot_load_option(load_option)
+ printc(string.format("Booting Boot%04x %s...\n",
+ load_option.bootnum, load_option.description))
+ -- TODO Setup bootenv from load_option
+ core.boot()
+end
+
+printc(">>> EFI Boot Manager Menu\n")
+print_menu()
+
+local load_option = efibootmgr.boot_order[1]
+
+printc(string.format("Default: Boot%04x %s\n",
+ load_option.bootnum, load_option.description))
+
+printc("Choose: ")
+local endtime = loader.time() + efibootmgr.timeout
+repeat
+ time = endtime - loader.time()
+ if io.ischar() then
+ o = io.getchar() - 48
+ if 1 <= o and o <= #efibootmgr.boot_order then
+ load_option = efibootmgr.boot_order[o]
+ else
+ printc(" ")
+ printc(color.highlight("invalid key"))
+ end
+ break
+ end
+ loader.delay(50000)
+until time <= 0
+printc("\n")
+
+boot_load_option(load_option)
+
+printc("<<< EFI Boot Manager Menu\n")

File Metadata

Mime Type
text/plain
Expires
Mon, Apr 6, 7:04 PM (9 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30993879
Default Alt Text
D55936.diff (11 KB)

Event Timeline