mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
vbe: Add fixups for a basic set of OS requests
As a starting point, add support for providing random data, if requested by the OS. Also add ASLR, as a placeholder for now. Signed-off-by: Simon Glass <sjg@chromium.org> (fixed up to use uclass_first_device_err() instead)
This commit is contained in:
parent
a753190a0c
commit
8aaacd6136
3 changed files with 235 additions and 1 deletions
|
@ -47,5 +47,5 @@ ifdef CONFIG_SPL_BUILD
|
|||
obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE) += vbe.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE) += vbe.o vbe_fixup.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE) += vbe_simple.o
|
||||
|
|
233
boot/vbe_fixup.c
Normal file
233
boot/vbe_fixup.c
Normal file
|
@ -0,0 +1,233 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Verified Boot for Embedded (VBE) device tree fixup functions
|
||||
*
|
||||
* Copyright 2022 Google LLC
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#define LOG_CATEGORY LOGC_BOOT
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <event.h>
|
||||
#include <image.h>
|
||||
#include <malloc.h>
|
||||
#include <rng.h>
|
||||
#include <dm/ofnode.h>
|
||||
|
||||
#define VBE_PREFIX "vbe,"
|
||||
#define VBE_PREFIX_LEN (sizeof(VBE_PREFIX) - 1)
|
||||
#define VBE_ERR_STR_LEN 128
|
||||
#define VBE_MAX_RAND_SIZE 256
|
||||
|
||||
struct vbe_result {
|
||||
int errnum;
|
||||
char err_str[VBE_ERR_STR_LEN];
|
||||
};
|
||||
|
||||
typedef int (*vbe_req_func)(ofnode node, struct vbe_result *result);
|
||||
|
||||
static int handle_random_req(ofnode node, int default_size,
|
||||
struct vbe_result *result)
|
||||
{
|
||||
char buf[VBE_MAX_RAND_SIZE];
|
||||
struct udevice *dev;
|
||||
u32 size;
|
||||
int ret;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_DM_RNG))
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (ofnode_read_u32(node, "vbe,size", &size)) {
|
||||
if (!default_size) {
|
||||
snprintf(result->err_str, VBE_ERR_STR_LEN,
|
||||
"Missing vbe,size property");
|
||||
return log_msg_ret("byt", -EINVAL);
|
||||
}
|
||||
size = default_size;
|
||||
}
|
||||
if (size > VBE_MAX_RAND_SIZE) {
|
||||
snprintf(result->err_str, VBE_ERR_STR_LEN,
|
||||
"vbe,size %#x exceeds max size %#x", size,
|
||||
VBE_MAX_RAND_SIZE);
|
||||
return log_msg_ret("siz", -E2BIG);
|
||||
}
|
||||
ret = uclass_first_device_err(UCLASS_RNG, &dev);
|
||||
if (ret) {
|
||||
snprintf(result->err_str, VBE_ERR_STR_LEN,
|
||||
"Cannot find random-number device (err=%d)", ret);
|
||||
return log_msg_ret("wr", ret);
|
||||
}
|
||||
ret = dm_rng_read(dev, buf, size);
|
||||
if (ret) {
|
||||
snprintf(result->err_str, VBE_ERR_STR_LEN,
|
||||
"Failed to read random-number device (err=%d)", ret);
|
||||
return log_msg_ret("rd", ret);
|
||||
}
|
||||
ret = ofnode_write_prop(node, "data", buf, size, true);
|
||||
if (ret)
|
||||
return log_msg_ret("wr", -EINVAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vbe_req_random_seed(ofnode node, struct vbe_result *result)
|
||||
{
|
||||
return handle_random_req(node, 0, result);
|
||||
}
|
||||
|
||||
static int vbe_req_aslr_move(ofnode node, struct vbe_result *result)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int vbe_req_aslr_rand(ofnode node, struct vbe_result *result)
|
||||
{
|
||||
return handle_random_req(node, 4, result);
|
||||
}
|
||||
|
||||
static int vbe_req_efi_runtime_rand(ofnode node, struct vbe_result *result)
|
||||
{
|
||||
return handle_random_req(node, 4, result);
|
||||
}
|
||||
|
||||
static struct vbe_req {
|
||||
const char *compat;
|
||||
vbe_req_func func;
|
||||
} vbe_reqs[] = {
|
||||
/* address space layout randomization - move the OS in memory */
|
||||
{ "aslr-move", vbe_req_aslr_move },
|
||||
|
||||
/* provide random data for address space layout randomization */
|
||||
{ "aslr-rand", vbe_req_aslr_rand },
|
||||
|
||||
/* provide random data for EFI-runtime-services address */
|
||||
{ "efi-runtime-rand", vbe_req_efi_runtime_rand },
|
||||
|
||||
/* generate random data bytes to see the OS's rand generator */
|
||||
{ "random-rand", vbe_req_random_seed },
|
||||
|
||||
};
|
||||
|
||||
static int vbe_process_request(ofnode node, struct vbe_result *result)
|
||||
{
|
||||
const char *compat, *req_name;
|
||||
int i;
|
||||
|
||||
compat = ofnode_read_string(node, "compatible");
|
||||
if (!compat)
|
||||
return 0;
|
||||
|
||||
if (strlen(compat) <= VBE_PREFIX_LEN ||
|
||||
strncmp(compat, VBE_PREFIX, VBE_PREFIX_LEN))
|
||||
return -EINVAL;
|
||||
|
||||
req_name = compat + VBE_PREFIX_LEN; /* drop "vbe," prefix */
|
||||
for (i = 0; i < ARRAY_SIZE(vbe_reqs); i++) {
|
||||
if (!strcmp(vbe_reqs[i].compat, req_name)) {
|
||||
int ret;
|
||||
|
||||
ret = vbe_reqs[i].func(node, result);
|
||||
if (ret)
|
||||
return log_msg_ret("req", ret);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
snprintf(result->err_str, VBE_ERR_STR_LEN, "Unknown request: %s",
|
||||
req_name);
|
||||
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
/**
|
||||
* bootmeth_vbe_ft_fixup() - Process VBE OS requests and do device tree fixups
|
||||
*
|
||||
* If there are no images provided, this does nothing and returns 0.
|
||||
*
|
||||
* @ctx: Context for event
|
||||
* @event: Event to process
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
static int bootmeth_vbe_ft_fixup(void *ctx, struct event *event)
|
||||
{
|
||||
const struct event_ft_fixup *fixup = &event->data.ft_fixup;
|
||||
const struct bootm_headers *images = fixup->images;
|
||||
ofnode parent, dest_parent, root, node;
|
||||
oftree fit;
|
||||
|
||||
if (!images || !images->fit_hdr_os)
|
||||
return 0;
|
||||
|
||||
/* Get the image node with requests in it */
|
||||
log_debug("fit=%p, noffset=%d\n", images->fit_hdr_os,
|
||||
images->fit_noffset_os);
|
||||
fit = oftree_from_fdt(images->fit_hdr_os);
|
||||
root = oftree_root(fit);
|
||||
if (of_live_active()) {
|
||||
log_warning("Cannot fix up live tree\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ofnode_valid(root))
|
||||
return log_msg_ret("rt", -EINVAL);
|
||||
parent = noffset_to_ofnode(root, images->fit_noffset_os);
|
||||
if (!ofnode_valid(parent))
|
||||
return log_msg_ret("img", -EINVAL);
|
||||
dest_parent = oftree_path(fixup->tree, "/chosen");
|
||||
if (!ofnode_valid(dest_parent))
|
||||
return log_msg_ret("dst", -EINVAL);
|
||||
|
||||
ofnode_for_each_subnode(node, parent) {
|
||||
const char *name = ofnode_get_name(node);
|
||||
struct vbe_result result;
|
||||
ofnode dest;
|
||||
int ret;
|
||||
|
||||
log_debug("copy subnode: %s\n", name);
|
||||
ret = ofnode_add_subnode(dest_parent, name, &dest);
|
||||
if (ret && ret != -EEXIST)
|
||||
return log_msg_ret("add", ret);
|
||||
ret = ofnode_copy_props(node, dest);
|
||||
if (ret)
|
||||
return log_msg_ret("cp", ret);
|
||||
|
||||
*result.err_str = '\0';
|
||||
ret = vbe_process_request(dest, &result);
|
||||
if (ret) {
|
||||
result.errnum = ret;
|
||||
log_err("Failed to process VBE request %s (err=%d)\n",
|
||||
ofnode_get_name(dest), ret);
|
||||
if (*result.err_str) {
|
||||
char *msg = strdup(result.err_str);
|
||||
|
||||
if (!msg)
|
||||
return log_msg_ret("msg", -ENOMEM);
|
||||
ret = ofnode_write_string(dest, "vbe,error",
|
||||
msg);
|
||||
if (ret) {
|
||||
free(msg);
|
||||
return log_msg_ret("str", -ENOMEM);
|
||||
}
|
||||
}
|
||||
if (result.errnum) {
|
||||
ret = ofnode_write_u32(dest, "vbe,errnum",
|
||||
result.errnum);
|
||||
if (ret)
|
||||
return log_msg_ret("num", -ENOMEM);
|
||||
if (result.errnum != -ENOTSUPP)
|
||||
return log_msg_ret("pro",
|
||||
result.errnum);
|
||||
if (result.errnum == -ENOTSUPP &&
|
||||
ofnode_read_bool(dest, "vbe,required")) {
|
||||
log_err("Cannot handle required request: %s\n",
|
||||
ofnode_get_name(dest));
|
||||
return log_msg_ret("req",
|
||||
result.errnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EVENT_SPY(EVT_FT_FIXUP, bootmeth_vbe_ft_fixup);
|
|
@ -16,6 +16,7 @@ def test_event_dump(u_boot_console):
|
|||
out = util.run_and_log(cons, ['scripts/event_dump.py', sandbox])
|
||||
expect = '''.*Event type Id Source location
|
||||
-------------------- ------------------------------ ------------------------------
|
||||
EVT_FT_FIXUP bootmeth_vbe_ft_fixup .*boot/vbe_fixup.c:.*
|
||||
EVT_FT_FIXUP bootmeth_vbe_simple_ft_fixup .*boot/vbe_simple.c:.*
|
||||
EVT_MISC_INIT_F sandbox_misc_init_f .*arch/sandbox/cpu/start.c:'''
|
||||
assert re.match(expect, out, re.MULTILINE) is not None
|
||||
|
|
Loading…
Reference in a new issue