diff options
author | Simon Glass <sjg@chromium.org> | 2022-07-30 15:52:37 -0600 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2022-08-12 08:17:11 -0400 |
commit | 5fe76d460d857b00d582d7cd6cea9ac740ea912b (patch) | |
tree | 32ecaafa1d653e275683cfacac41dd2bb57efca1 | |
parent | 11361c596585bff7530e993e2d6c88c2766c0913 (diff) | |
download | u-boot-5fe76d460d857b00d582d7cd6cea9ac740ea912b.zip u-boot-5fe76d460d857b00d582d7cd6cea9ac740ea912b.tar.gz u-boot-5fe76d460d857b00d582d7cd6cea9ac740ea912b.tar.bz2 |
vbe: Add a new vbe command
Add a command to look at VBE methods and their status. Provide a test for
all of this as well.
Signed-off-by: Simon Glass <sjg@chromium.org>
-rw-r--r-- | cmd/Kconfig | 10 | ||||
-rw-r--r-- | cmd/Makefile | 1 | ||||
-rw-r--r-- | cmd/vbe.c | 87 | ||||
-rw-r--r-- | test/boot/vbe_simple.c | 115 |
4 files changed, 213 insertions, 0 deletions
diff --git a/cmd/Kconfig b/cmd/Kconfig index 7d19706..211ebe9 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -330,6 +330,16 @@ config BOOTM_RTEMS help Support booting RTEMS images via the bootm command. +config CMD_VBE + bool "vbe - Verified Boot for Embedded" + depends on BOOTMETH_VBE + default y + help + Provides various subcommands related to VBE, such as listing the + available methods, looking at the state and changing which method + is used to boot. Updating the parameters is not currently + supported. + config BOOTM_VXWORKS bool "Support booting VxWorks OS images" depends on CMD_BOOTM diff --git a/cmd/Makefile b/cmd/Makefile index 5e43a1e..6e87522 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -179,6 +179,7 @@ obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o obj-$(CONFIG_CMD_USB_SDP) += usb_gadget_sdp.o obj-$(CONFIG_CMD_THOR_DOWNLOAD) += thordown.o +obj-$(CONFIG_CMD_VBE) += vbe.o obj-$(CONFIG_CMD_XIMG) += ximg.o obj-$(CONFIG_CMD_YAFFS2) += yaffs2.o obj-$(CONFIG_CMD_SPL) += spl.o diff --git a/cmd/vbe.c b/cmd/vbe.c new file mode 100644 index 0000000..a5737ed --- /dev/null +++ b/cmd/vbe.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Verified Boot for Embedded (VBE) command + * + * Copyright 2022 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <bootmeth.h> +#include <bootstd.h> +#include <command.h> +#include <vbe.h> + +static int do_vbe_list(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + vbe_list(); + + return 0; +} + +static int do_vbe_select(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *std; + struct udevice *dev; + int ret; + + ret = bootstd_get_priv(&std); + if (ret) + return CMD_RET_FAILURE; + if (argc < 2) { + std->vbe_bootmeth = NULL; + return 0; + } + if (vbe_find_by_any(argv[1], &dev)) + return CMD_RET_FAILURE; + + std->vbe_bootmeth = dev; + + return 0; +} + +static int do_vbe_info(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *std; + char buf[256]; + int ret, len; + + ret = bootstd_get_priv(&std); + if (ret) + return CMD_RET_FAILURE; + if (!std->vbe_bootmeth) { + printf("No VBE bootmeth selected\n"); + return CMD_RET_FAILURE; + } + ret = bootmeth_get_state_desc(std->vbe_bootmeth, buf, sizeof(buf)); + if (ret) { + printf("Failed (err=%d)\n", ret); + return CMD_RET_FAILURE; + } + len = strnlen(buf, sizeof(buf)); + if (len >= sizeof(buf)) { + printf("Buffer overflow\n"); + return CMD_RET_FAILURE; + } + + puts(buf); + if (buf[len] != '\n') + putc('\n'); + + return 0; +} + +#ifdef CONFIG_SYS_LONGHELP +static char vbe_help_text[] = + "list - list VBE bootmeths\n" + "vbe select - select a VBE bootmeth by sequence or name\n" + "vbe info - show information about a VBE bootmeth"; +#endif + +U_BOOT_CMD_WITH_SUBCMDS(vbe, "Verified Boot for Embedded", vbe_help_text, + U_BOOT_SUBCMD_MKENT(list, 1, 1, do_vbe_list), + U_BOOT_SUBCMD_MKENT(select, 2, 1, do_vbe_select), + U_BOOT_SUBCMD_MKENT(info, 2, 1, do_vbe_info)); diff --git a/test/boot/vbe_simple.c b/test/boot/vbe_simple.c new file mode 100644 index 0000000..2f6979c --- /dev/null +++ b/test/boot/vbe_simple.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for vbe-simple bootmeth. All start with 'vbe_simple' + * + * Copyright 2023 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <bootmeth.h> +#include <dm.h> +#include <image.h> +#include <memalign.h> +#include <mmc.h> +#include <of_live.h> +#include <vbe.h> +#include <version_string.h> +#include <linux/log2.h> +#include <test/suites.h> +#include <test/ut.h> +#include <u-boot/crc.h> +#include "bootstd_common.h" + +#define NVDATA_START_BLK ((0x400 + 0x400) / MMC_MAX_BLOCK_LEN) +#define VERSION_START_BLK ((0x400 + 0x800) / MMC_MAX_BLOCK_LEN) +#define TEST_VERSION "U-Boot v2022.04-local2" +#define TEST_VERNUM 0x00010002 + +/* Basic test of reading nvdata and updating a fwupd node in the device tree */ +static int vbe_simple_test_base(struct unit_test_state *uts) +{ + ALLOC_CACHE_ALIGN_BUFFER(u8, buf, MMC_MAX_BLOCK_LEN); + const char *version, *bl_version; + struct event_ft_fixup fixup; + struct udevice *dev, *mmc; + struct device_node *np; + struct blk_desc *desc; + char fdt_buf[0x400]; + char info[100]; + int node_ofs; + ofnode node; + u32 vernum; + + /* Set up the version string */ + ut_assertok(uclass_get_device(UCLASS_MMC, 1, &mmc)); + desc = blk_get_by_device(mmc); + ut_assertnonnull(desc); + + memset(buf, '\0', MMC_MAX_BLOCK_LEN); + strcpy(buf, TEST_VERSION); + if (blk_dwrite(desc, VERSION_START_BLK, 1, buf) != 1) + return log_msg_ret("write", -EIO); + + /* Set up the nvdata */ + memset(buf, '\0', MMC_MAX_BLOCK_LEN); + buf[1] = ilog2(0x40) << 4 | 1; + *(u32 *)(buf + 4) = TEST_VERNUM; + buf[0] = crc8(0, buf + 1, 0x3f); + if (blk_dwrite(desc, NVDATA_START_BLK, 1, buf) != 1) + return log_msg_ret("write", -EIO); + + /* Read the version back */ + ut_assertok(vbe_find_by_any("firmware0", &dev)); + ut_assertok(bootmeth_get_state_desc(dev, info, sizeof(info))); + ut_asserteq_str("Version: " TEST_VERSION "\nVernum: 1/2", info); + + ut_assertok(fdt_create_empty_tree(fdt_buf, sizeof(fdt_buf))); + node_ofs = fdt_add_subnode(fdt_buf, 0, "chosen"); + ut_assert(node_ofs > 0); + + node_ofs = fdt_add_subnode(fdt_buf, node_ofs, "fwupd"); + ut_assert(node_ofs > 0); + + node_ofs = fdt_add_subnode(fdt_buf, node_ofs, "firmware0"); + ut_assert(node_ofs > 0); + + /* + * This can only work on the live tree, since the ofnode interface for + * flat tree assumes that ofnode points to the control FDT + */ + ut_assertok(unflatten_device_tree(fdt_buf, &np)); + + /* + * It would be better to call image_setup_libfdt() here, but that + * function does not allow passing an ofnode. We can pass fdt_buf but + * when it comes to send the evenr, it creates an ofnode that uses the + * control FDT, since it has no way of accessing the live tree created + * here. + * + * Two fix this we need: + * - image_setup_libfdt() is updated to use ofnode + * - ofnode updated to support access to an FDT other than the control + * FDT. This is partially implemented with live tree, but not with + * flat tree + */ + fixup.tree.np = np; + ut_assertok(event_notify(EVT_FT_FIXUP, &fixup, sizeof(fixup))); + + node = ofnode_path_root(fixup.tree, "/chosen/fwupd/firmware0"); + + version = ofnode_read_string(node, "cur-version"); + ut_assertnonnull(version); + ut_asserteq_str(TEST_VERSION, version); + + ut_assertok(ofnode_read_u32(node, "cur-vernum", &vernum)); + ut_asserteq(TEST_VERNUM, vernum); + + bl_version = ofnode_read_string(node, "bootloader-version"); + ut_assertnonnull(bl_version); + ut_asserteq_str(version_string, bl_version); + + return 0; +} +BOOTSTD_TEST(vbe_simple_test_base, UT_TESTF_DM | UT_TESTF_SCAN_FDT | + UT_TESTF_LIVE_TREE); |