// SPDX-License-Identifier: GPL-2.0
/*
 * Verified Boot for Embedded (VBE) OS request (device tree fixup) functions
 *
 * Copyright 2022 Google LLC
 * Written by Simon Glass <sjg@chromium.org>
 */

#define LOG_CATEGORY LOGC_BOOT

#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 (!CONFIG_IS_ENABLED(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(dest, node);
		if (ret)
			return log_msg_ret("cp", ret);

		*result.err_str = '\0';
		ret = vbe_process_request(dest, &result);
		if (ret) {
			result.errnum = ret;
			log_warning("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_FULL(EVT_FT_FIXUP, bootmeth_vbe_ft_fixup);
