aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stand/liblua/lutils.c48
-rw-r--r--stand/libsa/Makefile2
-rw-r--r--stand/libsa/features.c56
-rw-r--r--stand/libsa/libsa.360
-rw-r--r--stand/libsa/stand.h15
-rw-r--r--stand/lua/core.lua9
-rw-r--r--stand/lua/core.lua.89
7 files changed, 197 insertions, 2 deletions
diff --git a/stand/liblua/lutils.c b/stand/liblua/lutils.c
index 1792d0c8c620..274d9a39da21 100644
--- a/stand/liblua/lutils.c
+++ b/stand/liblua/lutils.c
@@ -76,6 +76,25 @@ lua_has_command(lua_State *L)
}
static int
+lua_has_feature(lua_State *L)
+{
+ const char *feature;
+ char *msg;
+
+ feature = luaL_checkstring(L, 1);
+
+ if (feature_name_is_enabled(feature)) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+
+ lua_pushnil(L);
+ lua_pushstring(L, "Feature not enabled");
+ return 2;
+}
+
+
+static int
lua_perform(lua_State *L)
{
int argc;
@@ -552,6 +571,7 @@ static const struct luaL_Reg loaderlib[] = {
REG_SIMPLE(parse),
REG_SIMPLE(getenv),
REG_SIMPLE(has_command),
+ REG_SIMPLE(has_feature),
REG_SIMPLE(perform),
REG_SIMPLE(printc), /* Also registered as the global 'printc' */
REG_SIMPLE(setenv),
@@ -579,6 +599,33 @@ static const struct luaL_Reg iolib[] = {
};
#undef REG_SIMPLE
+static void
+lua_add_feature(void *cookie, const char *name, const char *desc, bool enabled)
+{
+ lua_State *L = cookie;
+
+ /*
+ * The feature table consists solely of features that are enabled, and
+ * their associated descriptions for debugging purposes.
+ */
+ lua_pushstring(L, desc);
+ lua_setfield(L, -2, name);
+}
+
+static void
+lua_add_features(lua_State *L)
+{
+
+ lua_newtable(L);
+ feature_iter(&lua_add_feature, L);
+
+ /*
+ * We should still have just the table on the stack after we're done
+ * iterating.
+ */
+ lua_setfield(L, -2, "features");
+}
+
int
luaopen_loader(lua_State *L)
{
@@ -592,6 +639,7 @@ luaopen_loader(lua_State *L)
lua_setfield(L, -2, "lua_path");
lua_pushinteger(L, bootprog_rev);
lua_setfield(L, -2, "version");
+ lua_add_features(L);
/* Set global printc to loader.printc */
lua_register(L, "printc", lua_printc);
return 1;
diff --git a/stand/libsa/Makefile b/stand/libsa/Makefile
index 57340709873b..a1b9bc32e025 100644
--- a/stand/libsa/Makefile
+++ b/stand/libsa/Makefile
@@ -13,7 +13,7 @@ LIB?= sa
# standalone components and stuff we have modified locally
SRCS+= gzguts.h zutil.h __main.c abort.c assert.c bcd.c environment.c \
- getopt.c gets.c globals.c \
+ features.c getopt.c gets.c globals.c \
hexdump.c nvstore.c pager.c panic.c printf.c strdup.c strerror.c \
random.c sbrk.c tslog.c twiddle.c zalloc.c zalloc_malloc.c
diff --git a/stand/libsa/features.c b/stand/libsa/features.c
new file mode 100644
index 000000000000..23dce2b13b60
--- /dev/null
+++ b/stand/libsa/features.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2023 Kyle Evans <kevans@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ */
+
+#include <sys/param.h>
+
+#include "stand.h"
+
+static uint32_t loader_features;
+
+#define FEATURE_ENTRY(name, desc) { FEATURE_##name, #name, desc }
+static const struct feature_entry {
+ uint32_t value;
+ const char *name;
+ const char *desc;
+} feature_map[] = {
+ FEATURE_ENTRY(EARLY_ACPI, "Loader probes ACPI in early startup"),
+};
+
+void
+feature_enable(uint32_t mask)
+{
+
+ loader_features |= mask;
+}
+
+bool
+feature_name_is_enabled(const char *name)
+{
+ const struct feature_entry *entry;
+
+ for (size_t i = 0; i < nitems(feature_map); i++) {
+ entry = &feature_map[i];
+
+ if (strcmp(entry->name, name) == 0)
+ return ((loader_features & entry->value) != 0);
+ }
+
+ return (false);
+}
+
+void
+feature_iter(feature_iter_fn *iter_fn, void *cookie)
+{
+ const struct feature_entry *entry;
+
+ for (size_t i = 0; i < nitems(feature_map); i++) {
+ entry = &feature_map[i];
+
+ (*iter_fn)(cookie, entry->name, entry->desc,
+ (loader_features & entry->value) != 0);
+ }
+}
diff --git a/stand/libsa/libsa.3 b/stand/libsa/libsa.3
index a6f30051c8df..7643423b342a 100644
--- a/stand/libsa/libsa.3
+++ b/stand/libsa/libsa.3
@@ -497,6 +497,66 @@ Attempts to open and display the file
.Fa fname .
Returns -1 on error, 0 at EOF, or 1 if the user elects to quit while reading.
.El
+.Sh FEATURE SUPPORT
+A set of functions are provided to communicate support of features from the
+loader binary to the interpreter.
+These are used to do something sensible if we are still operating with a loader
+binary that behaves differently than expected.
+.Bl -hang -width 10n
+.It Xo
+.Ft void
+.Fn feature_enable "uint32_t mask"
+.Xc
+.Pp
+Enable the referenced
+.Fa mask
+feature, which should be one of the
+.Li FEATURE_*
+macros defined in
+.In stand.h .
+.It Xo
+.Ft bool
+.Fn feature_name_is_enabled "const char *name"
+.Xc
+.Pp
+Check if the referenced
+.Fa name
+feature is enabled.
+The
+.Fa name
+is usually the same name as the
+.Li FEATURE_*
+macro, but with the FEATURE_ prefix stripped off.
+The authoritative source of feature names is the mapping table near the top in
+.Pa stand/libsa/features.c .
+.It Xo
+.Ft void
+.Fn "(feature_iter_fn)" "void *cookie" "const char *name" "const char *desc" "bool enabled"
+.Xc
+.Pp
+The
+.Fa cookie
+argument is passed as-is from the argument of the same name to
+.Fn feature_iter .
+The
+.Fa name
+and
+.Fa desc
+arguments are defined in the mapping table in
+.Pa stand/libsa/features.c .
+The
+.Fa enabled
+argument indicates the current status of the feature, though one could
+theoretically turn a feature off in later execution.
+As such, this should likely not be trusted if it is needed after the iteration
+has finished.
+.It Xo
+.Ft void
+.Fn "feature_iter" "feature_iter_fn *iter_fn" "void *cookie"
+.Xc
+.Pp
+Iterate over the current set of features.
+.El
.Sh MISC
.Bl -hang -width 10n
.It Xo
diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h
index b6ddebb82fd7..f500a8f47847 100644
--- a/stand/libsa/stand.h
+++ b/stand/libsa/stand.h
@@ -496,6 +496,21 @@ extern void *reallocf(void *, size_t);
*/
caddr_t ptov(uintptr_t);
+/* features.c */
+typedef void (feature_iter_fn)(void *, const char *, const char *, bool);
+
+extern void feature_enable(uint32_t);
+extern bool feature_name_is_enabled(const char *);
+extern void feature_iter(feature_iter_fn *, void *);
+
+/*
+ * Note that these should also be added to the mapping table in features.c,
+ * which the interpreter may query to provide details from. The name with
+ * FEATURE_ removed is assumed to be the name we'll provide in the loader
+ * features table, just to simplify reasoning about these.
+ */
+#define FEATURE_EARLY_ACPI 0x0001
+
/* hexdump.c */
void hexdump(caddr_t region, size_t len);
diff --git a/stand/lua/core.lua b/stand/lua/core.lua
index 5c3c65463e51..3a80b0822ca6 100644
--- a/stand/lua/core.lua
+++ b/stand/lua/core.lua
@@ -378,6 +378,15 @@ function core.boot(argstr)
loader.perform(composeLoaderCmd("boot", argstr))
end
+function core.hasFeature(name)
+ if not loader.has_feature then
+ -- Loader too old, no feature support
+ return nil, "No feature support in loaded loader"
+ end
+
+ return loader.has_feature(name)
+end
+
function core.isSingleUserBoot()
local single_user = loader.getenv("boot_single")
return single_user ~= nil and single_user:lower() == "yes"
diff --git a/stand/lua/core.lua.8 b/stand/lua/core.lua.8
index 5274ba4c2143..84447d7632b9 100644
--- a/stand/lua/core.lua.8
+++ b/stand/lua/core.lua.8
@@ -24,7 +24,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd November 20, 2023
+.Dd December 8, 2023
.Dt CORE.LUA 8
.Os
.Sh NAME
@@ -142,6 +142,13 @@ due to a boot environment change or a potential change in either
.Ic kernel
or
.Ic kernels .
+.It Fn core.hasFeature featureName
+Checks whether the named
+.Fa featureName
+is enabled in the current loader.
+This is specifically used for detecting capabilities of the loaded loader
+binary, so that one can reasonably implement backwards compatibility shims if
+needed.
.It Fn core.kernelList
Returns a table of kernels to display on the boot menu.
This will combine