HardenedBSD/stand/libsa/features.c
Kyle Evans 1631382cf2 loader: provide a features table for binary compatibility advertisement
liblua now provides a loader.has_feature() function to probe the loader
binary for features advertised.  name => desc mappings are provided in
loader.features to get a list of all of the features loader *can*
support.  core.hasFeature is provided as a shim to loader.has_feature
so that individual consumers don't need to think about the logic of the
loader module not providing has_feature; we know that means the feature
isn't enabled.

The first consumer of this will be EARLY_ACPI to advertise that the
loader binary probes for ACPI presence before the interpreter has
started, so that we know whether we can trust the presence of acpi.rsdp
as relatively authoritative.  In general, it's intended to be used to
avoid breaking new scripts on older loaders within reason.

This will be used in lua as `core.hasFeature("EARLY_ACPI")`, while the
C bits of loader will `feature_enable(FEATURE_EARLY_ACPI)`.

Reviewed by:	imp
Differential Revision:	https://reviews.freebsd.org/D42695
2023-12-08 15:43:19 -06:00

57 lines
1.0 KiB
C

/*-
* 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);
}
}