diff options
Diffstat (limited to 'cmd/upl.c')
-rw-r--r-- | cmd/upl.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/cmd/upl.c b/cmd/upl.c new file mode 100644 index 00000000000..c9745886507 --- /dev/null +++ b/cmd/upl.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Commands for UPL handoff generation + * + * Copyright 2024 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#define LOG_CATEGORY UCLASS_BOOTSTD + +#include <abuf.h> +#include <alist.h> +#include <command.h> +#include <display_options.h> +#include <mapmem.h> +#include <string.h> +#include <upl.h> +#include <dm/ofnode.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; + +static int do_upl_info(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + const struct upl *upl = gd_upl(); + + printf("UPL state: %sactive\n", upl ? "" : "in"); + if (!upl) + return 0; + if (argc > 1 && !strcmp("-v", argv[1])) { + int i; + + printf("fit %lx\n", upl->fit); + printf("conf_offset %x\n", upl->conf_offset); + for (i = 0; i < upl->image.count; i++) { + const struct upl_image *img = + alist_get(&upl->image, i, struct upl_image); + + printf("image %d: load %lx size %lx offset %x: %s\n", i, + img->load, img->size, img->offset, + img->description); + } + } + + return 0; +} + +static int do_upl_write(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct upl s_upl, *upl = &s_upl; + struct unit_test_state uts; + struct abuf buf; + oftree tree; + ulong addr; + int ret; + + upl_get_test_data(&uts, upl); + + log_debug("Writing UPL\n"); + ret = upl_create_handoff_tree(upl, &tree); + if (ret) { + log_err("Failed to write (err=%dE)\n", ret); + return CMD_RET_FAILURE; + } + + log_debug("Flattening\n"); + ret = oftree_to_fdt(tree, &buf); + if (ret) { + log_err("Failed to write (err=%dE)\n", ret); + return CMD_RET_FAILURE; + } + addr = map_to_sysmem(abuf_data(&buf)); + printf("UPL handoff written to %lx size %lx\n", addr, abuf_size(&buf)); + if (env_set_hex("upladdr", addr) || + env_set_hex("uplsize", abuf_size(&buf))) { + printf("Cannot set env var\n"); + return CMD_RET_FAILURE; + } + + log_debug("done\n"); + + return 0; +} + +static int do_upl_read(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct upl s_upl, *upl = &s_upl; + oftree tree; + ulong addr; + int ret; + + if (argc < 1) + return CMD_RET_USAGE; + addr = hextoul(argv[1], NULL); + + printf("Reading UPL at %lx\n", addr); + tree = oftree_from_fdt(map_sysmem(addr, 0)); + ret = upl_read_handoff(upl, tree); + if (ret) { + log_err("Failed to read (err=%dE)\n", ret); + return CMD_RET_FAILURE; + } + + return 0; +} + +U_BOOT_LONGHELP(upl, + "info [-v] - Check UPL status\n" + "upl read <addr> - Read handoff information\n" + "upl write - Write handoff information"); + +U_BOOT_CMD_WITH_SUBCMDS(upl, "Universal Payload support", upl_help_text, + U_BOOT_SUBCMD_MKENT(info, 2, 1, do_upl_info), + U_BOOT_SUBCMD_MKENT(read, 2, 1, do_upl_read), + U_BOOT_SUBCMD_MKENT(write, 1, 1, do_upl_write)); |