[PATCH 00/34] x86: expo: Add support for editing coreboot CMOS RAM settings

U-Boot provides support for editing settings with an 'expo', as well as reading and writing settings to CMOS RAM.
This series integrates expo functionality with coreboot, using the sysinfo table to get a list of settings, creating an expo with them and allowing them to be edited.
A new CI test provides coverage for some coreboot-related commands. For this to work, a number of minor tweaks are made to existing tests, so that they pass on coreboot (x86) or at least are skipped when they cannot pass. Likely most of these fixes will apply to other boards too.
It includes several other fixes and improvements: - new -m flag for 'bootflow scan' so it can display a menu automatically - Fix for video-scrolling crash with Truetype - menu items can now have individual integer values - menu items are lined up according to the width of all menu labels
Simon Glass (34): test: Run tests that don't need devices test: Add a new suite for commands test: Add helper to skip to partial console line test: Make UT_LIB_ASN1 depend on sandbox test: Run bootstd tests only on sandbox test: Handle use of stack pointer in bdinfo test: bdinfo: Add missing asserts test: fdt: Add a special case for real boards test: font: Add dependencies on fonts test: event: Only run test_event_probe() on sandbox test: lmb: Move tests into the lib suite test: print: Skip test on x86 video: Add a function to clear the display sandbox: Add a dummy booti command bootstd: Add a menu option to bootflow scan video: Add a dark-grey console colour video: Avoid starting a new line to close to the bottom expo: Place menu items to the right of all labels expo: Set the initial next_id to 1 expo: Use standard numbering for save and discard expo: Allow menu items to have values expo: Add a little more cedit CMOS logging expo: Support menu-item values in cedit expo: Drop unneceesary calls to expo_str() expo: Drop scene_title_set() expo: Add forward declaration for udevice to cedit x86: coreboot: Enable unit tests x86: CI: Update coreboot x86: coreboot: Add a test for cbsysinfo command x86: coreboot: Show the option table x86: coreboot: Enable support for the configuration editor x86: coreboot: Add a command to check and update CMOS RAM x86: coreboot: Allow building an expo for editing CMOS config x86: Enable RTC command by default
.azure-pipelines.yml | 2 +- .gitlab-ci.yml | 2 +- arch/sandbox/dts/cedit.dtsi | 3 + arch/sandbox/lib/bootm.c | 7 + arch/x86/dts/coreboot.dts | 7 + boot/Makefile | 4 + boot/cedit.c | 191 +++++++++++++++-------- boot/expo.c | 3 + boot/expo_build.c | 36 ++--- boot/expo_build_cb.c | 244 ++++++++++++++++++++++++++++++ boot/scene.c | 61 ++++++-- boot/scene_internal.h | 30 +++- boot/scene_menu.c | 26 +++- boot/scene_textline.c | 3 +- cmd/Kconfig | 14 +- cmd/bootflow.c | 27 +++- cmd/booti.c | 2 +- cmd/cedit.c | 28 ++++ cmd/cls.c | 25 +-- cmd/x86/Makefile | 1 + cmd/x86/cbcmos.c | 141 +++++++++++++++++ cmd/x86/cbsysinfo.c | 73 ++++++++- common/console.c | 31 ++++ configs/coreboot64_defconfig | 2 + configs/coreboot_defconfig | 6 + configs/tools-only_defconfig | 3 +- doc/board/coreboot/coreboot.rst | 6 + doc/develop/cedit.rst | 9 +- doc/develop/expo.rst | 26 +++- doc/usage/cmd/bootflow.rst | 5 + doc/usage/cmd/cbcmos.rst | 45 ++++++ doc/usage/cmd/cbsysinfo.rst | 99 ++++++++++++ doc/usage/cmd/cedit.rst | 91 ++++++++++- doc/usage/index.rst | 1 + drivers/video/vidconsole-uclass.c | 4 +- drivers/video/video-uclass.c | 3 + include/cedit.h | 1 + include/console.h | 10 ++ include/expo.h | 51 +++++-- include/test/cedit-test.h | 30 ++-- include/test/cmd.h | 15 ++ include/test/suites.h | 1 + include/test/ut.h | 30 ++++ include/video.h | 4 +- include/video_console.h | 8 + test/Kconfig | 6 + test/Makefile | 2 +- test/boot/bootflow.c | 82 ++++++++++ test/boot/cedit.c | 22 ++- test/boot/expo.c | 26 +++- test/boot/files/expo_ids.h | 3 +- test/boot/files/expo_layout.dts | 5 +- test/cmd/Makefile | 3 + test/cmd/bdinfo.c | 23 ++- test/cmd/cmd_ut_cmd.c | 21 +++ test/cmd/coreboot.c | 120 +++++++++++++++ test/cmd/fdt.c | 8 +- test/cmd/font.c | 6 +- test/cmd_ut.c | 8 +- test/common/event.c | 3 + test/lib/lmb.c | 36 ++--- test/print_ut.c | 8 + test/test-main.c | 3 +- test/ut.c | 27 ++++ tools/expo.py | 33 +++- 65 files changed, 1640 insertions(+), 216 deletions(-) create mode 100644 boot/expo_build_cb.c create mode 100644 cmd/x86/cbcmos.c create mode 100644 doc/usage/cmd/cbcmos.rst create mode 100644 include/test/cmd.h create mode 100644 test/cmd/cmd_ut_cmd.c create mode 100644 test/cmd/coreboot.c

Tests without the UT_TESTF_SCAN_FDT flag are currently skipped unless OF_LIVE is enabled.
Drop this condition, so that they can run on non-sandbox builds, which often don't have OF_LIVE enabled.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/test-main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/test/test-main.c b/test/test-main.c index 778bf0a18a0f..2a3b2ba364a8 100644 --- a/test/test-main.c +++ b/test/test-main.c @@ -476,8 +476,7 @@ static int ut_run_test_live_flat(struct unit_test_state *uts, * (for sandbox we handle this by copying the tree, but not for other * boards) */ - if ((test->flags & UT_TESTF_SCAN_FDT) && - !(test->flags & UT_TESTF_LIVE_TREE) && + if (!(test->flags & UT_TESTF_LIVE_TREE) && (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) || !(test->flags & UT_TESTF_OTHER_FDT)) && (!runs || ut_test_run_on_flattree(test)) &&

Add a new suite for 'cmd' tests, used for testing commands. These are kept in the test/cmd directory.
For now it is empty, but it will be used for coreboot-command tests.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/test/cmd.h | 15 +++++++++++++++ include/test/suites.h | 1 + test/cmd/Makefile | 2 ++ test/cmd/cmd_ut_cmd.c | 21 +++++++++++++++++++++ test/cmd_ut.c | 6 ++++++ 5 files changed, 45 insertions(+) create mode 100644 include/test/cmd.h create mode 100644 test/cmd/cmd_ut_cmd.c
diff --git a/include/test/cmd.h b/include/test/cmd.h new file mode 100644 index 000000000000..c200570e423d --- /dev/null +++ b/include/test/cmd.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2023 Google LLC + * Written by Simon Glass sjg@chromium.org + */ + +#ifndef __TEST_CMD_H__ +#define __TEST_CMD_H__ + +#include <test/test.h> + +/* Declare a new command test */ +#define CMD_TEST(_name, _flags) UNIT_TEST(_name, _flags, cmd_test) + +#endif /* __TEST_CMD_H__ */ diff --git a/include/test/suites.h b/include/test/suites.h index 1c7dc65966a1..2d4897d46b8e 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -34,6 +34,7 @@ int do_ut_bootstd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_ut_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_common(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); diff --git a/test/cmd/Makefile b/test/cmd/Makefile index 8d70ac510a53..0be2cec89018 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -3,6 +3,8 @@ # Copyright (c) 2013 Google, Inc # Copyright 2022-2023 Arm Limited and/or its affiliates open-source-office@arm.com
+obj-y += cmd_ut_cmd.o + ifdef CONFIG_HUSH_PARSER obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o endif diff --git a/test/cmd/cmd_ut_cmd.c b/test/cmd/cmd_ut_cmd.c new file mode 100644 index 000000000000..1a5bfdb4a183 --- /dev/null +++ b/test/cmd/cmd_ut_cmd.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2023 Google LLC + * Written by Simon Glass sjg@chromium.org + * + * Unit tests for command functions + */ + +#include <common.h> +#include <command.h> +#include <test/cmd.h> +#include <test/suites.h> +#include <test/ut.h> + +int do_ut_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(cmd_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(cmd_test); + + return cmd_ut_category("cmd", "cmd_test_", tests, n_ents, argc, argv); +} diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 0f56409e8031..d3505fe8d97e 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -60,6 +60,9 @@ static struct cmd_tbl cmd_ut_sub[] = { #ifdef CONFIG_BOOTSTD U_BOOT_CMD_MKENT(bootstd, CONFIG_SYS_MAXARGS, 1, do_ut_bootstd, "", ""), +#endif +#ifdef CONFIG_CMDLINE + U_BOOT_CMD_MKENT(cmd, CONFIG_SYS_MAXARGS, 1, do_ut_cmd, "", ""), #endif U_BOOT_CMD_MKENT(common, CONFIG_SYS_MAXARGS, 1, do_ut_common, "", ""), #if defined(CONFIG_UT_DM) @@ -188,6 +191,9 @@ static char ut_help_text[] = #ifdef CONFIG_BOOTSTD "\nbootstd - standard boot implementation" #endif +#ifdef CONFIG_CMDLINE + "\ncmd - test various commands" +#endif #ifdef CONFIG_SANDBOX "\ncompression - compressors and bootm decompression" #endif

Add a new suite for 'cmd' tests, used for testing commands. These are kept in the test/cmd directory.
For now it is empty, but it will be used for coreboot-command tests.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/test/cmd.h | 15 +++++++++++++++ include/test/suites.h | 1 + test/cmd/Makefile | 2 ++ test/cmd/cmd_ut_cmd.c | 21 +++++++++++++++++++++ test/cmd_ut.c | 6 ++++++ 5 files changed, 45 insertions(+) create mode 100644 include/test/cmd.h create mode 100644 test/cmd/cmd_ut_cmd.c
Applied to u-boot-dm/next, thanks!

Sometimes we need to skip to a line but it includes addresses or other information which can vary depending on the runtime conditions.
Add a new ut_assert_skip_to_linen() which is similar to the existing ut_assert_skip_to_line() function but only checks that the console line matches up to the length of the provided string.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/test/ut.h | 30 ++++++++++++++++++++++++++++++ test/ut.c | 27 +++++++++++++++++++++++++++ 2 files changed, 57 insertions(+)
diff --git a/include/test/ut.h b/include/test/ut.h index ea6ee95d7344..d3172af8083f 100644 --- a/include/test/ut.h +++ b/include/test/ut.h @@ -97,6 +97,23 @@ int ut_check_skipline(struct unit_test_state *uts); */ int ut_check_skip_to_line(struct unit_test_state *uts, const char *fmt, ...);
+/** + * ut_check_skip_to_linen() - skip output until a partial line is found + * + * This creates a string and then checks it against the following lines of + * console output obtained with console_record_readline() until it is found. + * Only the characters up to the length of the string are checked, so the line + * may extend further + * + * After the function returns, uts->expect_str holds the expected string and + * uts->actual_str holds the actual string read from the console. + * + * @uts: Test state + * @fmt: printf() format string to look for, followed by args + * Return: 0 if OK, -ENOENT if not found, other value on error + */ +int ut_check_skip_to_linen(struct unit_test_state *uts, const char *fmt, ...); + /** * ut_check_console_end() - Check there is no more console output * @@ -359,6 +376,19 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); __ret; \ })
+/* Assert that a following console output line matches */ +#define ut_assert_skip_to_linen(fmt, args...) ({ \ + int __ret = 0; \ + \ + if (ut_check_skip_to_linen(uts, fmt, ##args)) { \ + ut_failf(uts, __FILE__, __LINE__, __func__, \ + "console", "\nExpected '%s',\n got to '%s'", \ + uts->expect_str, uts->actual_str); \ + return CMD_RET_FAILURE; \ + } \ + __ret; \ +}) + /* Assert that there is no more console output */ #define ut_assert_console_end() ({ \ int __ret = 0; \ diff --git a/test/ut.c b/test/ut.c index 28da417686e4..628e9dc98050 100644 --- a/test/ut.c +++ b/test/ut.c @@ -121,6 +121,33 @@ int ut_check_skipline(struct unit_test_state *uts) return 0; }
+int ut_check_skip_to_linen(struct unit_test_state *uts, const char *fmt, ...) +{ + va_list args; + int len; + int ret; + + va_start(args, fmt); + len = vsnprintf(uts->expect_str, sizeof(uts->expect_str), fmt, args); + va_end(args); + if (len >= sizeof(uts->expect_str)) { + ut_fail(uts, __FILE__, __LINE__, __func__, + "unit_test_state->expect_str too small"); + return -EOVERFLOW; + } + while (1) { + if (!console_record_avail()) + return -ENOENT; + ret = readline_check(uts); + if (ret < 0) + return ret; + + if (!strncmp(uts->expect_str, uts->actual_str, + strlen(uts->expect_str))) + return 0; + } +} + int ut_check_skip_to_line(struct unit_test_state *uts, const char *fmt, ...) { va_list args;

Sometimes we need to skip to a line but it includes addresses or other information which can vary depending on the runtime conditions.
Add a new ut_assert_skip_to_linen() which is similar to the existing ut_assert_skip_to_line() function but only checks that the console line matches up to the length of the provided string.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/test/ut.h | 30 ++++++++++++++++++++++++++++++ test/ut.c | 27 +++++++++++++++++++++++++++ 2 files changed, 57 insertions(+)
Applied to u-boot-dm/next, thanks!

This doesn't seem to work on a real board, so use the test on sandbox only.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/test/Kconfig b/test/Kconfig index 830245b6f9a9..69d63a5ff7dd 100644 --- a/test/Kconfig +++ b/test/Kconfig @@ -31,6 +31,7 @@ if UT_LIB
config UT_LIB_ASN1 bool "Unit test for asn1 compiler and decoder function" + depends on SANDBOX default y imply ASYMMETRIC_KEY_TYPE imply ASYMMETRIC_PUBLIC_KEY_SUBTYPE

This doesn't seem to work on a real board, so use the test on sandbox only.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/Kconfig | 1 + 1 file changed, 1 insertion(+)
Applied to u-boot-dm/next, thanks!

These make use of disk images which are not available on reak boards. Add a new Kconfig to ensure these tests only run where they are valid.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/Kconfig | 5 +++++ test/Makefile | 2 +- test/cmd_ut.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/test/Kconfig b/test/Kconfig index 69d63a5ff7dd..022395e489bb 100644 --- a/test/Kconfig +++ b/test/Kconfig @@ -64,6 +64,11 @@ config UT_LIB_RSA
endif
+config UT_BOOTSTD + bool "Unit tests for standard boot" + depends on UNIT_TEST && SANDBOX + default y + config UT_COMPRESSION bool "Unit test for compression" depends on UNIT_TEST diff --git a/test/Makefile b/test/Makefile index 178773647a82..4e179cb3930a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -26,7 +26,7 @@ obj-$(CONFIG_UT_TIME) += time_ut.o obj-y += ut.o
ifeq ($(CONFIG_SPL_BUILD),) -obj-$(CONFIG_UNIT_TEST) += boot/ +obj-$(CONFIG_$(SPL_)UT_BOOTSTD) += boot/ obj-$(CONFIG_UNIT_TEST) += common/ obj-y += log/ obj-$(CONFIG_$(SPL_)UT_UNICODE) += unicode_ut.o diff --git a/test/cmd_ut.c b/test/cmd_ut.c index d3505fe8d97e..f74930a7ecbe 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -57,7 +57,7 @@ static struct cmd_tbl cmd_ut_sub[] = { #ifdef CONFIG_CMD_BDI U_BOOT_CMD_MKENT(bdinfo, CONFIG_SYS_MAXARGS, 1, do_ut_bdinfo, "", ""), #endif -#ifdef CONFIG_BOOTSTD +#ifdef CONFIG_UT_BOOTSTD U_BOOT_CMD_MKENT(bootstd, CONFIG_SYS_MAXARGS, 1, do_ut_bootstd, "", ""), #endif

These make use of disk images which are not available on reak boards. Add a new Kconfig to ensure these tests only run where they are valid.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/Kconfig | 5 +++++ test/Makefile | 2 +- test/cmd_ut.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-)
Applied to u-boot-dm/next, thanks!

This test assumes that the stack pointer is the same across two calls to lmb_init_and_reserve() but this is not the case on x86, for example.
Add a special case to handle this, along with a detailed comment.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/cmd/bdinfo.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/test/cmd/bdinfo.c b/test/cmd/bdinfo.c index 8c09281cac0d..0f09a5a3e1db 100644 --- a/test/cmd/bdinfo.c +++ b/test/cmd/bdinfo.c @@ -114,6 +114,18 @@ static int lmb_test_dump_region(struct unit_test_state *uts, end = base + size - 1; flags = rgn->region[i].flags;
+ /* + * this entry includes the stack (get_sp()) on many platforms + * so will different each time lmb_init_and_reserve() is called. + * We could instead have the bdinfo command put its lmb region + * in a known location, so we can check it directly, rather than + * calling lmb_init_and_reserve() to create a new (and hopefully + * identical one). But for now this seems good enough. + */ + if (!IS_ENABLED(CONFIG_SANDBOX) && i == 3) { + ut_assert_nextlinen(" %s[%d]\t[", name, i); + continue; + } ut_assert_nextline(" %s[%d]\t[0x%llx-0x%llx], 0x%08llx bytes flags: %x", name, i, base, end, size, flags); }

This test assumes that the stack pointer is the same across two calls to lmb_init_and_reserve() but this is not the case on x86, for example.
Add a special case to handle this, along with a detailed comment.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/cmd/bdinfo.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
Applied to u-boot-dm/next, thanks!

Calling into sub-test functions should be done using ut_assertok() so that the test exits immediately on failure. Add those which are missing.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/cmd/bdinfo.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/test/cmd/bdinfo.c b/test/cmd/bdinfo.c index 0f09a5a3e1db..9ada7523fc27 100644 --- a/test/cmd/bdinfo.c +++ b/test/cmd/bdinfo.c @@ -136,8 +136,8 @@ static int lmb_test_dump_region(struct unit_test_state *uts, static int lmb_test_dump_all(struct unit_test_state *uts, struct lmb *lmb) { ut_assert_nextline("lmb_dump_all:"); - lmb_test_dump_region(uts, &lmb->memory, "memory"); - lmb_test_dump_region(uts, &lmb->reserved, "reserved"); + ut_assertok(lmb_test_dump_region(uts, &lmb->memory, "memory")); + ut_assertok(lmb_test_dump_region(uts, &lmb->reserved, "reserved"));
return 0; } @@ -188,7 +188,7 @@ static int bdinfo_test_move(struct unit_test_state *uts) ut_assertok(test_num_l(uts, "fdt_size", (ulong)gd->fdt_size));
if (IS_ENABLED(CONFIG_VIDEO)) - test_video_info(uts); + ut_assertok(test_video_info(uts));
/* The gd->multi_dtb_fit may not be available, hence, #if below. */ #if CONFIG_IS_ENABLED(MULTI_DTB_FIT) @@ -199,7 +199,7 @@ static int bdinfo_test_move(struct unit_test_state *uts) struct lmb lmb;
lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob); - lmb_test_dump_all(uts, &lmb); + ut_assertok(lmb_test_dump_all(uts, &lmb)); if (IS_ENABLED(CONFIG_OF_REAL)) ut_assert_nextline("devicetree = %s", fdtdec_get_srcname()); } @@ -224,6 +224,9 @@ static int bdinfo_test_move(struct unit_test_state *uts) ut_assertok(test_num_l(uts, "malloc base", gd_malloc_start())); }
+ if (IS_ENABLED(CONFIG_X86)) + ut_check_skip_to_linen(uts, " high end ="); + ut_assertok(ut_check_console_end(uts));
return 0;

Calling into sub-test functions should be done using ut_assertok() so that the test exits immediately on failure. Add those which are missing.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/cmd/bdinfo.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
Applied to u-boot-dm/next, thanks!

The error that this test checks for is only shown on sandbox. For real boards, there is normally no error. Add a special case to handle this.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/cmd/fdt.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index 1f103a1d7eb4..547085521758 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -160,7 +160,13 @@ static int fdt_test_addr(struct unit_test_state *uts) set_working_fdt_addr(0); ut_assert_nextline("Working FDT set to 0"); ut_asserteq(CMD_RET_FAILURE, run_command("fdt addr", 0)); - ut_assert_nextline("libfdt fdt_check_header(): FDT_ERR_BADMAGIC"); + + /* + * sandbox fails the check for !blob since the 0 pointer is mapped to + * memory somewhere other than at 0x0 + */ + if (IS_ENABLED(CONFIG_SANDBOX)) + ut_assert_nextline("libfdt fdt_check_header(): FDT_ERR_BADMAGIC"); ut_assertok(ut_check_console_end(uts));
/* Set up a working FDT and try again */

The font test needs two fonts. If one is not available, skip out early, to avoid an error.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/cmd/font.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/test/cmd/font.c b/test/cmd/font.c index 40682e5ce495..1fe05c1ead51 100644 --- a/test/cmd/font.c +++ b/test/cmd/font.c @@ -30,13 +30,17 @@ static int font_test_base(struct unit_test_state *uts) ut_assertok(console_record_reset_enable()); ut_assertok(run_command("font list", 0)); ut_assert_nextline("nimbus_sans_l_regular"); - ut_assert_nextline("cantoraone_regular"); + if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_CANTORAONE)) + ut_assert_nextline("cantoraone_regular"); ut_assertok(ut_check_console_end(uts));
ut_assertok(vidconsole_get_font_size(dev, &name, &size)); ut_asserteq_str("nimbus_sans_l_regular", name); ut_asserteq(18, size);
+ if (!IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_CANTORAONE)) + return 0; + max_metrics = 1; if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE)) max_metrics = IF_ENABLED_INT(CONFIG_CONSOLE_TRUETYPE,

The font test needs two fonts. If one is not available, skip out early, to avoid an error.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/cmd/font.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
Applied to u-boot-dm/next, thanks!

This needs test devices which are only present on sandbox. Add a check for this and skip just this test if running on a real board.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/common/event.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/test/common/event.c b/test/common/event.c index c0912a3437bb..b462694fc3b6 100644 --- a/test/common/event.c +++ b/test/common/event.c @@ -92,6 +92,9 @@ static int test_event_probe(struct unit_test_state *uts) struct test_state state; struct udevice *dev;
+ if (!IS_ENABLED(SANDBOX)) + return -EAGAIN; + state.val = 0; ut_assertok(event_register("pre", EVT_DM_PRE_PROBE, h_probe, &state)); ut_assertok(event_register("post", EVT_DM_POST_PROBE, h_probe, &state));

This needs test devices which are only present on sandbox. Add a check for this and skip just this test if running on a real board.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/common/event.c | 3 +++ 1 file changed, 3 insertions(+)
Applied to u-boot-dm/next, thanks!

These tests are marked as driver model tests, but have nothing to do with driver model. As a result, they are run as part of 'ut dm' which only exists for sandbox.
Move them to the 'lib' suite and drop the requirement for initing devices, since they don't use devices.
Also put the lib_test_lmb_max_regions() macro inside the same #ifdef as its function, to avoid a build error if the condition is false.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/lib/lmb.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-)
diff --git a/test/lib/lmb.c b/test/lib/lmb.c index 162887503588..0eccd77114e1 100644 --- a/test/lib/lmb.c +++ b/test/lib/lmb.c @@ -9,6 +9,7 @@ #include <log.h> #include <malloc.h> #include <dm/test.h> +#include <test/lib.h> #include <test/test.h> #include <test/ut.h>
@@ -205,8 +206,7 @@ static int lib_test_lmb_simple(struct unit_test_state *uts) /* simulate 512 MiB RAM beginning at 1.5GiB */ return test_multi_alloc_512mb(uts, 0xE0000000); } - -DM_TEST(lib_test_lmb_simple, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +LIB_TEST(lib_test_lmb_simple, 0);
/* Create two memory regions with one reserved region and allocate */ static int lib_test_lmb_simple_x2(struct unit_test_state *uts) @@ -221,8 +221,7 @@ static int lib_test_lmb_simple_x2(struct unit_test_state *uts) /* simulate 512 MiB RAM beginning at 3.5GiB and 1 GiB */ return test_multi_alloc_512mb_x2(uts, 0xE0000000, 0x40000000); } - -DM_TEST(lib_test_lmb_simple_x2, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +LIB_TEST(lib_test_lmb_simple_x2, 0);
/* Simulate 512 MiB RAM, allocate some blocks that fit/don't fit */ static int test_bigblock(struct unit_test_state *uts, const phys_addr_t ram) @@ -288,8 +287,7 @@ static int lib_test_lmb_big(struct unit_test_state *uts) /* simulate 512 MiB RAM beginning at 1.5GiB */ return test_bigblock(uts, 0xE0000000); } - -DM_TEST(lib_test_lmb_big, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +LIB_TEST(lib_test_lmb_big, 0);
/* Simulate 512 MiB RAM, allocate a block without previous reservation */ static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram, @@ -364,7 +362,7 @@ static int lib_test_lmb_noreserved(struct unit_test_state *uts) return test_noreserved(uts, 0xE0000000, 4, 1); }
-DM_TEST(lib_test_lmb_noreserved, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +LIB_TEST(lib_test_lmb_noreserved, 0);
static int lib_test_lmb_unaligned_size(struct unit_test_state *uts) { @@ -378,8 +376,8 @@ static int lib_test_lmb_unaligned_size(struct unit_test_state *uts) /* simulate 512 MiB RAM beginning at 1.5GiB */ return test_noreserved(uts, 0xE0000000, 5, 8); } +LIB_TEST(lib_test_lmb_unaligned_size, 0);
-DM_TEST(lib_test_lmb_unaligned_size, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); /* * Simulate a RAM that starts at 0 and allocate down to address 0, which must * fail as '0' means failure for the lmb_alloc functions. @@ -421,8 +419,7 @@ static int lib_test_lmb_at_0(struct unit_test_state *uts)
return 0; } - -DM_TEST(lib_test_lmb_at_0, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +LIB_TEST(lib_test_lmb_at_0, 0);
/* Check that calling lmb_reserve with overlapping regions fails. */ static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts) @@ -459,9 +456,7 @@ static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts)
return 0; } - -DM_TEST(lib_test_lmb_overlapping_reserve, - UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +LIB_TEST(lib_test_lmb_overlapping_reserve, 0);
/* * Simulate 512 MiB RAM, reserve 3 blocks, allocate addresses in between. @@ -590,8 +585,7 @@ static int lib_test_lmb_alloc_addr(struct unit_test_state *uts) /* simulate 512 MiB RAM beginning at 1.5GiB */ return test_alloc_addr(uts, 0xE0000000); } - -DM_TEST(lib_test_lmb_alloc_addr, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +LIB_TEST(lib_test_lmb_alloc_addr, 0);
/* Simulate 512 MiB RAM, reserve 3 blocks, check addresses in between */ static int test_get_unreserved_size(struct unit_test_state *uts, @@ -661,9 +655,7 @@ static int lib_test_lmb_get_free_size(struct unit_test_state *uts) /* simulate 512 MiB RAM beginning at 1.5GiB */ return test_get_unreserved_size(uts, 0xE0000000); } - -DM_TEST(lib_test_lmb_get_free_size, - UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +LIB_TEST(lib_test_lmb_get_free_size, 0);
#ifdef CONFIG_LMB_USE_MAX_REGIONS static int lib_test_lmb_max_regions(struct unit_test_state *uts) @@ -732,11 +724,9 @@ static int lib_test_lmb_max_regions(struct unit_test_state *uts)
return 0; } +LIB_TEST(lib_test_lmb_max_regions, 0); #endif
-DM_TEST(lib_test_lmb_max_regions, - UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); - static int lib_test_lmb_flags(struct unit_test_state *uts) { const phys_addr_t ram = 0x40000000; @@ -822,6 +812,4 @@ static int lib_test_lmb_flags(struct unit_test_state *uts)
return 0; } - -DM_TEST(lib_test_lmb_flags, - UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +LIB_TEST(lib_test_lmb_flags, 0);

These tests are marked as driver model tests, but have nothing to do with driver model. As a result, they are run as part of 'ut dm' which only exists for sandbox.
Move them to the 'lib' suite and drop the requirement for initing devices, since they don't use devices.
Also put the lib_test_lmb_max_regions() macro inside the same #ifdef as its function, to avoid a build error if the condition is false.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/lib/lmb.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-)
Applied to u-boot-dm/next, thanks!

These tests cannot work on x86 machines as memory at address zero is not writable. Add a condition to skip these.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/print_ut.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/test/print_ut.c b/test/print_ut.c index b26f6281b013..bb844d2542b7 100644 --- a/test/print_ut.c +++ b/test/print_ut.c @@ -170,6 +170,10 @@ static int print_display_buffer(struct unit_test_state *uts) u8 *buf; int i;
+ /* This test requires writable memory at zero */ + if (IS_ENABLED(CONFIG_X86)) + return -EAGAIN; + buf = map_sysmem(0, BUF_SIZE); memset(buf, '\0', BUF_SIZE); for (i = 0; i < 0x11; i++) @@ -275,6 +279,10 @@ static int print_do_hex_dump(struct unit_test_state *uts) u8 *buf; int i;
+ /* This test requires writable memory at zero */ + if (IS_ENABLED(CONFIG_X86)) + return -EAGAIN; + buf = map_sysmem(0, BUF_SIZE); memset(buf, '\0', BUF_SIZE); for (i = 0; i < 0x11; i++)

These tests cannot work on x86 machines as memory at address zero is not writable. Add a condition to skip these.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/print_ut.c | 8 ++++++++ 1 file changed, 8 insertions(+)
Applied to u-boot-dm/next, thanks!

Move the code from the 'cls' command into the console file, so it can be called from elsewhere.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/cls.c | 25 +++---------------------- common/console.c | 31 +++++++++++++++++++++++++++++++ include/console.h | 10 ++++++++++ 3 files changed, 44 insertions(+), 22 deletions(-)
diff --git a/cmd/cls.c b/cmd/cls.c index 1125a3f81bbb..80d0558d4679 100644 --- a/cmd/cls.c +++ b/cmd/cls.c @@ -7,33 +7,14 @@ */ #include <common.h> #include <command.h> +#include <console.h> #include <dm.h> -#include <video_console.h> - -#define CSI "\x1b["
static int do_video_clear(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - __maybe_unused struct udevice *dev; - - /* - * Send clear screen and home - * - * FIXME(Heinrich Schuchardt xypron.glpk@gmx.de): This should go - * through an API and only be written to serial terminals, not video - * displays - */ - printf(CSI "2J" CSI "1;1H"); - if (IS_ENABLED(CONFIG_VIDEO_ANSI)) - return 0; - - if (IS_ENABLED(CONFIG_VIDEO)) { - if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev)) - return CMD_RET_FAILURE; - if (vidconsole_clear_and_reset(dev)) - return CMD_RET_FAILURE; - } + if (console_clear()) + return CMD_RET_FAILURE;
return CMD_RET_SUCCESS; } diff --git a/common/console.c b/common/console.c index 98c3ee6ca6b8..1ffda49c87e0 100644 --- a/common/console.c +++ b/common/console.c @@ -19,12 +19,15 @@ #include <stdio_dev.h> #include <exports.h> #include <env_internal.h> +#include <video_console.h> #include <watchdog.h> #include <asm/global_data.h> #include <linux/delay.h>
DECLARE_GLOBAL_DATA_PTR;
+#define CSI "\x1b[" + static int on_console(const char *name, const char *value, enum env_op op, int flags) { @@ -1010,6 +1013,34 @@ int console_init_f(void) return 0; }
+int console_clear(void) +{ + /* + * Send clear screen and home + * + * FIXME(Heinrich Schuchardt xypron.glpk@gmx.de): This should go + * through an API and only be written to serial terminals, not video + * displays + */ + printf(CSI "2J" CSI "1;1H"); + if (IS_ENABLED(CONFIG_VIDEO_ANSI)) + return 0; + + if (IS_ENABLED(CONFIG_VIDEO)) { + struct udevice *dev; + int ret; + + ret = uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev); + if (ret) + return ret; + ret = vidconsole_clear_and_reset(dev); + if (ret) + return ret; + } + + return 0; +} + static void stdio_print_current_devices(void) { char *stdinname, *stdoutname, *stderrname; diff --git a/include/console.h b/include/console.h index ceb733b5cb69..e29817e57b00 100644 --- a/include/console.h +++ b/include/console.h @@ -156,6 +156,16 @@ int console_announce_r(void); */ void console_puts_select_stderr(bool serial_only, const char *s);
+/** + * console_clear() - Clear the console + * + * Uses an ANSI sequence to clear the display, failing back to clearing the + * video display directly if !CONFIG_VIDEO_ANSI + * + * Return: 0 if OK, -ve on error + */ +int console_clear(void); + /* * CONSOLE multiplexing. */

Hi,
On Sun, 1 Oct 2023 at 19:16, Simon Glass sjg@chromium.org wrote:
Move the code from the 'cls' command into the console file, so it can be called from elsewhere.
Signed-off-by: Simon Glass sjg@chromium.org
cmd/cls.c | 25 +++---------------------- common/console.c | 31 +++++++++++++++++++++++++++++++ include/console.h | 10 ++++++++++ 3 files changed, 44 insertions(+), 22 deletions(-)
Any word on this patch, please?
Heinrich, do you want to look at it?
Regards, Simon

Hi,
On Sun, 1 Oct 2023 at 19:16, Simon Glass sjg@chromium.org wrote:
Move the code from the 'cls' command into the console file, so it can be called from elsewhere.
Signed-off-by: Simon Glass sjg@chromium.org
cmd/cls.c | 25 +++---------------------- common/console.c | 31 +++++++++++++++++++++++++++++++ include/console.h | 10 ++++++++++ 3 files changed, 44 insertions(+), 22 deletions(-)
Any word on this patch, please?
Heinrich, do you want to look at it?
Regards, Simon
Applied to u-boot-dm/next, thanks!

On 02.10.23 03:15, Simon Glass wrote:
Move the code from the 'cls' command into the console file, so it can be called from elsewhere.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
cmd/cls.c | 25 +++---------------------- common/console.c | 31 +++++++++++++++++++++++++++++++ include/console.h | 10 ++++++++++ 3 files changed, 44 insertions(+), 22 deletions(-)
diff --git a/cmd/cls.c b/cmd/cls.c index 1125a3f81bbb..80d0558d4679 100644 --- a/cmd/cls.c +++ b/cmd/cls.c @@ -7,33 +7,14 @@ */ #include <common.h> #include <command.h> +#include <console.h> #include <dm.h> -#include <video_console.h>
-#define CSI "\x1b["
static int do_video_clear(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) {
- __maybe_unused struct udevice *dev;
- /*
* Send clear screen and home
*
* FIXME(Heinrich Schuchardt <xypron.glpk@gmx.de>): This should go
* through an API and only be written to serial terminals, not video
* displays
*/
- printf(CSI "2J" CSI "1;1H");
- if (IS_ENABLED(CONFIG_VIDEO_ANSI))
return 0;
- if (IS_ENABLED(CONFIG_VIDEO)) {
if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev))
return CMD_RET_FAILURE;
if (vidconsole_clear_and_reset(dev))
return CMD_RET_FAILURE;
- }
if (console_clear())
return CMD_RET_FAILURE;
return CMD_RET_SUCCESS; }
diff --git a/common/console.c b/common/console.c index 98c3ee6ca6b8..1ffda49c87e0 100644 --- a/common/console.c +++ b/common/console.c @@ -19,12 +19,15 @@ #include <stdio_dev.h> #include <exports.h> #include <env_internal.h> +#include <video_console.h> #include <watchdog.h> #include <asm/global_data.h> #include <linux/delay.h>
DECLARE_GLOBAL_DATA_PTR;
+#define CSI "\x1b["
- static int on_console(const char *name, const char *value, enum env_op op, int flags) {
@@ -1010,6 +1013,34 @@ int console_init_f(void) return 0; }
+int console_clear(void) +{
- /*
* Send clear screen and home
*
* FIXME(Heinrich Schuchardt <xypron.glpk@gmx.de>): This should go
* through an API and only be written to serial terminals, not video
* displays
*/
- printf(CSI "2J" CSI "1;1H");
- if (IS_ENABLED(CONFIG_VIDEO_ANSI))
return 0;
- if (IS_ENABLED(CONFIG_VIDEO)) {
struct udevice *dev;
int ret;
ret = uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev);
if (ret)
return ret;
ret = vidconsole_clear_and_reset(dev);
if (ret)
return ret;
- }
- return 0;
+}
- static void stdio_print_current_devices(void) { char *stdinname, *stdoutname, *stderrname;
diff --git a/include/console.h b/include/console.h index ceb733b5cb69..e29817e57b00 100644 --- a/include/console.h +++ b/include/console.h @@ -156,6 +156,16 @@ int console_announce_r(void); */ void console_puts_select_stderr(bool serial_only, const char *s);
+/**
- console_clear() - Clear the console
- Uses an ANSI sequence to clear the display, failing back to clearing the
- video display directly if !CONFIG_VIDEO_ANSI
- Return: 0 if OK, -ve on error
- */
+int console_clear(void);
- /*
*/
- CONSOLE multiplexing.

Add basic sandbox support for 'booti' so we can start to boot the test ARMbian image. This is helpful in checking that it is parsed correctly.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/sandbox/lib/bootm.c | 7 +++++++ cmd/Kconfig | 2 +- cmd/booti.c | 2 +- configs/tools-only_defconfig | 3 ++- 4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/arch/sandbox/lib/bootm.c b/arch/sandbox/lib/bootm.c index dc8b8e46cb41..a748ba650b12 100644 --- a/arch/sandbox/lib/bootm.c +++ b/arch/sandbox/lib/bootm.c @@ -78,3 +78,10 @@ int do_bootm_linux(int flag, int argc, char *argv[], struct bootm_headers *image
return 0; } + +/* used for testing 'booti' command */ +int booti_setup(ulong image, ulong *relocated_addr, ulong *size, + bool force_reloc) +{ + return 0; +} diff --git a/cmd/Kconfig b/cmd/Kconfig index 34e1c91a15a9..987f7d8cf623 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -305,7 +305,7 @@ config CMD_BOOTZ
config CMD_BOOTI bool "booti" - depends on ARM64 || RISCV + depends on ARM64 || RISCV || SANDBOX default y help Boot an AArch64 Linux Kernel image from memory. diff --git a/cmd/booti.c b/cmd/booti.c index 6ac39193db80..a20e65196f72 100644 --- a/cmd/booti.c +++ b/cmd/booti.c @@ -75,7 +75,7 @@ static int booti_start(struct cmd_tbl *cmdtp, int flag, int argc, unmap_sysmem((void *)ld);
ret = booti_setup(ld, &relocated_addr, &image_size, false); - if (ret != 0) + if (ret || IS_ENABLED(CONFIG_SANDBOX)) return 1;
/* Handle BOOTM_STATE_LOADOS */ diff --git a/configs/tools-only_defconfig b/configs/tools-only_defconfig index 3f588ea69bee..b54d2cefa100 100644 --- a/configs/tools-only_defconfig +++ b/configs/tools-only_defconfig @@ -6,8 +6,8 @@ CONFIG_SYS_LOAD_ADDR=0x0 CONFIG_PCI=y # CONFIG_SANDBOX_SDL is not set CONFIG_ANDROID_BOOT_IMAGE=y -CONFIG_FIT=y CONFIG_TIMESTAMP=y +CONFIG_FIT=y CONFIG_FIT_SIGNATURE=y # CONFIG_BOOTSTD_FULL is not set # CONFIG_BOOTMETH_CROS is not set @@ -16,6 +16,7 @@ CONFIG_USE_BOOTCOMMAND=y CONFIG_BOOTCOMMAND="run distro_bootcmd" # CONFIG_CMD_BOOTD is not set # CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_EXTENSION is not set # CONFIG_CMD_DATE is not set

Add basic sandbox support for 'booti' so we can start to boot the test ARMbian image. This is helpful in checking that it is parsed correctly.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/sandbox/lib/bootm.c | 7 +++++++ cmd/Kconfig | 2 +- cmd/booti.c | 2 +- configs/tools-only_defconfig | 3 ++- 4 files changed, 11 insertions(+), 3 deletions(-)
Applied to u-boot-dm/next, thanks!

Allow showing a menu and automatically booting, with 'bootflow scan'. This is more convenient than using a script.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/bootflow.c | 27 +++++++++++-- doc/usage/cmd/bootflow.rst | 5 +++ test/boot/bootflow.c | 82 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 4 deletions(-)
diff --git a/cmd/bootflow.c b/cmd/bootflow.c index 1516f8a4193b..e4ed4ab83d9d 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -135,7 +135,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, struct udevice *dev = NULL; struct bootflow bflow; bool all = false, boot = false, errors = false, no_global = false; - bool list = false, no_hunter = false; + bool list = false, no_hunter = false, menu = false, text_mode = false; int num_valid = 0; const char *label = NULL; bool has_args; @@ -155,6 +155,8 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, no_global = strchr(argv[1], 'G'); list = strchr(argv[1], 'l'); no_hunter = strchr(argv[1], 'H'); + menu = strchr(argv[1], 'm'); + text_mode = strchr(argv[1], 't'); argc--; argv++; } @@ -213,15 +215,32 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, } if (list) show_bootflow(i, &bflow, errors); - if (boot && !bflow.err) + if (!menu && boot && !bflow.err) bootflow_run_boot(&iter, &bflow); } bootflow_iter_uninit(&iter); if (list) show_footer(i, num_valid);
- if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL) && !num_valid && !list) - printf("No bootflows found; try again with -l\n"); + if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL) && IS_ENABLED(CONFIG_EXPO)) { + if (!num_valid && !list) { + printf("No bootflows found; try again with -l\n"); + } else if (menu) { + struct bootflow *sel_bflow; + + ret = bootflow_handle_menu(std, text_mode, &sel_bflow); + if (!ret && boot) { + ret = console_clear(); + if (ret) { + log_err("Failed to clear console: %dE\n", + ret); + return ret; + } + + bootflow_run_boot(NULL, sel_bflow); + } + } + }
return 0; } diff --git a/doc/usage/cmd/bootflow.rst b/doc/usage/cmd/bootflow.rst index 6a0645c28d07..795d5990bdc3 100644 --- a/doc/usage/cmd/bootflow.rst +++ b/doc/usage/cmd/bootflow.rst @@ -52,6 +52,8 @@ Flags are: matters, since by then the system boots in the OS and U-Boot is no-longer running. `bootflow scan -b` is a quick way to boot the first available OS. A valid bootflow is one that made it all the way to the `loaded` state. + Note that if `-m` is provided as well, booting is delayed until the user + selects a bootflow.
-e Used with -l to also show errors for each bootflow. The shows detailed error @@ -71,6 +73,9 @@ Flags are: priority or label is tried, to see if more bootdevs can be discovered, but this flag disables that process.
+-m + Show a menu of available bootflows for the user to select. When used with + -b it then boots the one that was selected, if any.
The optional argument specifies a particular bootdev to scan. This can either be the name of a bootdev or its sequence number (both shown with `bootdev list`). diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 04a5bd5d7a80..a57f5017364a 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -637,6 +637,88 @@ static int bootflow_cmd_menu(struct unit_test_state *uts) } BOOTSTD_TEST(bootflow_cmd_menu, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+/* Check 'bootflow scan -m' to select a bootflow using a menu */ +static int bootflow_scan_menu(struct unit_test_state *uts) +{ + struct bootstd_priv *std; + const char **old_order, **new_order; + char prev[3]; + + /* get access to the current bootflow */ + ut_assertok(bootstd_get_priv(&std)); + + ut_assertok(prep_mmc_bootdev(uts, "mmc4", false, &old_order)); + + /* Add keypresses to move to and select the second one in the list */ + prev[0] = CTL_CH('n'); + prev[1] = '\r'; + prev[2] = '\0'; + ut_asserteq(2, console_in_puts(prev)); + + ut_assertok(run_command("bootflow scan -lm", 0)); + new_order = std->bootdev_order; + std->bootdev_order = old_order; + + ut_assert_skip_to_line("No more bootdevs"); + ut_assert_nextlinen("--"); + ut_assert_nextline("(2 bootflows, 2 valid)"); + + ut_assert_nextline("Selected: Armbian"); + ut_assertnonnull(std->cur_bootflow); + ut_assert_console_end(); + + /* Check not selecting anything */ + prev[0] = '\e'; + prev[1] = '\0'; + ut_asserteq(1, console_in_puts(prev)); + + std->bootdev_order = new_order; /* Blue Monday */ + ut_assertok(run_command("bootflow scan -lm", 0)); + std->bootdev_order = old_order; + + ut_assertnull(std->cur_bootflow); + ut_assert_skip_to_line("(2 bootflows, 2 valid)"); + ut_assert_nextline("Nothing chosen"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_scan_menu, + UT_TESTF_DM | UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); + +/* Check 'bootflow scan -mb' to select and boot a bootflow using a menu */ +static int bootflow_scan_menu_boot(struct unit_test_state *uts) +{ + struct bootstd_priv *std; + const char **old_order; + char prev[3]; + + /* get access to the current bootflow */ + ut_assertok(bootstd_get_priv(&std)); + + ut_assertok(prep_mmc_bootdev(uts, "mmc4", false, &old_order)); + + /* Add keypresses to move to and select the second one in the list */ + prev[0] = CTL_CH('n'); + prev[1] = '\r'; + prev[2] = '\0'; + ut_asserteq(2, console_in_puts(prev)); + + ut_assertok(run_command("bootflow scan -lmb", 0)); + std->bootdev_order = old_order; + + ut_assert_skip_to_line("(2 bootflows, 2 valid)"); + + ut_assert_nextline("Selected: Armbian"); + ut_assert_skip_to_line("Boot failed (err=-14)"); + ut_assertnonnull(std->cur_bootflow); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_scan_menu_boot, + UT_TESTF_DM | UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); + /* Check searching for a single bootdev using the hunters */ static int bootflow_cmd_hunt_single(struct unit_test_state *uts) {

Allow showing a menu and automatically booting, with 'bootflow scan'. This is more convenient than using a script.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/bootflow.c | 27 +++++++++++-- doc/usage/cmd/bootflow.rst | 5 +++ test/boot/bootflow.c | 82 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 4 deletions(-)
Applied to u-boot-dm/next, thanks!

This is useful for highlighting something with a black background, as is needed with cedit when using a white-on-black console. Add this as a new colour.
Signed-off-by: Simon Glass sjg@chromium.org ---
boot/scene.c | 2 +- drivers/video/video-uclass.c | 3 +++ include/video.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/boot/scene.c b/boot/scene.c index d4dfb49ada15..0b37971b1ff4 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -346,7 +346,7 @@ static void scene_render_background(struct scene_obj *obj, bool box_only)
/* draw a background for the object */ if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) { - fore = VID_BLACK; + fore = VID_DARK_GREY; back = VID_WHITE; } else { fore = VID_LIGHT_GRAY; diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index f743ed74c818..51fafbb21747 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -281,6 +281,9 @@ static const struct vid_rgb colours[VID_COLOUR_COUNT] = { { 0xff, 0x00, 0xff }, /* bright magenta */ { 0x00, 0xff, 0xff }, /* bright cyan */ { 0xff, 0xff, 0xff }, /* white */ + + /* an extra one for menus */ + { 0x40, 0x40, 0x40 }, /* dark gray */ };
u32 video_index_to_colour(struct video_priv *priv, enum colour_idx idx) diff --git a/include/video.h b/include/video.h index 4d8df9baaada..ae9ce03f5bfa 100644 --- a/include/video.h +++ b/include/video.h @@ -179,6 +179,7 @@ enum colour_idx { VID_LIGHT_MAGENTA, VID_LIGHT_CYAN, VID_WHITE, + VID_DARK_GREY,
VID_COLOUR_COUNT };

When starting a new text line, an assumption is made that the current vertical position is a multiple of the character height. When this is not true, characters can be written after the end of the framebuffer.
This can causes crashes and strange errors from QEMU.
Adjust the scrolling check when processing a newline character, to avoid any problems.
Add some comments to make things a little clearer.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/vidconsole-uclass.c | 4 +++- include/video.h | 3 ++- include/video_console.h | 8 ++++++++ 3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index a312a1985242..a8d2199147dd 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -94,7 +94,9 @@ static void vidconsole_newline(struct udevice *dev) priv->ycur += priv->y_charsize;
/* Check if we need to scroll the terminal */ - if ((priv->ycur + priv->y_charsize) / priv->y_charsize > priv->rows) { + if (vid_priv->rot % 2 ? + priv->ycur + priv->x_charsize > vid_priv->xsize : + priv->ycur + priv->y_charsize > vid_priv->ysize) { vidconsole_move_rows(dev, 0, rows, priv->rows - rows); for (i = 0; i < rows; i++) vidconsole_set_row(dev, priv->rows - i - 1, diff --git a/include/video.h b/include/video.h index ae9ce03f5bfa..e20f1173762e 100644 --- a/include/video.h +++ b/include/video.h @@ -78,7 +78,8 @@ enum video_format { * * @xsize: Number of pixel columns (e.g. 1366) * @ysize: Number of pixels rows (e.g.. 768) - * @rot: Display rotation (0=none, 1=90 degrees clockwise, etc.) + * @rot: Display rotation (0=none, 1=90 degrees clockwise, etc.). THis + * does not affect @xsize and @ysize * @bpix: Encoded bits per pixel (enum video_log2_bpp) * @format: Pixel format (enum video_format) * @vidconsole_drv_name: Driver to use for the text console, NULL to diff --git a/include/video_console.h b/include/video_console.h index bde67fa9a5a9..ecbf183b3d03 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -27,6 +27,14 @@ enum { * Drivers must set up @rows, @cols, @x_charsize, @y_charsize in their probe() * method. Drivers may set up @xstart_frac if desired. * + * Note that these values relate to the rotated console, so that an 80x25 + * console which is rotated 90 degrees will have rows=80 and cols=25 + * + * The xcur_frac and ycur values refer to the unrotated coordinates, that is + * xcur_frac always advances with each character, even if its limit might be + * vid_priv->ysize instead of vid_priv->xsize if the console is rotated 90 or + * 270 degrees. + * * @sdev: stdio device, acting as an output sink * @xcur_frac: Current X position, in fractional units (VID_TO_POS(x)) * @ycur: Current Y position in pixels (0=top)

At present a fixed position is used for menu items, 200 pixels to the right of the left side of the labels. This means that a menu item with a very long label may overlap the items.
It seems better to calculate the maximum label width and then place the items to the right of all of them.
To implement this, add a new struct to containing arrangement information. Calculate it before doing the actual arrangement. Add a new style item which sets the amount of space from the right side of the labels to left side of the items.
Signed-off-by: Simon Glass sjg@chromium.org ---
boot/cedit.c | 13 ++++++++--- boot/expo.c | 2 ++ boot/scene.c | 52 +++++++++++++++++++++++++++++++++++++++++-- boot/scene_internal.h | 20 +++++++++++++++-- boot/scene_menu.c | 9 +++++--- boot/scene_textline.c | 3 ++- doc/develop/expo.rst | 4 ++++ include/expo.h | 12 ++++++++++ 8 files changed, 104 insertions(+), 11 deletions(-)
diff --git a/boot/cedit.c b/boot/cedit.c index 8c654dba6dc3..b5f89e945bce 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -52,10 +52,11 @@ struct cedit_iter_priv {
int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id) { + struct expo_arrange_info arr; struct scene_obj_txt *txt; struct scene_obj *obj; struct scene *scn; - int y; + int y, ret;
scn = expo_lookup_scene_id(exp, scene_id); if (!scn) @@ -69,6 +70,11 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id) if (txt) scene_obj_set_pos(scn, txt->obj.id, 200, 10);
+ memset(&arr, '\0', sizeof(arr)); + ret = scene_calc_arrange(scn, &arr); + if (ret < 0) + return log_msg_ret("arr", ret); + y = 100; list_for_each_entry(obj, &scn->obj_head, sibling) { switch (obj->type) { @@ -78,12 +84,13 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id) break; case SCENEOBJT_MENU: scene_obj_set_pos(scn, obj->id, 50, y); - scene_menu_arrange(scn, (struct scene_obj_menu *)obj); + scene_menu_arrange(scn, &arr, + (struct scene_obj_menu *)obj); y += 50; break; case SCENEOBJT_TEXTLINE: scene_obj_set_pos(scn, obj->id, 50, y); - scene_textline_arrange(scn, + scene_textline_arrange(scn, &arr, (struct scene_obj_textline *)obj); y += 50; break; diff --git a/boot/expo.c b/boot/expo.c index cadb6a0ad6e3..d030820e77ca 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -259,6 +259,8 @@ int expo_apply_theme(struct expo *exp, ofnode node) ofnode_read_u32(node, "font-size", &theme->font_size); ofnode_read_u32(node, "menu-inset", &theme->menu_inset); ofnode_read_u32(node, "menuitem-gap-y", &theme->menuitem_gap_y); + ofnode_read_u32(node, "menu-title-margin-x", + &theme->menu_title_margin_x);
list_for_each_entry(scn, &exp->scene_head, sibling) { ret = scene_apply_theme(scn, theme); diff --git a/boot/scene.c b/boot/scene.c index 0b37971b1ff4..56569e76e9f2 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -478,11 +478,59 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode) return 0; }
+int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr) +{ + struct scene_obj *obj; + + arr->label_width = 0; + list_for_each_entry(obj, &scn->obj_head, sibling) { + uint label_id = 0; + int width; + + switch (obj->type) { + case SCENEOBJT_NONE: + case SCENEOBJT_IMAGE: + case SCENEOBJT_TEXT: + break; + case SCENEOBJT_MENU: { + struct scene_obj_menu *menu; + + menu = (struct scene_obj_menu *)obj, + label_id = menu->title_id; + break; + } + case SCENEOBJT_TEXTLINE: { + struct scene_obj_textline *tline; + + tline = (struct scene_obj_textline *)obj, + label_id = tline->label_id; + break; + } + } + + if (label_id) { + int ret; + + ret = scene_obj_get_hw(scn, label_id, &width); + if (ret < 0) + return log_msg_ret("hei", ret); + arr->label_width = max(arr->label_width, width); + } + } + + return 0; +} + int scene_arrange(struct scene *scn) { + struct expo_arrange_info arr; struct scene_obj *obj; int ret;
+ ret = scene_calc_arrange(scn, &arr); + if (ret < 0) + return log_msg_ret("arr", ret); + list_for_each_entry(obj, &scn->obj_head, sibling) { switch (obj->type) { case SCENEOBJT_NONE: @@ -493,7 +541,7 @@ int scene_arrange(struct scene *scn) struct scene_obj_menu *menu;
menu = (struct scene_obj_menu *)obj, - ret = scene_menu_arrange(scn, menu); + ret = scene_menu_arrange(scn, &arr, menu); if (ret) return log_msg_ret("arr", ret); break; @@ -502,7 +550,7 @@ int scene_arrange(struct scene *scn) struct scene_obj_textline *tline;
tline = (struct scene_obj_textline *)obj, - ret = scene_textline_arrange(scn, tline); + ret = scene_textline_arrange(scn, &arr, tline); if (ret) return log_msg_ret("arr", ret); break; diff --git a/boot/scene_internal.h b/boot/scene_internal.h index e72202c98213..be25f6a8b967 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -96,10 +96,12 @@ int scene_calc_dims(struct scene *scn, bool do_menus); * if not already done * * @scn: Scene to update + * @arr: Arrangement information * @menu: Menu to process * Returns: 0 if OK, -ve on error */ -int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu); +int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr, + struct scene_obj_menu *menu);
/** * scene_textline_arrange() - Set the position of things in a textline @@ -108,10 +110,12 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu); * positioned correctly relative to the textline. * * @scn: Scene to update + * @arr: Arrangement information * @tline: textline to process * Returns: 0 if OK, -ve on error */ -int scene_textline_arrange(struct scene *scn, struct scene_obj_textline *tline); +int scene_textline_arrange(struct scene *scn, struct expo_arrange_info *arr, + struct scene_obj_textline *tline);
/** * scene_apply_theme() - Apply a theme to a scene @@ -358,4 +362,16 @@ int scene_textline_open(struct scene *scn, struct scene_obj_textline *tline); */ int scene_textline_close(struct scene *scn, struct scene_obj_textline *tline);
+/** + * scene_calc_arrange() - Calculate sizes needed to arrange a scene + * + * Checks the size of some objects and stores this info to help with a later + * scene arrangement + * + * @scn: Scene to check + * @arr: Place to put scene-arrangement info + * Returns: 0 if OK, -ve on error + */ +int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr); + #endif /* __SCENE_INTERNAL_H */ diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 63994165efba..dbf6eacb2983 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -169,7 +169,8 @@ int scene_menu_calc_dims(struct scene_obj_menu *menu) return 0; }
-int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) +int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr, + struct scene_obj_menu *menu) { const bool open = menu->obj.flags & SCENEOF_OPEN; struct expo *exp = scn->expo; @@ -183,16 +184,18 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) x = menu->obj.dim.x; y = menu->obj.dim.y; if (menu->title_id) { + int width; + ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.dim.x, y); if (ret < 0) return log_msg_ret("tit", ret);
- ret = scene_obj_get_hw(scn, menu->title_id, NULL); + ret = scene_obj_get_hw(scn, menu->title_id, &width); if (ret < 0) return log_msg_ret("hei", ret);
if (stack) - x += 200; + x += arr->label_width + theme->menu_title_margin_x; else y += ret * 2; } diff --git a/boot/scene_textline.c b/boot/scene_textline.c index 6ea072a1c268..576a402a688d 100644 --- a/boot/scene_textline.c +++ b/boot/scene_textline.c @@ -85,7 +85,8 @@ int scene_textline_calc_dims(struct scene_obj_textline *tline) return 0; }
-int scene_textline_arrange(struct scene *scn, struct scene_obj_textline *tline) +int scene_textline_arrange(struct scene *scn, struct expo_arrange_info *arr, + struct scene_obj_textline *tline) { const bool open = tline->obj.flags & SCENEOF_OPEN; bool point; diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index c87b6ec81285..f7b636e5fc62 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -176,6 +176,10 @@ menu-inset menuitem-gap-y Number of pixels between menu items
+menu-title-margin-x + Number of pixels between right side of menu title to the left size of the + menu labels + Pop-up mode -----------
diff --git a/include/expo.h b/include/expo.h index 3260703a7a01..4f62ee077e1f 100644 --- a/include/expo.h +++ b/include/expo.h @@ -59,11 +59,14 @@ struct expo_action { * @font_size: Default font size for all text * @menu_inset: Inset width (on each side and top/bottom) for menu items * @menuitem_gap_y: Gap between menu items in pixels + * @menu_title_margin_x: Gap between right side of menu title and left size of + * menu label */ struct expo_theme { u32 font_size; u32 menu_inset; u32 menuitem_gap_y; + u32 menu_title_margin_x; };
/** @@ -341,6 +344,15 @@ struct scene_obj_textline { uint pos; };
+/** + * struct expo_arrange_info - Information used when arranging a scene + * + * @label_width: Maximum width of labels in scene + */ +struct expo_arrange_info { + int label_width; +}; + /** * expo_new() - create a new expo *

If expo_set_dynamic_start() is never called, the first scene created will have an ID of 0, which is invalid. Correct this by setting a default value.
Add a test to check this.
Signed-off-by: Simon Glass sjg@chromium.org ---
boot/expo.c | 1 + test/boot/expo.c | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/boot/expo.c b/boot/expo.c index d030820e77ca..20ca0b9bfa0a 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -30,6 +30,7 @@ int expo_new(const char *name, void *priv, struct expo **expp) exp->priv = priv; INIT_LIST_HEAD(&exp->scene_head); INIT_LIST_HEAD(&exp->str_head); + exp->next_id = 1;
*expp = exp;
diff --git a/test/boot/expo.c b/test/boot/expo.c index 714fdfa415d1..8a84cbc71032 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -92,7 +92,7 @@ static int expo_base(struct unit_test_state *uts) *name = '\0'; ut_assertnonnull(exp); ut_asserteq(0, exp->scene_id); - ut_asserteq(0, exp->next_id); + ut_asserteq(1, exp->next_id);
/* Make sure the name was allocated */ ut_assertnonnull(exp->name); @@ -131,7 +131,7 @@ static int expo_scene(struct unit_test_state *uts) ut_assertok(expo_new(EXPO_NAME, NULL, &exp));
scn = NULL; - ut_asserteq(0, exp->next_id); + ut_asserteq(1, exp->next_id); strcpy(name, SCENE_NAME1); id = scene_new(exp, name, SCENE1, &scn); *name = '\0'; @@ -168,6 +168,25 @@ static int expo_scene(struct unit_test_state *uts) } BOOTSTD_TEST(expo_scene, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+/* Check creating a scene with no ID */ +static int expo_scene_no_id(struct unit_test_state *uts) +{ + struct scene *scn; + struct expo *exp; + char name[100]; + int id; + + ut_assertok(expo_new(EXPO_NAME, NULL, &exp)); + ut_asserteq(1, exp->next_id); + + strcpy(name, SCENE_NAME1); + id = scene_new(exp, SCENE_NAME1, 0, &scn); + ut_asserteq(1, scn->id); + + return 0; +} +BOOTSTD_TEST(expo_scene_no_id, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + /* Check creating a scene with objects */ static int expo_object(struct unit_test_state *uts) {

Set aside some expo IDs for 'save' and 'discard' buttons. This avoids needing to store the IDs for these. Adjust the documentation and expo tool for the new EXPOID_BASE_ID value.
Ignore these objects when saving and loading the cedit, since they do not contain real data.
Adjust 'cedit run' to return failure when the user exits the expo without saving. Update the test for this change as well.
Signed-off-by: Simon Glass sjg@chromium.org ---
boot/cedit.c | 24 +++++++++++++++++++++--- boot/expo.c | 2 +- doc/develop/cedit.rst | 7 ++++++- doc/develop/expo.rst | 12 ++++++++---- include/expo.h | 20 ++++++++++++++++++++ include/test/cedit-test.h | 30 +++++++++++++++--------------- test/boot/cedit.c | 14 ++++++++------ test/boot/expo.c | 8 ++++---- test/boot/files/expo_ids.h | 3 +-- tools/expo.py | 33 ++++++++++++++++++++++++++++----- 10 files changed, 112 insertions(+), 41 deletions(-)
diff --git a/boot/cedit.c b/boot/cedit.c index b5f89e945bce..a53a4f289906 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -155,7 +155,7 @@ int cedit_run(struct expo *exp) struct video_priv *vid_priv; uint scene_id; struct scene *scn; - bool done; + bool done, save; int ret;
cli_ch_init(cch); @@ -165,6 +165,7 @@ int cedit_run(struct expo *exp) scene_id = ret;
done = false; + save = false; do { struct expo_action act; int ichar, key; @@ -209,6 +210,15 @@ int cedit_run(struct expo *exp) case EXPOACT_OPEN: scene_set_open(scn, act.select.id, true); cedit_arange(exp, vid_priv, scene_id); + switch (scn->highlight_id) { + case EXPOID_SAVE: + done = true; + save = true; + break; + case EXPOID_DISCARD: + done = true; + break; + } break; case EXPOACT_CLOSE: scene_set_open(scn, act.select.id, false); @@ -230,6 +240,8 @@ int cedit_run(struct expo *exp)
if (ret) return log_msg_ret("end", ret); + if (!save) + return -EACCES;
return 0; } @@ -478,6 +490,9 @@ static int h_write_settings_env(struct scene_obj *obj, void *vpriv) const char *str; int val, ret;
+ if (obj->id < EXPOID_BASE_ID) + return 0; + snprintf(var, sizeof(var), "c.%s", obj->name);
switch (obj->type) { @@ -550,6 +565,9 @@ static int h_read_settings_env(struct scene_obj *obj, void *vpriv) char var[60]; int val;
+ if (obj->id < EXPOID_BASE_ID) + return 0; + snprintf(var, sizeof(var), "c.%s", obj->name);
switch (obj->type) { @@ -645,7 +663,7 @@ static int h_write_settings_cmos(struct scene_obj *obj, void *vpriv) int val, ret; uint i, seq;
- if (obj->type != SCENEOBJT_MENU) + if (obj->type != SCENEOBJT_MENU || obj->id < EXPOID_BASE_ID) return 0;
menu = (struct scene_obj_menu *)obj; @@ -735,7 +753,7 @@ static int h_read_settings_cmos(struct scene_obj *obj, void *vpriv) int val, ret; uint i;
- if (obj->type != SCENEOBJT_MENU) + if (obj->type != SCENEOBJT_MENU || obj->id < EXPOID_BASE_ID) return 0;
menu = (struct scene_obj_menu *)obj; diff --git a/boot/expo.c b/boot/expo.c index 20ca0b9bfa0a..2a1591cce6a4 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -30,7 +30,7 @@ int expo_new(const char *name, void *priv, struct expo **expp) exp->priv = priv; INIT_LIST_HEAD(&exp->scene_head); INIT_LIST_HEAD(&exp->str_head); - exp->next_id = 1; + exp->next_id = EXPOID_BASE_ID;
*expp = exp;
diff --git a/doc/develop/cedit.rst b/doc/develop/cedit.rst index 82305b921f0a..310be8892404 100644 --- a/doc/develop/cedit.rst +++ b/doc/develop/cedit.rst @@ -94,7 +94,7 @@ them. Expo supports doing this with an enum, where every ID is listed in the enum::
enum { - ZERO, + ID_PROMPT = EXPOID_BASE_ID,
ID_PROMPT,
@@ -130,6 +130,11 @@ that means that something is wrong with your syntax, or perhaps you have an ID in the `.dts` file that is not mentioned in your enum. Check both files and try again.
+Note that the first ID in your file must be no less that `EXPOID_BASE_ID` since +IDs before that are reserved. The `expo.py` tool automatically obtains this +value from the `expo.h` header file, but you must set the first ID to this +enum value. +
Use the command interface ------------------------- diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index f7b636e5fc62..d8115c463c1b 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -88,8 +88,13 @@ or even the IDs of objects. Programmatic creation of many items in a loop can be handled by allocating space in the enum for a maximum number of items, then adding the loop count to the enum values to obtain unique IDs.
-Where dynamic IDs are need, use expo_set_dynamic_start() to set the start value, -so that they are allocated above the starting (enum) IDs. +Some standard IDs are reserved for certain purposes. These are defined by +`enum expo_id_t` and start at 1. `EXPOID_BASE_ID` defines the first ID which +can be used for an expo. + +An ID of 0 is invalid. If this is specified in an expo call then a valid +'dynamic IDs is allocated. Use expo_set_dynamic_start() to set the start +value, so that they are allocated above the starting (enum) IDs.
All text strings are stored in a structure attached to the expo, referenced by a text ID. This makes it easier at some point to implement multiple languages or @@ -417,8 +422,7 @@ strings are provided inline in the nodes where they are used. /* this comment is parsed by the expo.py tool to insert the values below
enum { - ZERO, - ID_PROMPT, + ID_PROMPT = EXPOID_BASE_ID, ID_SCENE1, ID_SCENE1_TITLE,
diff --git a/include/expo.h b/include/expo.h index 4f62ee077e1f..4198c96adaa6 100644 --- a/include/expo.h +++ b/include/expo.h @@ -15,6 +15,26 @@ struct udevice;
#include <cli.h>
+/** + * enum expo_id_t - standard expo IDs + * + * These are assumed to be in use at all times. Expos should use IDs starting + * from EXPOID_BASE_ID, + * + * @EXPOID_NONE: Not used, invalid ID 0 + * @EXPOID_SAVE: User has requested that the expo data be saved + * @EXPOID_DISCARD: User has requested that the expo data be discarded + * @EXPOID_BASE_ID: First ID which can be used for expo objects + */ +enum expo_id_t { + EXPOID_NONE, + + EXPOID_SAVE, + EXPOID_DISCARD, + + EXPOID_BASE_ID = 5, +}; + /** * enum expoact_type - types of actions reported by the expo * diff --git a/include/test/cedit-test.h b/include/test/cedit-test.h index 475ecc9c2dc2..0d38a9534156 100644 --- a/include/test/cedit-test.h +++ b/include/test/cedit-test.h @@ -9,24 +9,24 @@ #ifndef __cedit_test_h #define __cedit_test_h
-#define ID_PROMPT 1 -#define ID_SCENE1 2 -#define ID_SCENE1_TITLE 3 +#define ID_PROMPT 5 +#define ID_SCENE1 6 +#define ID_SCENE1_TITLE 7
-#define ID_CPU_SPEED 4 -#define ID_CPU_SPEED_TITLE 5 -#define ID_CPU_SPEED_1 6 -#define ID_CPU_SPEED_2 7 -#define ID_CPU_SPEED_3 8 +#define ID_CPU_SPEED 8 +#define ID_CPU_SPEED_TITLE 9 +#define ID_CPU_SPEED_1 10 +#define ID_CPU_SPEED_2 11 +#define ID_CPU_SPEED_3 12
-#define ID_POWER_LOSS 9 -#define ID_AC_OFF 10 -#define ID_AC_ON 11 -#define ID_AC_MEMORY 12 +#define ID_POWER_LOSS 13 +#define ID_AC_OFF 14 +#define ID_AC_ON 15 +#define ID_AC_MEMORY 16
-#define ID_MACHINE_NAME 13 -#define ID_MACHINE_NAME_EDIT 14 +#define ID_MACHINE_NAME 17 +#define ID_MACHINE_NAME_EDIT 18
-#define ID_DYNAMIC_START 15 +#define ID_DYNAMIC_START 19
#endif diff --git a/test/boot/cedit.c b/test/boot/cedit.c index aa4171904864..37807f9a9818 100644 --- a/test/boot/cedit.c +++ b/test/boot/cedit.c @@ -34,9 +34,11 @@ static int cedit_base(struct unit_test_state *uts) * ^N Move down to second item * ^M Select item * \e Quit + * + * cedit_run() returns -EACCESS so this command returns CMD_RET_FAILURE */ console_in_puts("\x0e\x0d\x0e\x0d\e"); - ut_assertok(run_command("cedit run", 0)); + ut_asserteq(1, run_command("cedit run", 0));
exp = cur_exp; scn = expo_lookup_scene_id(exp, exp->scene_id); @@ -152,14 +154,14 @@ static int cedit_env(struct unit_test_state *uts) strcpy(str, "my-machine");
ut_assertok(run_command("cedit write_env -v", 0)); - ut_assert_nextlinen("c.cpu-speed=7"); + ut_assert_nextlinen("c.cpu-speed=11"); ut_assert_nextlinen("c.cpu-speed-str=2.5 GHz"); - ut_assert_nextlinen("c.power-loss=10"); + ut_assert_nextlinen("c.power-loss=14"); ut_assert_nextlinen("c.power-loss-str=Always Off"); ut_assert_nextlinen("c.machine-name=my-machine"); ut_assert_console_end();
- ut_asserteq(7, env_get_ulong("c.cpu-speed", 10, 0)); + ut_asserteq(11, env_get_ulong("c.cpu-speed", 10, 0)); ut_asserteq_str("2.5 GHz", env_get("c.cpu-speed-str")); ut_asserteq_str("my-machine", env_get("c.machine-name"));
@@ -168,8 +170,8 @@ static int cedit_env(struct unit_test_state *uts) *str = '\0';
ut_assertok(run_command("cedit read_env -v", 0)); - ut_assert_nextlinen("c.cpu-speed=7"); - ut_assert_nextlinen("c.power-loss=10"); + ut_assert_nextlinen("c.cpu-speed=11"); + ut_assert_nextlinen("c.power-loss=14"); ut_assert_nextlinen("c.machine-name=my-machine"); ut_assert_console_end();
diff --git a/test/boot/expo.c b/test/boot/expo.c index 8a84cbc71032..2e8acac07313 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -92,7 +92,7 @@ static int expo_base(struct unit_test_state *uts) *name = '\0'; ut_assertnonnull(exp); ut_asserteq(0, exp->scene_id); - ut_asserteq(1, exp->next_id); + ut_asserteq(EXPOID_BASE_ID, exp->next_id);
/* Make sure the name was allocated */ ut_assertnonnull(exp->name); @@ -131,7 +131,7 @@ static int expo_scene(struct unit_test_state *uts) ut_assertok(expo_new(EXPO_NAME, NULL, &exp));
scn = NULL; - ut_asserteq(1, exp->next_id); + ut_asserteq(EXPOID_BASE_ID, exp->next_id); strcpy(name, SCENE_NAME1); id = scene_new(exp, name, SCENE1, &scn); *name = '\0'; @@ -177,11 +177,11 @@ static int expo_scene_no_id(struct unit_test_state *uts) int id;
ut_assertok(expo_new(EXPO_NAME, NULL, &exp)); - ut_asserteq(1, exp->next_id); + ut_asserteq(EXPOID_BASE_ID, exp->next_id);
strcpy(name, SCENE_NAME1); id = scene_new(exp, SCENE_NAME1, 0, &scn); - ut_asserteq(1, scn->id); + ut_asserteq(EXPOID_BASE_ID, scn->id);
return 0; } diff --git a/test/boot/files/expo_ids.h b/test/boot/files/expo_ids.h index a86e0d06f6b5..ffb511364b1f 100644 --- a/test/boot/files/expo_ids.h +++ b/test/boot/files/expo_ids.h @@ -4,8 +4,7 @@ */
enum { - ZERO, - ID_PROMPT, + ID_PROMPT = EXPOID_BASE_ID,
ID_SCENE1, ID_SCENE1_TITLE, diff --git a/tools/expo.py b/tools/expo.py index ea80c70f04e3..44995f28a382 100755 --- a/tools/expo.py +++ b/tools/expo.py @@ -20,17 +20,22 @@ from u_boot_pylib import tools
# Parse: # SCENE1 = 7, +# or SCENE1 = EXPOID_BASE_ID, # or SCENE2, -RE_ENUM = re.compile(r'(\S*)(\s*= (\d))?,') +RE_ENUM = re.compile(r'(\S*)(\s*= ([0-9A-Z_]+))?,')
# Parse #define <name> "string" RE_DEF = re.compile(r'#define (\S*)\s*"(.*)"')
-def calc_ids(fname): +# Parse EXPOID_BASE_ID = 5, +RE_BASE_ID = re.compile(r'\s*EXPOID_BASE_ID\s*= (\d+),') + +def calc_ids(fname, base_id): """Figure out the value of the enums in a C file
Args: fname (str): Filename to parse + base_id (int): Base ID (value of EXPOID_BASE_ID)
Returns: OrderedDict(): @@ -55,8 +60,12 @@ def calc_ids(fname): if not line or line.startswith('/*'): continue m_enum = RE_ENUM.match(line) - if m_enum.group(3): - cur_id = int(m_enum.group(3)) + enum_name = m_enum.group(3) + if enum_name: + if enum_name == 'EXPOID_BASE_ID': + cur_id = base_id + else: + cur_id = int(enum_name) vals[m_enum.group(1)] = cur_id cur_id += 1 else: @@ -67,10 +76,24 @@ def calc_ids(fname): return vals
+def find_base_id(): + fname = 'include/expo.h' + base_id = None + with open(fname, 'r', encoding='utf-8') as inf: + for line in inf.readlines(): + m_base_id = RE_BASE_ID.match(line) + if m_base_id: + base_id = int(m_base_id.group(1)) + if base_id is None: + raise ValueError('EXPOID_BASE_ID not found in expo.h') + #print(f'EXPOID_BASE_ID={base_id}') + return base_id + def run_expo(args): """Run the expo program""" + base_id = find_base_id() fname = args.enum_fname or args.layout - ids = calc_ids(fname) + ids = calc_ids(fname, base_id) if not ids: print(f"Warning: No enum ID values found in file '{fname}'")

At present menu items are stored according to their sequence number in the menu. In some cases we may want to have holes in that sequence, or not use a sequence at all.
Add a new 'value' property for menu items. This will be used for reading and writing, if present. If there is no 'value' property, then the normal sequence number will be used instead.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/sandbox/dts/cedit.dtsi | 3 +++ boot/expo_build.c | 16 ++++++++++++---- boot/scene_internal.h | 10 ++++++++++ boot/scene_menu.c | 17 +++++++++++++++++ doc/develop/expo.rst | 10 ++++++++++ include/expo.h | 2 ++ test/boot/expo.c | 1 + test/boot/files/expo_layout.dts | 3 +++ 8 files changed, 58 insertions(+), 4 deletions(-)
diff --git a/arch/sandbox/dts/cedit.dtsi b/arch/sandbox/dts/cedit.dtsi index 9bd84e629367..facd7a49befc 100644 --- a/arch/sandbox/dts/cedit.dtsi +++ b/arch/sandbox/dts/cedit.dtsi @@ -39,6 +39,9 @@ /* IDs for the menu items */ item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2 ID_CPU_SPEED_3>; + + /* values for the menu items */ + item-value = <0 3 6>; };
power-loss { diff --git a/boot/expo_build.c b/boot/expo_build.c index d66d619911df..24ec4fc542a7 100644 --- a/boot/expo_build.c +++ b/boot/expo_build.c @@ -228,10 +228,10 @@ static void list_strings(struct build_info *info) static int menu_build(struct build_info *info, ofnode node, struct scene *scn, uint id, struct scene_obj **objp) { + const u32 *item_ids, *item_values; struct scene_obj_menu *menu; + int ret, size, i, num_items; uint title_id, menu_id; - const u32 *item_ids; - int ret, size, i; const char *name;
name = ofnode_get_name(node); @@ -255,9 +255,15 @@ static int menu_build(struct build_info *info, ofnode node, struct scene *scn, return log_msg_ret("itm", -EINVAL); if (!size || size % sizeof(u32)) return log_msg_ret("isz", -EINVAL); - size /= sizeof(u32); + num_items = size / sizeof(u32);
- for (i = 0; i < size; i++) { + item_values = ofnode_read_prop(node, "item-value", &size); + if (item_values) { + if (size != num_items * sizeof(u32)) + return log_msg_ret("vsz", -EINVAL); + } + + for (i = 0; i < num_items; i++) { struct scene_menitem *item; uint label, key, desc;
@@ -281,6 +287,8 @@ static int menu_build(struct build_info *info, ofnode node, struct scene *scn, desc, 0, 0, &item); if (ret < 0) return log_msg_ret("mi", ret); + if (item_values) + item->value = fdt32_to_cpu(item_values[i]); } *objp = &menu->obj;
diff --git a/boot/scene_internal.h b/boot/scene_internal.h index be25f6a8b967..ec9008ea593b 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -281,6 +281,16 @@ struct scene_menitem *scene_menuitem_find(const struct scene_obj_menu *menu, struct scene_menitem *scene_menuitem_find_seq(const struct scene_obj_menu *menu, uint seq);
+/** + * scene_menuitem_find_val() - Find the menu item with a given value + * + * @menu: Menu to check + * @find_val: Value to look for + * Return: menu item if found, else NULL + */ +struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu, + int val); + /** * scene_bbox_union() - update bouding box with the demensions of an object * diff --git a/boot/scene_menu.c b/boot/scene_menu.c index dbf6eacb2983..002821ec1f59 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -62,6 +62,22 @@ struct scene_menitem *scene_menuitem_find_seq(const struct scene_obj_menu *menu, return NULL; }
+struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu, + int val) +{ + struct scene_menitem *item; + uint i; + + i = 0; + list_for_each_entry(item, &menu->item_head, sibling) { + if (item->value == val) + return item; + i++; + } + + return NULL; +} + /** * update_pointers() - Update the pointer object and handle highlights * @@ -417,6 +433,7 @@ int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id, item->desc_id = desc_id; item->preview_id = preview_id; item->flags = flags; + item->value = INT_MAX; list_add_tail(&item->sibling, &menu->item_head);
if (itemp) diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index d8115c463c1b..cc7c36173dbe 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -361,6 +361,13 @@ item-id Specifies the ID for each menu item. These are used for checking which item has been selected.
+item-value + type: u32 list, optional + + Specifies the value for each menu item. These are used for saving and + loading. If this is omitted the value is its position in the menu (0..n-1). + Valid values are positive and negative integers INT_MIN...(INT_MAX - 1). + item-label / item-label-id type: string list / u32 list, required
@@ -474,6 +481,9 @@ strings are provided inline in the nodes where they are used. /* IDs for the menu items */ item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2 ID_CPU_SPEED_3>; + + /* values for the menu items */ + item-value = <(-1) 3 6>; };
power-loss { diff --git a/include/expo.h b/include/expo.h index 4198c96adaa6..bb329b9776dd 100644 --- a/include/expo.h +++ b/include/expo.h @@ -330,6 +330,7 @@ enum scene_menuitem_flags_t { * @desc_id: ID of text object to use as the description text * @preview_id: ID of the preview object, or 0 if none * @flags: Flags for this item + * @value: Value for this item, or INT_MAX to use sequence * @sibling: Node to link this item to its siblings */ struct scene_menitem { @@ -340,6 +341,7 @@ struct scene_menitem { uint desc_id; uint preview_id; uint flags; + int value; struct list_head sibling; };
diff --git a/test/boot/expo.c b/test/boot/expo.c index 2e8acac07313..75f31fe66907 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -719,6 +719,7 @@ static int expo_test_build(struct unit_test_state *uts) ut_asserteq(0, item->desc_id); ut_asserteq(0, item->preview_id); ut_asserteq(0, item->flags); + ut_asserteq(0, item->value);
txt = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE); ut_asserteq_str("2 GHz", expo_get_str(exp, txt->str_id)); diff --git a/test/boot/files/expo_layout.dts b/test/boot/files/expo_layout.dts index bed552288f4c..ebe5adb27bbe 100644 --- a/test/boot/files/expo_layout.dts +++ b/test/boot/files/expo_layout.dts @@ -39,6 +39,9 @@ item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2 ID_CPU_SPEED_3>;
+ /* values for the menu items */ + item-value = <(-1) 3 6>; + start-bit = <0x400>; bit-length = <2>; };

Add some more logging in the CMOS read/write code. Tidy up a few comments while we are here.
Signed-off-by: Simon Glass sjg@chromium.org ---
boot/cedit.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/boot/cedit.c b/boot/cedit.c index a53a4f289906..cc1d5b763577 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -585,7 +585,7 @@ static int h_read_settings_env(struct scene_obj *obj, void *vpriv)
/* * note that no validation is done here, to make sure the ID is - * valid * and actually points to a menu item + * valid and actually points to a menu item */ menu->cur_item_id = val; break; @@ -719,6 +719,7 @@ int cedit_write_settings_cmos(struct expo *exp, struct udevice *dev, }
/* write the data to the RTC */ + log_debug("Writing CMOS\n"); first = CMOS_MAX_BYTES; last = -1; for (i = 0, count = 0; i < CMOS_MAX_BYTES; i++) { @@ -786,6 +787,7 @@ static int h_read_settings_cmos(struct scene_obj *obj, void *vpriv) }
/* update the current item */ + log_debug("look for menuitem value %d in menu %d\n", val, menu->obj.id); mi = scene_menuitem_find_seq(menu, val); if (!mi) return log_msg_ret("seq", -ENOENT); @@ -820,7 +822,7 @@ int cedit_read_settings_cmos(struct expo *exp, struct udevice *dev, goto done; }
- /* read the data to the RTC */ + /* indicate what bytes were read from the RTC */ first = CMOS_MAX_BYTES; last = -1; for (i = 0, count = 0; i < CMOS_MAX_BYTES; i++) {

Update the cedit read/write functions to support menu items with values.
Signed-off-by: Simon Glass sjg@chromium.org ---
boot/cedit.c | 148 +++++++++++++++++++++----------- boot/scene_menu.c | 2 +- doc/usage/cmd/cedit.rst | 15 +++- test/boot/cedit.c | 8 +- test/boot/files/expo_layout.dts | 4 +- 5 files changed, 117 insertions(+), 60 deletions(-)
diff --git a/boot/cedit.c b/boot/cedit.c index cc1d5b763577..7fc800940fbe 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -294,11 +294,49 @@ static int get_cur_menuitem_text(const struct scene_obj_menu *menu, return 0; }
+/** + * get_cur_menuitem_val() - Get the value of a menu's current item + * + * Obtains the value of the current item in the menu. If no value, then + * enumerates the items of a menu (0, 1, 2) and returns the sequence number of + * the currently selected item. If the first item is selected, this returns 0; + * if the second, 1; etc. + * + * @menu: Menu to check + * @valp: Returns current-item value / sequence number + * Return: 0 on success, else -ve error value + */ +static int get_cur_menuitem_val(const struct scene_obj_menu *menu, int *valp) +{ + const struct scene_menitem *mi; + int seq; + + seq = 0; + list_for_each_entry(mi, &menu->item_head, sibling) { + if (mi->id == menu->cur_item_id) { + *valp = mi->value == INT_MAX ? seq : mi->value; + return 0; + } + seq++; + } + + return log_msg_ret("nf", -ENOENT); +} + +/** + * write_dt_string() - Write a string to the devicetree, expanding if needed + * + * If this fails, it tries again after expanding the devicetree a little + * + * @buf: Buffer containing the devicetree + * @name: Property name to use + * @str: String value + * Return: 0 if OK, -EFAULT if something went horribly wrong + */ static int write_dt_string(struct abuf *buf, const char *name, const char *str) { int ret, i;
- /* write the text of the current item */ ret = -EAGAIN; for (i = 0; ret && i < 2; i++) { ret = fdt_property_string(abuf_data(buf), name, str); @@ -316,6 +354,38 @@ static int write_dt_string(struct abuf *buf, const char *name, const char *str) return 0; }
+/** + * write_dt_u32() - Write an int to the devicetree, expanding if needed + * + * If this fails, it tries again after expanding the devicetree a little + * + * @buf: Buffer containing the devicetree + * @name: Property name to use + * @lva: Integer value + * Return: 0 if OK, -EFAULT if something went horribly wrong + */ +static int write_dt_u32(struct abuf *buf, const char *name, uint val) +{ + int ret, i; + + /* write the text of the current item */ + ret = -EAGAIN; + for (i = 0; ret && i < 2; i++) { + ret = fdt_property_u32(abuf_data(buf), name, val); + if (!i) { + ret = check_space(ret, buf); + if (ret) + return log_msg_ret("rs2", -ENOMEM); + } + } + + /* this should not happen */ + if (ret) + return log_msg_ret("str", -EFAULT); + + return 0; +} + static int h_write_settings(struct scene_obj *obj, void *vpriv) { struct cedit_iter_priv *priv = vpriv; @@ -340,23 +410,21 @@ static int h_write_settings(struct scene_obj *obj, void *vpriv) const struct scene_obj_menu *menu; const char *str; char name[80]; - int i; + int val;
/* write the ID of the current item */ menu = (struct scene_obj_menu *)obj; - ret = -EAGAIN; - for (i = 0; ret && i < 2; i++) { - ret = fdt_property_u32(abuf_data(buf), obj->name, - menu->cur_item_id); - if (!i) { - ret = check_space(ret, buf); - if (ret) - return log_msg_ret("res", -ENOMEM); - } - } - /* this should not happen */ + ret = write_dt_u32(buf, obj->name, menu->cur_item_id); if (ret) - return log_msg_ret("wrt", -EFAULT); + return log_msg_ret("wrt", ret); + + snprintf(name, sizeof(name), "%s-value", obj->name); + ret = get_cur_menuitem_val(menu, &val); + if (ret < 0) + return log_msg_ret("cur", ret); + ret = write_dt_u32(buf, name, val); + if (ret) + return log_msg_ret("wr2", ret);
ret = get_cur_menuitem_text(menu, &str); if (ret) @@ -522,6 +590,14 @@ static int h_write_settings_env(struct scene_obj *obj, void *vpriv) ret = env_set(name, str); if (ret) return log_msg_ret("st2", ret); + + ret = get_cur_menuitem_val(menu, &val); + if (ret < 0) + return log_msg_ret("cur", ret); + snprintf(name, sizeof(name), "c.%s-value", obj->name); + if (priv->verbose) + printf("%s=%d\n", name, val); + break; case SCENEOBJT_TEXTLINE: { const struct scene_obj_textline *tline; @@ -625,43 +701,12 @@ int cedit_read_settings_env(struct expo *exp, bool verbose) return 0; }
-/** - * get_cur_menuitem_seq() - Get the sequence number of a menu's current item - * - * Enumerates the items of a menu (0, 1, 2) and returns the sequence number of - * the currently selected item. If the first item is selected, this returns 0; - * if the second, 1; etc. - * - * @menu: Menu to check - * Return: Sequence number on success, else -ve error value - */ -static int get_cur_menuitem_seq(const struct scene_obj_menu *menu) -{ - const struct scene_menitem *mi; - int seq, found; - - seq = 0; - found = -1; - list_for_each_entry(mi, &menu->item_head, sibling) { - if (mi->id == menu->cur_item_id) { - found = seq; - break; - } - seq++; - } - - if (found == -1) - return log_msg_ret("nf", -ENOENT); - - return found; -} - static int h_write_settings_cmos(struct scene_obj *obj, void *vpriv) { const struct scene_obj_menu *menu; struct cedit_iter_priv *priv = vpriv; int val, ret; - uint i, seq; + uint i;
if (obj->type != SCENEOBJT_MENU || obj->id < EXPOID_BASE_ID) return 0; @@ -669,11 +714,10 @@ static int h_write_settings_cmos(struct scene_obj *obj, void *vpriv) menu = (struct scene_obj_menu *)obj; val = menu->cur_item_id;
- ret = get_cur_menuitem_seq(menu); + ret = get_cur_menuitem_val(menu, &val); if (ret < 0) return log_msg_ret("cur", ret); - seq = ret; - log_debug("%s: seq=%d\n", menu->obj.name, seq); + log_debug("%s: val=%d\n", menu->obj.name, val);
/* figure out where to place this item */ if (!obj->bit_length) @@ -681,11 +725,11 @@ static int h_write_settings_cmos(struct scene_obj *obj, void *vpriv) if (obj->start_bit + obj->bit_length > CMOS_MAX_BITS) return log_msg_ret("bit", -E2BIG);
- for (i = 0; i < obj->bit_length; i++, seq >>= 1) { + for (i = 0; i < obj->bit_length; i++, val >>= 1) { uint bitnum = obj->start_bit + i;
priv->mask[CMOS_BYTE(bitnum)] |= 1 << CMOS_BIT(bitnum); - if (seq & 1) + if (val & 1) priv->value[CMOS_BYTE(bitnum)] |= BIT(CMOS_BIT(bitnum)); log_debug("bit %x %x %x\n", bitnum, priv->mask[CMOS_BYTE(bitnum)], @@ -788,7 +832,7 @@ static int h_read_settings_cmos(struct scene_obj *obj, void *vpriv)
/* update the current item */ log_debug("look for menuitem value %d in menu %d\n", val, menu->obj.id); - mi = scene_menuitem_find_seq(menu, val); + mi = scene_menuitem_find_val(menu, val); if (!mi) return log_msg_ret("seq", -ENOENT);
diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 002821ec1f59..86f5fd88804e 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -70,7 +70,7 @@ struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu,
i = 0; list_for_each_entry(item, &menu->item_head, sibling) { - if (item->value == val) + if (item->value == INT_MAX ? val == i : item->value == val) return item; i++; } diff --git a/doc/usage/cmd/cedit.rst b/doc/usage/cmd/cedit.rst index f415b48699ea..0f0cc26e74ba 100644 --- a/doc/usage/cmd/cedit.rst +++ b/doc/usage/cmd/cedit.rst @@ -104,8 +104,10 @@ That results in:: / { cedit-values { cpu-speed = <0x00000006>; + cpu-speed-value = <0x00000003>; cpu-speed-str = "2 GHz"; power-loss = <0x0000000a>; + power-loss-value = <0x00000000>; power-loss-str = "Always Off"; }; } @@ -115,16 +117,23 @@ That results in:: This shows settings being stored in the environment::
=> cedit write_env -v - c.cpu-speed=7 + c.cpu-speed=11 c.cpu-speed-str=2.5 GHz - c.power-loss=12 - c.power-loss-str=Memory + c.cpu-speed-value=3 + c.power-loss=14 + c.power-loss-str=Always Off + c.power-loss-value=0 + c.machine-name=my-machine + c.cpu-speed=11 + c.power-loss=14 + c.machine-name=my-machine => print ... c.cpu-speed=6 c.cpu-speed-str=2 GHz c.power-loss=10 c.power-loss-str=Always Off + c.machine-name=my-machine ...
=> cedit read_env -v diff --git a/test/boot/cedit.c b/test/boot/cedit.c index 37807f9a9818..876503befe0b 100644 --- a/test/boot/cedit.c +++ b/test/boot/cedit.c @@ -100,14 +100,16 @@ static int cedit_fdt(struct unit_test_state *uts)
ut_asserteq(ID_CPU_SPEED_2, ofnode_read_u32_default(node, "cpu-speed", 0)); + ut_asserteq(3, + ofnode_read_u32_default(node, "cpu-speed-value", 0)); ut_asserteq_str("2.5 GHz", ofnode_read_string(node, "cpu-speed-str")); ut_asserteq_str("my-machine", ofnode_read_string(node, "machine-name"));
- /* There should only be 5 properties */ + /* There should only be 7 properties */ for (i = 0, ofnode_first_property(node, &prop); ofprop_valid(&prop); i++, ofnode_next_property(&prop)) ; - ut_asserteq(5, i); + ut_asserteq(7, i);
ut_assert_console_end();
@@ -156,8 +158,10 @@ static int cedit_env(struct unit_test_state *uts) ut_assertok(run_command("cedit write_env -v", 0)); ut_assert_nextlinen("c.cpu-speed=11"); ut_assert_nextlinen("c.cpu-speed-str=2.5 GHz"); + ut_assert_nextlinen("c.cpu-speed-value=3"); ut_assert_nextlinen("c.power-loss=14"); ut_assert_nextlinen("c.power-loss-str=Always Off"); + ut_assert_nextlinen("c.power-loss-value=0"); ut_assert_nextlinen("c.machine-name=my-machine"); ut_assert_console_end();
diff --git a/test/boot/files/expo_layout.dts b/test/boot/files/expo_layout.dts index ebe5adb27bbe..9bc1e4950b96 100644 --- a/test/boot/files/expo_layout.dts +++ b/test/boot/files/expo_layout.dts @@ -40,10 +40,10 @@ ID_CPU_SPEED_3>;
/* values for the menu items */ - item-value = <(-1) 3 6>; + item-value = <0 3 6>;
start-bit = <0x400>; - bit-length = <2>; + bit-length = <3>; };
power-loss {

The scene_txt_str() function calls expo_str() so there is no need to call it beforehand. Drop this unnecessary code.
Signed-off-by: Simon Glass sjg@chromium.org ---
boot/expo_build.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-)
diff --git a/boot/expo_build.c b/boot/expo_build.c index 24ec4fc542a7..88b6f2ea7eb4 100644 --- a/boot/expo_build.c +++ b/boot/expo_build.c @@ -47,7 +47,6 @@ int add_txt_str(struct build_info *info, ofnode node, struct scene *scn, const char *find_name, uint obj_id) { const char *text; - uint str_id; int ret;
info->err_prop = find_name; @@ -68,12 +67,7 @@ int add_txt_str(struct build_info *info, ofnode node, struct scene *scn, return log_msg_ret("id", -EINVAL); }
- ret = expo_str(scn->expo, find_name, 0, text); - if (ret < 0) - return log_msg_ret("add", ret); - str_id = ret; - - ret = scene_txt_str(scn, find_name, obj_id, str_id, text, NULL); + ret = scene_txt_str(scn, find_name, obj_id, 0, text, NULL); if (ret < 0) return log_msg_ret("add", ret);
@@ -95,7 +89,6 @@ int add_txt_str_list(struct build_info *info, ofnode node, struct scene *scn, const char *find_name, int index, uint obj_id) { const char *text; - uint str_id; int ret;
ret = ofnode_read_string_index(node, find_name, index, &text); @@ -115,12 +108,7 @@ int add_txt_str_list(struct build_info *info, ofnode node, struct scene *scn, return log_msg_ret("id", -EINVAL); }
- ret = expo_str(scn->expo, find_name, 0, text); - if (ret < 0) - return log_msg_ret("add", ret); - str_id = ret; - - ret = scene_txt_str(scn, find_name, obj_id, str_id, text, NULL); + ret = scene_txt_str(scn, find_name, obj_id, 0, text, NULL); if (ret < 0) return log_msg_ret("add", ret);

This function is really just an assignment, so serves no useful purpose. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org ---
boot/expo_build.c | 4 ++-- boot/scene.c | 7 ------- include/expo.h | 9 --------- test/boot/expo.c | 2 +- 4 files changed, 3 insertions(+), 19 deletions(-)
diff --git a/boot/expo_build.c b/boot/expo_build.c index 88b6f2ea7eb4..b2a651a314b6 100644 --- a/boot/expo_build.c +++ b/boot/expo_build.c @@ -405,7 +405,7 @@ static int scene_build(struct build_info *info, ofnode scn_node, if (ret < 0) return log_msg_ret("tit", ret); title_id = ret; - scene_title_set(scn, title_id); + scn->title_id = title_id;
ret = add_txt_str(info, scn_node, scn, "prompt", 0); if (ret < 0) @@ -421,7 +421,7 @@ static int scene_build(struct build_info *info, ofnode scn_node, return 0; }
-int build_it(struct build_info *info, ofnode root, struct expo **expp) +static int build_it(struct build_info *info, ofnode root, struct expo **expp) { ofnode scenes, node; struct expo *exp; diff --git a/boot/scene.c b/boot/scene.c index 56569e76e9f2..1369bcda13b8 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -71,13 +71,6 @@ void scene_destroy(struct scene *scn) free(scn); }
-int scene_title_set(struct scene *scn, uint id) -{ - scn->title_id = id; - - return 0; -} - int scene_obj_count(struct scene *scn) { struct scene_obj *obj; diff --git a/include/expo.h b/include/expo.h index bb329b9776dd..74b45606efe6 100644 --- a/include/expo.h +++ b/include/expo.h @@ -540,15 +540,6 @@ void scene_set_highlight_id(struct scene *scn, uint id); */ int scene_set_open(struct scene *scn, uint id, bool open);
-/** - * scene_title_set() - set the scene title - * - * @scn: Scene to update - * @title_id: Title ID to set - * Returns: 0 if OK - */ -int scene_title_set(struct scene *scn, uint title_id); - /** * scene_obj_count() - Count the number of objects in a scene * diff --git a/test/boot/expo.c b/test/boot/expo.c index 75f31fe66907..c7b8e9ba6749 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -152,7 +152,7 @@ static int expo_scene(struct unit_test_state *uts) scn = NULL; id = scene_new(exp, SCENE_NAME2, 0, &scn); ut_assertnonnull(scn); - ut_assertok(scene_title_set(scn, title_id)); + scn->title_id = title_id; ut_asserteq(STR_SCENE_TITLE + 1, id); ut_asserteq(STR_SCENE_TITLE + 2, exp->next_id); ut_asserteq_ptr(exp, scn->expo);

Some files may include this header file without first including dm.h so add a forward declaration.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/cedit.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/cedit.h b/include/cedit.h index f43cafa5aa24..f9a4a6d9e8eb 100644 --- a/include/cedit.h +++ b/include/cedit.h @@ -12,6 +12,7 @@ struct abuf; struct expo; struct scene; +struct udevice; struct video_priv;
enum {

Enable unit tests so we can run command-line tests in coreboot. Enable console recording, with enough space for the 'cbsysinfo' command. Add to the pre-relocation malloc() space to make room for this.
Signed-off-by: Simon Glass sjg@chromium.org ---
configs/coreboot_defconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig index 7d744e9962ae..5433a5ae0c2d 100644 --- a/configs/coreboot_defconfig +++ b/configs/coreboot_defconfig @@ -1,6 +1,7 @@ CONFIG_X86=y CONFIG_TEXT_BASE=0x1110000 CONFIG_SYS_MALLOC_LEN=0x2000000 +CONFIG_SYS_MALLOC_F_LEN=0x1000 CONFIG_NR_DRAM_BANKS=8 CONFIG_ENV_SIZE=0x1000 CONFIG_DEFAULT_DEVICE_TREE="coreboot" @@ -16,6 +17,8 @@ CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" CONFIG_BOOTCOMMAND="bootflow scan -l; if bootflow menu; then cls; bootflow boot; fi" +CONFIG_CONSOLE_RECORD=y +CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000 CONFIG_PRE_CONSOLE_BUFFER=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_LOG=y @@ -60,3 +63,4 @@ CONFIG_CONSOLE_SCROLL_LINES=5 CONFIG_CMD_DHRYSTONE=y # CONFIG_GZIP is not set CONFIG_SMBIOS_PARSER=y +CONFIG_UNIT_TEST=y

Update to a newer version which supports settings in CMOS RAM.
Signed-off-by: Simon Glass sjg@chromium.org ---
.azure-pipelines.yml | 2 +- .gitlab-ci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 421c5018b40b..83491e38f70c 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -255,7 +255,7 @@ stages: cp images/spi-nor.img ${UBOOT_TRAVIS_BUILD_DIR}/; fi if [[ "${TEST_PY_BD}" == "coreboot" ]]; then - wget -O - "https://drive.google.com/uc?id=1uJ2VkUQ8czWFZmhJQ90Tp8V_zrJ6BrBH&export=..." |xz -dc >${UBOOT_TRAVIS_BUILD_DIR}/coreboot.rom; + wget -O - "https://drive.google.com/uc?id=1RWzwnrha-wsj8WgO2XHByo7vttxb62pJ&export=..." |xz -dc >${UBOOT_TRAVIS_BUILD_DIR}/coreboot.rom; wget -O - "https://drive.google.com/uc?id=149Cz-5SZXHNKpi9xg6R_5XITWohu348y&export=..." >cbfstool; chmod a+x cbfstool; ./cbfstool ${UBOOT_TRAVIS_BUILD_DIR}/coreboot.rom add-flat-binary -f ${UBOOT_TRAVIS_BUILD_DIR}/u-boot.bin -n fallback/payload -c LZMA -l 0x1110000 -e 0x1110000; diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6efbd8021c8c..a9c2e578ce16 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -69,7 +69,7 @@ stages: fi - if [[ "${TEST_PY_BD}" == "coreboot" ]]; then wget -O - - "https://drive.google.com/uc?id=1uJ2VkUQ8czWFZmhJQ90Tp8V_zrJ6BrBH&export=..." | + "https://drive.google.com/uc?id=1RWzwnrha-wsj8WgO2XHByo7vttxb62pJ&export=..." | xz -dc >${UBOOT_TRAVIS_BUILD_DIR}/coreboot.rom; wget -O - "https://drive.google.com/uc?id=149Cz-5SZXHNKpi9xg6R_5XITWohu348y&export=..." >

Add a simple test for this command, checking that coreboot has the required features.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/cmd/Makefile | 1 + test/cmd/coreboot.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 test/cmd/coreboot.c
diff --git a/test/cmd/Makefile b/test/cmd/Makefile index 0be2cec89018..d6460b2ae5b9 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -14,6 +14,7 @@ endif obj-y += exit.o mem.o obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o obj-$(CONFIG_CMD_BDI) += bdinfo.o +obj-$(CONFIG_COREBOOT_SYSINFO) += coreboot.o obj-$(CONFIG_CMD_FDT) += fdt.o obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o obj-$(CONFIG_CMD_HISTORY) += history.o diff --git a/test/cmd/coreboot.c b/test/cmd/coreboot.c new file mode 100644 index 000000000000..277c670c15e9 --- /dev/null +++ b/test/cmd/coreboot.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for coreboot commands + * + * Copyright 2023 Google LLC + * Written by Simon Glass sjg@chromium.org + */ + +#include <common.h> +#include <command.h> +#include <test/cmd.h> +#include <test/test.h> +#include <test/ut.h> + +/** + * test_cmd_cbsysinfo() - test the cbsysinfo command produces expected output + * + * This includes ensuring that the coreboot build has the expected options + * enabled + */ +static int test_cmd_cbsysinfo(struct unit_test_state *uts) +{ + ut_assertok(run_command("cbsysinfo", 0)); + ut_assert_nextlinen("Coreboot table at"); + + /* Make sure the linear frame buffer is enabled */ + ut_assert_skip_to_linen("Framebuffer"); + ut_assert_nextlinen(" Phys addr"); + + ut_assert_skip_to_line("Chrome OS VPD: 00000000"); + ut_assert_nextlinen("RSDP"); + ut_assert_nextlinen("Unimpl."); + ut_assert_console_end(); + + return 0; +} +CMD_TEST(test_cmd_cbsysinfo, UT_TESTF_CONSOLE_REC);

Update the cbsysinfo command to show the contents of the CMOS option table.
While we are here, add some example output for this command, along with mention of what the unimplemented tags are.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/x86/cbsysinfo.c | 73 ++++++++++++++++++++++++++- doc/usage/cmd/cbsysinfo.rst | 99 +++++++++++++++++++++++++++++++++++++ test/cmd/coreboot.c | 7 +++ 3 files changed, 178 insertions(+), 1 deletion(-)
diff --git a/cmd/x86/cbsysinfo.c b/cmd/x86/cbsysinfo.c index 84822a3e3211..8c46203e1afa 100644 --- a/cmd/x86/cbsysinfo.c +++ b/cmd/x86/cbsysinfo.c @@ -185,6 +185,77 @@ static const char *timestamp_name(uint32_t id) return "<unknown>"; }
+static void show_option_vals(const struct cb_cmos_option_table *tab, + uint id) +{ + const void *ptr, *end; + bool found = false; + + end = (void *)tab + tab->size; + for (ptr = (void *)tab + tab->header_length; ptr < end;) { + const struct cb_record *rec = ptr; + + switch (rec->tag) { + case CB_TAG_OPTION_ENUM: { + const struct cb_cmos_enums *enums = ptr; + + if (enums->config_id == id) { + if (!found) + printf(" "); + printf(" %d:%s", enums->value, enums->text); + found = true; + } + break; + } + break; + case CB_TAG_OPTION_DEFAULTS: + case CB_TAG_OPTION_CHECKSUM: + case CB_TAG_OPTION: + break; + default: + printf("tag %x\n", rec->tag); + break; + } + ptr += rec->size; + } +} + +static void show_option_table(const struct cb_cmos_option_table *tab) +{ + const void *ptr, *end; + + print_ptr("option_table", tab); + if (!tab->size) + return; + + printf(" Bit Len Cfg ID Name\n"); + end = (void *)tab + tab->size; + for (ptr = (void *)tab + tab->header_length; ptr < end;) { + const struct cb_record *rec = ptr; + + switch (rec->tag) { + case CB_TAG_OPTION: { + const struct cb_cmos_entries *entry = ptr; + + printf("%4x %4x %3c %3x %-20s", entry->bit, + entry->length, entry->config, entry->config_id, + entry->name); + show_option_vals(tab, entry->config_id); + printf("\n"); + break; + } + case CB_TAG_OPTION_ENUM: + case CB_TAG_OPTION_DEFAULTS: + case CB_TAG_OPTION_CHECKSUM: + break; + default: + printf("tag %x\n", rec->tag); + break; + } + ptr += rec->size; + } +} + static void show_table(struct sysinfo_t *info, bool verbose) { struct cb_serial *ser = info->serial; @@ -219,7 +290,7 @@ static void show_table(struct sysinfo_t *info, bool verbose) printf("%12d: %02x:%-8s %016llx %016llx\n", i, mr->type, get_mem_name(mr->type), mr->base, mr->size); } - print_ptr("option_table", info->option_table); + show_option_table(info->option_table);
print_hex("CMOS start", info->cmos_range_start); if (info->cmos_range_start) { diff --git a/doc/usage/cmd/cbsysinfo.rst b/doc/usage/cmd/cbsysinfo.rst index 8c03a85169dc..ea6878e54232 100644 --- a/doc/usage/cmd/cbsysinfo.rst +++ b/doc/usage/cmd/cbsysinfo.rst @@ -23,3 +23,102 @@ Example ::
=> cbsysinfo + Coreboot table at 500, size 5c4, records 1d (dec 29), decoded to 000000007dce4520, forwarded to 000000007ff9a000 + + CPU KHz : 0 + Serial I/O port: 00000000 + base : 00000000 + pointer : 000000007ff9a370 + type : 1 + base : 000003f8 + baud : 0d115200 + regwidth : 1 + input_hz : 0d1843200 + PCI addr : 00000010 + Mem ranges : 7 + id: type || base || size + 0: 10:table 0000000000000000 0000000000001000 + 1: 01:ram 0000000000001000 000000000009f000 + 2: 02:reserved 00000000000a0000 0000000000060000 + 3: 01:ram 0000000000100000 000000007fe6d000 + 4: 10:table 000000007ff6d000 0000000000093000 + 5: 02:reserved 00000000fec00000 0000000000001000 + 6: 02:reserved 00000000ff800000 0000000000800000 + option_table: 000000007ff9a018 + Bit Len Cfg ID Name + 0 180 r 0 reserved_memory + 180 1 e 4 boot_option 0:Fallback 1:Normal + 184 4 h 0 reboot_counter + 190 8 r 0 reserved_century + 1b8 8 r 0 reserved_ibm_ps2_century + 1c0 1 e 1 power_on_after_fail 0:Disable 1:Enable + 1c4 4 e 6 debug_level 5:Notice 6:Info 7:Debug 8:Spew + 1d0 80 r 0 vbnv + 3f0 10 h 0 check_sum + CMOS start : 1c0 + CMOS end : 1cf + CMOS csum loc: 3f0 + VBNV start : ffffffff + VBNV size : ffffffff + CB version : 4.21-5-g7e6eae9679e3-dirty + Extra : + Build : Thu Sep 07 14:52:41 UTC 2023 + Time : 14:52:41 + Framebuffer : 000000007ff9a410 + Phys addr : fd000000 + X res : 0d800 + X res : 0d600 + Bytes / line: c80 + Bpp : 0d32 + pos/size red 16/8, green 8/8, blue 0/8, reserved 24/8 + GPIOs : 0 + id: port polarity val name + MACs : 0d10 + 0: 12:00:00:00:28:00 + 1: 00:00:00:fd:00:00 + 2: 20:03:00:00:58:02 + 3: 80:0c:00:00:20:10 + 4: 08:00:08:18:08:00 + 5: 16:00:00:00:10:00 + 6: 00:d0:fd:7f:00:00 + 7: 17:00:00:00:10:00 + 8: 00:e0:fd:7f:00:00 + 9: 37:00:00:00:10:00 + Multiboot tab: 0000000000000000 + CB header : 000000007ff9a000 + CB mainboard: 000000007ff9a344 + vendor : 0: Emulation + part_number : 10: QEMU x86 i440fx/piix4 + vboot handoff: 0000000000000000 + size : 0 + vdat addr : 0000000000000000 + size : 0 + SMBIOS : 7ff6d000 + size : 8000 + ROM MTRR : 0 + Tstamp table: 000000007ffdd000 + CBmem cons : 000000007ffde000 + Size : 1fff8 + Cursor : 3332 + MRC cache : 0000000000000000 + ACPI GNVS : 0000000000000000 + Board ID : ffffffff + RAM code : ffffffff + WiFi calib : 0000000000000000 + Ramoops buff: 0 + size : 0 + SF size : 0 + SF sector : 0 + SF erase cmd: 0 + FMAP offset : 0 + CBFS offset : 200 + CBFS size : 3ffe00 + Boot media size: 400000 + MTC start : 0 + MTC size : 0 + Chrome OS VPD: 0000000000000000 + RSDP : 000000007ff75000 + Unimpl. : 10 37 40 + => + +Note that "Unimpl." shows tags which U-Boot does not currently implement. diff --git a/test/cmd/coreboot.c b/test/cmd/coreboot.c index 277c670c15e9..eb3d8905986d 100644 --- a/test/cmd/coreboot.c +++ b/test/cmd/coreboot.c @@ -23,6 +23,13 @@ static int test_cmd_cbsysinfo(struct unit_test_state *uts) ut_assertok(run_command("cbsysinfo", 0)); ut_assert_nextlinen("Coreboot table at");
+ /* Make sure CMOS options are enabled */ + ut_assert_skip_to_line( + " 1c0 1 e 1 power_on_after_fail 0:Disable 1:Enable"); + ut_assert_skip_to_line("CMOS start : 1c0"); + ut_assert_nextline(" CMOS end : 1cf"); + ut_assert_nextline(" CMOS csum loc: 3f0"); + /* Make sure the linear frame buffer is enabled */ ut_assert_skip_to_linen("Framebuffer"); ut_assert_nextlinen(" Phys addr");

Enable cedit support along with required options and a simple style.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/coreboot.dts | 7 +++++++ configs/coreboot64_defconfig | 2 ++ configs/coreboot_defconfig | 2 ++ 3 files changed, 11 insertions(+)
diff --git a/arch/x86/dts/coreboot.dts b/arch/x86/dts/coreboot.dts index 83beb82f37c7..78ca00d64db4 100644 --- a/arch/x86/dts/coreboot.dts +++ b/arch/x86/dts/coreboot.dts @@ -54,5 +54,12 @@ menu-inset = <3>; menuitem-gap-y = <1>; }; + + cedit-theme { + font-size = <30>; + menu-inset = <3>; + menuitem-gap-y = <1>; + menu-title-margin-x = <30>; + }; }; }; diff --git a/configs/coreboot64_defconfig b/configs/coreboot64_defconfig index 42b46ba0d9b9..23b88b55663f 100644 --- a/configs/coreboot64_defconfig +++ b/configs/coreboot64_defconfig @@ -18,6 +18,7 @@ CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" CONFIG_BOOTCOMMAND="bootflow scan -l; if bootflow menu; then cls; bootflow boot; fi" +CONFIG_CEDIT=y CONFIG_PRE_CONSOLE_BUFFER=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_LOG=y @@ -47,6 +48,7 @@ CONFIG_TFTP_TSIZE=y CONFIG_USE_ROOTPATH=y CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_OFNODE_MULTI_TREE=y # CONFIG_ACPIGEN is not set CONFIG_SYS_IDE_MAXDEVICE=4 CONFIG_SYS_ATA_DATA_OFFSET=0 diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig index 5433a5ae0c2d..d4e44e00dcab 100644 --- a/configs/coreboot_defconfig +++ b/configs/coreboot_defconfig @@ -17,6 +17,7 @@ CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" CONFIG_BOOTCOMMAND="bootflow scan -l; if bootflow menu; then cls; bootflow boot; fi" +CONFIG_CEDIT=y CONFIG_CONSOLE_RECORD=y CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000 CONFIG_PRE_CONSOLE_BUFFER=y @@ -44,6 +45,7 @@ CONFIG_TFTP_TSIZE=y CONFIG_USE_ROOTPATH=y CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_OFNODE_MULTI_TREE=y # CONFIG_ACPIGEN is not set CONFIG_SYS_IDE_MAXDEVICE=4 CONFIG_SYS_ATA_DATA_OFFSET=0

Coreboot tables provide information about the CMOS-RAM checksum. Add a command which can check and update this.
With this it is possible to adjust CMOS-RAM settings and tidy up the checksum afterwards.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/Kconfig | 11 +++ cmd/x86/Makefile | 1 + cmd/x86/cbcmos.c | 141 +++++++++++++++++++++++++++++++++++++++ doc/usage/cmd/cbcmos.rst | 42 ++++++++++++ doc/usage/index.rst | 1 + test/cmd/coreboot.c | 42 ++++++++++++ 6 files changed, 238 insertions(+) create mode 100644 cmd/x86/cbcmos.c create mode 100644 doc/usage/cmd/cbcmos.rst
diff --git a/cmd/Kconfig b/cmd/Kconfig index 987f7d8cf623..e6977dc91bb2 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2742,6 +2742,17 @@ config CMD_CBSYSINFO memory by coreboot before jumping to U-Boot. It can be useful for debugging the beaaviour of coreboot or U-Boot.
+config CMD_CBCMOS + bool "cbcmos" + depends on X86 + default y if SYS_COREBOOT + help + This provides information options to check the CMOS RAM checksum, + if present, as well as to update it. + + It is useful when coreboot CMOS-RAM settings must be examined or + updated. + config CMD_CYCLIC bool "cyclic - Show information about cyclic functions" depends on CYCLIC diff --git a/cmd/x86/Makefile b/cmd/x86/Makefile index 5f82204c87e6..565e20776755 100644 --- a/cmd/x86/Makefile +++ b/cmd/x86/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0+
obj-$(CONFIG_CMD_CBSYSINFO) += cbsysinfo.o +obj-$(CONFIG_CMD_CBCMOS) += cbcmos.o obj-y += mtrr.o obj-$(CONFIG_CMD_EXCEPTION) += exception.o obj-$(CONFIG_USE_HOB) += hob.o diff --git a/cmd/x86/cbcmos.c b/cmd/x86/cbcmos.c new file mode 100644 index 000000000000..8d2f85fd0ec6 --- /dev/null +++ b/cmd/x86/cbcmos.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Support for booting from coreboot + * + * Copyright 2021 Google LLC + */ + +#define LOG_CATEGORY UCLASS_RTC + +#include <common.h> +#include <command.h> +#include <dm.h> +#include <rtc.h> +#include <asm/cb_sysinfo.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +const struct sysinfo_t *get_table(void) +{ + if (!gd->arch.coreboot_table) { + printf("No coreboot sysinfo table found\n"); + return NULL; + } + + return &lib_sysinfo; +} + +static int calc_sum(struct udevice *dev, uint start_bit, uint bit_count) +{ + uint start_byte = start_bit / 8; + uint byte_count = bit_count / 8; + int ret, i; + uint sum; + + log_debug("Calc sum from %x: %x bytes\n", start_byte, byte_count); + sum = 0; + for (i = 0; i < bit_count / 8; i++) { + ret = rtc_read8(dev, start_bit / 8 + i); + if (ret < 0) + return ret; + sum += ret; + } + + return (sum & 0xff) << 8 | (sum & 0xff00) >> 8; +} + +/** + * prep_cbcmos() - Prepare for a CMOS-RAM command + * + * @tab: coreboot table + * @devnum: RTC device name to use, or NULL for the first one + * @dep: Returns RTC device on success + * Return: calculated checksum for CMOS RAM or -ve on error + */ +static int prep_cbcmos(const struct sysinfo_t *tab, const char *devname, + struct udevice **devp) +{ + struct udevice *dev; + int ret; + + if (!tab) + return CMD_RET_FAILURE; + if (devname) + ret = uclass_get_device_by_name(UCLASS_RTC, devname, &dev); + else + ret = uclass_first_device_err(UCLASS_RTC, &dev); + if (ret) { + printf("Failed to get RTC device: %dE\n", ret); + return ret; + } + + ret = calc_sum(dev, tab->cmos_range_start, + tab->cmos_range_end + 1 - tab->cmos_range_start); + if (ret < 0) { + printf("Failed to read RTC device: %dE\n", ret); + return ret; + } + *devp = dev; + + return ret; +} + +static int do_cbcmos_check(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + const struct sysinfo_t *tab = get_table(); + struct udevice *dev; + u16 cur, sum; + int ret; + + ret = prep_cbcmos(tab, argv[1], &dev); + if (ret < 0) + return CMD_RET_FAILURE; + sum = ret; + + ret = rtc_read16(dev, tab->cmos_checksum_location / 8, &cur); + if (ret < 0) { + printf("Failed to read RTC device: %dE\n", ret); + return CMD_RET_FAILURE; + } + if (sum != cur) { + printf("Checksum %04x error: calculated %04x\n", cur, sum); + return CMD_RET_FAILURE; + } + + return 0; +} + +static int do_cbcmos_update(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + const struct sysinfo_t *tab = get_table(); + struct udevice *dev; + u16 sum; + int ret; + + ret = prep_cbcmos(tab, argv[1], &dev); + if (ret < 0) + return CMD_RET_FAILURE; + sum = ret; + + ret = rtc_write16(dev, tab->cmos_checksum_location / 8, sum); + if (ret < 0) { + printf("Failed to read RTC device: %dE\n", ret); + return CMD_RET_FAILURE; + } + printf("Checksum %04x written\n", sum); + + return 0; +} + +#ifdef CONFIG_SYS_LONGHELP +static char cbcmos_help_text[] = + "check - check CMOS RAM\n" + "cbcmos update - Update CMOS-RAM checksum"; +#endif /* CONFIG_SYS_LONGHELP */ + +U_BOOT_CMD_WITH_SUBCMDS(cbcmos, "coreboot CMOS RAM", cbcmos_help_text, + U_BOOT_SUBCMD_MKENT(check, 2, 1, do_cbcmos_check), + U_BOOT_SUBCMD_MKENT(update, 2, 1, do_cbcmos_update)); diff --git a/doc/usage/cmd/cbcmos.rst b/doc/usage/cmd/cbcmos.rst new file mode 100644 index 000000000000..156521dd02b9 --- /dev/null +++ b/doc/usage/cmd/cbcmos.rst @@ -0,0 +1,42 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +cbcmos +====== + +Synopis +------- + +:: + + cbcmos check [<dev>] + cbcmos update [<dev>] + + +Description +----------- + +This checks or updates the CMOS-RAM checksum value against the CMOS-RAM +contents. It is used with coreboot, which provides information about where to +find the checksum and what part of the CMOS RAM it covers. + +If `<dev>` is provided then the named real-time clock (RTC) device is used. +Otherwise the default RTC is used. + +Example +------- + +This shows checking and updating a checksum across bytes 38 and 39 of the +CMOS RAM:: + + => rtc read 38 2 + 00000038: 71 00 q. + => cbc check + => rtc write 38 66 + => rtc read 38 2 + 00000038: 66 00 f. + => cbc check + Checksum 7100 error: calculated 6600 + => cbc update + Checksum 6600 written + => cbc check + => diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 98b4719c4088..ae908e92327a 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -40,6 +40,7 @@ Shell commands cmd/button cmd/bootz cmd/cat + cmd/cbcmos cmd/cbsysinfo cmd/cedit cmd/cls diff --git a/test/cmd/coreboot.c b/test/cmd/coreboot.c index eb3d8905986d..0c49aca9f58a 100644 --- a/test/cmd/coreboot.c +++ b/test/cmd/coreboot.c @@ -8,10 +8,16 @@
#include <common.h> #include <command.h> +#include <dm.h> +#include <rtc.h> #include <test/cmd.h> #include <test/test.h> #include <test/ut.h>
+enum { + CSUM_LOC = 0x3f0 / 8, +}; + /** * test_cmd_cbsysinfo() - test the cbsysinfo command produces expected output * @@ -42,3 +48,39 @@ static int test_cmd_cbsysinfo(struct unit_test_state *uts) return 0; } CMD_TEST(test_cmd_cbsysinfo, UT_TESTF_CONSOLE_REC); + +/* test cbcmos command */ +static int test_cmd_cbcmos(struct unit_test_state *uts) +{ + u16 old_csum, new_csum; + struct udevice *dev; + + /* initially the checksum should be correct */ + ut_assertok(run_command("cbcmos check", 0)); + ut_assert_console_end(); + + /* make a change to the checksum */ + ut_assertok(uclass_first_device_err(UCLASS_RTC, &dev)); + ut_assertok(rtc_read16(dev, CSUM_LOC, &old_csum)); + ut_assertok(rtc_write16(dev, CSUM_LOC, old_csum + 1)); + + /* now the command should fail */ + ut_asserteq(1, run_command("cbcmos check", 0)); + ut_assert_nextline("Checksum %04x error: calculated %04x", + old_csum + 1, old_csum); + ut_assert_console_end(); + + /* now get it to fix the checksum */ + ut_assertok(run_command("cbcmos update", 0)); + ut_assert_nextline("Checksum %04x written", old_csum); + ut_assert_console_end(); + + /* check the RTC looks right */ + ut_assertok(rtc_read16(dev, CSUM_LOC, &new_csum)); + ut_asserteq(old_csum, new_csum); + ut_assert_console_end(); + + return 0; +} +CMD_TEST(test_cmd_cbcmos, UT_TESTF_CONSOLE_REC); +

Coreboot provides the CMOS layout in the tables it passes to U-Boot. Use that to build an editor for the CMOS settings.
Signed-off-by: Simon Glass sjg@chromium.org ---
boot/Makefile | 4 + boot/expo_build_cb.c | 244 ++++++++++++++++++++++++++++++++ cmd/cedit.c | 28 ++++ doc/board/coreboot/coreboot.rst | 6 + doc/develop/cedit.rst | 2 +- doc/usage/cmd/cbcmos.rst | 3 + doc/usage/cmd/cedit.rst | 76 ++++++++++ include/expo.h | 8 ++ test/cmd/coreboot.c | 34 +++++ 9 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 boot/expo_build_cb.c
diff --git a/boot/Makefile b/boot/Makefile index ad608598d298..7fd39833e5b6 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -59,6 +59,10 @@ endif obj-$(CONFIG_$(SPL_TPL_)EXPO) += expo.o scene.o expo_build.o obj-$(CONFIG_$(SPL_TPL_)EXPO) += scene_menu.o scene_textline.o
+ifdef CONFIG_COREBOOT_SYSINFO +obj-$(CONFIG_$(SPL_TPL_)EXPO) += expo_build_cb.o +endif + obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE) += vbe.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_REQUEST) += vbe_request.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE) += vbe_simple.o diff --git a/boot/expo_build_cb.c b/boot/expo_build_cb.c new file mode 100644 index 000000000000..88b74b090f00 --- /dev/null +++ b/boot/expo_build_cb.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Building an expo from an FDT description + * + * Copyright 2022 Google LLC + * Written by Simon Glass sjg@chromium.org + */ + +#define LOG_CATEGORY LOGC_EXPO + +#include <common.h> +#include <cedit.h> +#include <ctype.h> +#include <expo.h> +#include <log.h> +#include <malloc.h> +#include <asm/cb_sysinfo.h> + +/** + * struct build_info - Information to use when building + */ +struct build_info { + const struct cb_cmos_option_table *tab; + struct cedit_priv *priv; +}; + +/** + * convert_to_title() - Convert text to 'title' format and allocate a string + * + * Converts "this_is_a_test" to "This is a test" so it looks better + * + * @text: Text to convert + * Return: Allocated string, or NULL if out of memory + */ +static char *convert_to_title(const char *text) +{ + int len = strlen(text); + char *buf, *s; + + buf = malloc(len + 1); + if (!buf) + return NULL; + + for (s = buf; *text; s++, text++) { + if (s == buf) + *s = toupper(*text); + else if (*text == '_') + *s = ' '; + else + *s = *text; + } + *s = '\0'; + + return buf; +} + +/** + * menu_build() - Build a menu and add it to a scene + * + * See doc/developer/expo.rst for a description of the format + * + * @info: Build information + * @entry: CMOS entry to build a menu for + * @scn: Scene to add the menu to + * @objp: Returns the object pointer + * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format + * error, -ENOENT if there is a references to a non-existent string + */ +static int menu_build(struct build_info *info, + const struct cb_cmos_entries *entry, struct scene *scn, + struct scene_obj **objp) +{ + struct scene_obj_menu *menu; + const void *ptr, *end; + uint menu_id; + char *title; + int ret, i; + + ret = scene_menu(scn, entry->name, 0, &menu); + if (ret < 0) + return log_msg_ret("men", ret); + menu_id = ret; + + title = convert_to_title(entry->name); + if (!title) + return log_msg_ret("con", -ENOMEM); + + /* Set the title */ + ret = scene_txt_str(scn, "title", 0, 0, title, NULL); + if (ret < 0) + return log_msg_ret("tit", ret); + menu->title_id = ret; + + end = (void *)info->tab + info->tab->size; + for (ptr = (void *)info->tab + info->tab->header_length, i = 0; + ptr < end; i++) { + const struct cb_cmos_enums *enums = ptr; + struct scene_menitem *item; + uint label; + + ptr += enums->size; + if (enums->tag != CB_TAG_OPTION_ENUM || + enums->config_id != entry->config_id) + continue; + + ret = scene_txt_str(scn, enums->text, 0, 0, enums->text, NULL); + if (ret < 0) + return log_msg_ret("tit", ret); + label = ret; + + ret = scene_menuitem(scn, menu_id, simple_xtoa(i), 0, 0, label, + 0, 0, 0, &item); + if (ret < 0) + return log_msg_ret("mi", ret); + item->value = enums->value; + } + *objp = &menu->obj; + + return 0; +} + +/** + * scene_build() - Build a scene and all its objects + * + * See doc/developer/expo.rst for a description of the format + * + * @info: Build information + * @scn: Scene to add the object to + * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format + * error, -ENOENT if there is a references to a non-existent string + */ +static int scene_build(struct build_info *info, struct expo *exp) +{ + struct scene_obj_menu *menu; + const void *ptr, *end; + struct scene_obj *obj; + struct scene *scn; + uint label, menu_id; + int ret; + + ret = scene_new(exp, "cmos", 0, &scn); + if (ret < 0) + return log_msg_ret("scn", ret); + + ret = scene_txt_str(scn, "title", 0, 0, "CMOS RAM settings", NULL); + if (ret < 0) + return log_msg_ret("add", ret); + scn->title_id = ret; + + ret = scene_txt_str(scn, "prompt", 0, 0, + "UP and DOWN to choose, ENTER to select", NULL); + if (ret < 0) + return log_msg_ret("add", ret); + + end = (void *)info->tab + info->tab->size; + for (ptr = (void *)info->tab + info->tab->header_length; ptr < end;) { + const struct cb_cmos_entries *entry; + const struct cb_record *rec = ptr; + + entry = ptr; + ptr += rec->size; + if (rec->tag != CB_TAG_OPTION) + continue; + switch (entry->config) { + case 'e': + ret = menu_build(info, entry, scn, &obj); + break; + default: + continue; + } + if (ret < 0) + return log_msg_ret("add", ret); + + obj->start_bit = entry->bit; + obj->bit_length = entry->length; + } + + ret = scene_menu(scn, "save", EXPOID_SAVE, &menu); + if (ret < 0) + return log_msg_ret("men", ret); + menu_id = ret; + + ret = scene_txt_str(scn, "save", 0, 0, "Save and exit", NULL); + if (ret < 0) + return log_msg_ret("sav", ret); + label = ret; + ret = scene_menuitem(scn, menu_id, "save", 0, 0, label, + 0, 0, 0, NULL); + if (ret < 0) + return log_msg_ret("mi", ret); + + ret = scene_menu(scn, "nosave", EXPOID_DISCARD, &menu); + if (ret < 0) + return log_msg_ret("men", ret); + menu_id = ret; + + ret = scene_txt_str(scn, "nosave", 0, 0, "Exit without saving", NULL); + if (ret < 0) + return log_msg_ret("nos", ret); + label = ret; + ret = scene_menuitem(scn, menu_id, "exit", 0, 0, label, + 0, 0, 0, NULL); + if (ret < 0) + return log_msg_ret("mi", ret); + + return 0; +} + +static int build_it(struct build_info *info, struct expo **expp) +{ + struct expo *exp; + int ret; + + ret = expo_new("coreboot", NULL, &exp); + if (ret) + return log_msg_ret("exp", ret); + expo_set_dynamic_start(exp, EXPOID_BASE_ID); + + ret = scene_build(info, exp); + if (ret < 0) + return log_msg_ret("scn", ret); + + *expp = exp; + + return 0; +} + +int cb_expo_build(struct expo **expp) +{ + struct build_info info; + struct expo *exp; + int ret; + + info.tab = lib_sysinfo.option_table; + if (!info.tab) + return log_msg_ret("tab", -ENOENT); + + ret = build_it(&info, &exp); + if (ret) + return log_msg_ret("bui", ret); + *expp = exp; + + return 0; +} diff --git a/cmd/cedit.c b/cmd/cedit.c index 2ff284f4cde6..baa1d5cbadbb 100644 --- a/cmd/cedit.c +++ b/cmd/cedit.c @@ -68,6 +68,28 @@ static int do_cedit_load(struct cmd_tbl *cmdtp, int flag, int argc, return 0; }
+#ifdef CONFIG_COREBOOT_SYSINFO +static int do_cedit_cb_load(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct expo *exp; + int ret; + + if (argc > 1) + return CMD_RET_USAGE; + + ret = cb_expo_build(&exp); + if (ret) { + printf("Failed to build expo: %dE\n", ret); + return CMD_RET_FAILURE; + } + + cur_exp = exp; + + return 0; +} +#endif /* CONFIG_COREBOOT_SYSINFO */ + static int do_cedit_write_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -273,6 +295,9 @@ static int do_cedit_run(struct cmd_tbl *cmdtp, int flag, int argc, #ifdef CONFIG_SYS_LONGHELP static char cedit_help_text[] = "load <interface> <dev[:part]> <filename> - load config editor\n" +#ifdef CONFIG_COREBOOT_SYSINFO + "cb_load - load coreboot CMOS editor\n" +#endif "cedit read_fdt <i/f> <dev[:part]> <filename> - read settings\n" "cedit write_fdt <i/f> <dev[:part]> <filename> - write settings\n" "cedit read_env [-v] - read settings from env vars\n" @@ -284,6 +309,9 @@ static char cedit_help_text[] =
U_BOOT_CMD_WITH_SUBCMDS(cedit, "Configuration editor", cedit_help_text, U_BOOT_SUBCMD_MKENT(load, 5, 1, do_cedit_load), +#ifdef CONFIG_COREBOOT_SYSINFO + U_BOOT_SUBCMD_MKENT(cb_load, 5, 1, do_cedit_cb_load), +#endif U_BOOT_SUBCMD_MKENT(read_fdt, 5, 1, do_cedit_read_fdt), U_BOOT_SUBCMD_MKENT(write_fdt, 5, 1, do_cedit_write_fdt), U_BOOT_SUBCMD_MKENT(read_env, 2, 1, do_cedit_read_env), diff --git a/doc/board/coreboot/coreboot.rst b/doc/board/coreboot/coreboot.rst index 10a251c2b64f..f2c6452b5b94 100644 --- a/doc/board/coreboot/coreboot.rst +++ b/doc/board/coreboot/coreboot.rst @@ -195,3 +195,9 @@ To update the `coreboot.rom` file which is used: #. Upload the file to Google drive
#. Send a patch to change the file ID used by wget in the CI yaml files. + +Editing CMOS RAM settings +------------------------- + +U-Boot supports creating a configuration editor to edit coreboot CMOS-RAM +settings. See :ref:`cedit_cb_load`. diff --git a/doc/develop/cedit.rst b/doc/develop/cedit.rst index 310be8892404..1ac55ab1219b 100644 --- a/doc/develop/cedit.rst +++ b/doc/develop/cedit.rst @@ -172,4 +172,4 @@ Cedit provides several options for persistent settings:
For now, reading and writing settings is not automatic. See the :doc:`../usage/cmd/cedit` for how to do this on the command line or in a -script. +script. For x86 devices, see :ref:`cedit_cb_load`. diff --git a/doc/usage/cmd/cbcmos.rst b/doc/usage/cmd/cbcmos.rst index 156521dd02b9..9395cf1cbd71 100644 --- a/doc/usage/cmd/cbcmos.rst +++ b/doc/usage/cmd/cbcmos.rst @@ -40,3 +40,6 @@ CMOS RAM:: Checksum 6600 written => cbc check => + +See also :ref:`cedit_cb_load` which shows an example that includes the +configuration editor. diff --git a/doc/usage/cmd/cedit.rst b/doc/usage/cmd/cedit.rst index 0f0cc26e74ba..fbad0a9b1475 100644 --- a/doc/usage/cmd/cedit.rst +++ b/doc/usage/cmd/cedit.rst @@ -15,6 +15,7 @@ Synopis cedit write_env [-v] cedit read_env [-v] cedit write_cmos [-v] [dev] + cedit cb_load
Description ----------- @@ -89,6 +90,13 @@ updated. Normally the first RTC device is used to hold the data. You can specify a different device by name using the `dev` parameter.
+.. _cedit_cb_load: + +cedit cb_load +~~~~~~~~~~~~~ + +This is supported only on x86 devices booted from coreboot. It creates a new +configuration editor which can be used to edit CMOS settings.
Example ------- @@ -155,3 +163,71 @@ Here is an example with the device specified::
=> cedit write_cmos rtc@43 => + +This example shows editing coreboot CMOS-RAM settings. A script could be used +to automate this:: + + => cbsysinfo + Coreboot table at 500, size 5c4, records 1d (dec 29), decoded to 000000007dce3f40, forwarded to 000000007ff9a000 + + CPU KHz : 0 + Serial I/O port: 00000000 + base : 00000000 + pointer : 000000007ff9a370 + type : 1 + base : 000003f8 + baud : 0d115200 + regwidth : 1 + input_hz : 0d1843200 + PCI addr : 00000010 + Mem ranges : 7 + id: type || base || size + 0: 10:table 0000000000000000 0000000000001000 + 1: 01:ram 0000000000001000 000000000009f000 + 2: 02:reserved 00000000000a0000 0000000000060000 + 3: 01:ram 0000000000100000 000000007fe6d000 + 4: 10:table 000000007ff6d000 0000000000093000 + 5: 02:reserved 00000000fec00000 0000000000001000 + 6: 02:reserved 00000000ff800000 0000000000800000 + option_table: 000000007ff9a018 + Bit Len Cfg ID Name + 0 180 r 0 reserved_memory + 180 1 e 4 boot_option 0:Fallback 1:Normal + 184 4 h 0 reboot_counter + 190 8 r 0 reserved_century + 1b8 8 r 0 reserved_ibm_ps2_century + 1c0 1 e 1 power_on_after_fail 0:Disable 1:Enable + 1c4 4 e 6 debug_level 5:Notice 6:Info 7:Debug 8:Spew + 1d0 80 r 0 vbnv + 3f0 10 h 0 check_sum + CMOS start : 1c0 + CMOS end : 1cf + CMOS csum loc: 3f0 + VBNV start : ffffffff + VBNV size : ffffffff + ... + Unimpl. : 10 37 40 + +Check that the CMOS RAM checksum is correct, then create a configuration editor +and load the settings from CMOS RAM:: + + => cbcmos check + => cedit cb + => cedit read_cmos + +Now run the cedit. In this case the user selected 'save' so `cedit run` returns +success:: + + => if cedit run; then cedit write_cmos -v; fi + Write 2 bytes from offset 30 to 38 + => echo $? + 0 + +Update the checksum in CMOS RAM:: + + => cbcmos check + Checksum 6100 error: calculated 7100 + => cbcmos update + Checksum 7100 written + => cbcmos check + => diff --git a/include/expo.h b/include/expo.h index 74b45606efe6..19ee19b37430 100644 --- a/include/expo.h +++ b/include/expo.h @@ -762,4 +762,12 @@ int expo_apply_theme(struct expo *exp, ofnode node); */ int expo_build(ofnode root, struct expo **expp);
+/** + * cb_expo_build() - Build an expo for coreboot CMOS RAM + * + * @expp: Returns the expo created + * Return: 0 if OK, -ve on error + */ +int cb_expo_build(struct expo **expp); + #endif /*__EXPO_H */ diff --git a/test/cmd/coreboot.c b/test/cmd/coreboot.c index 0c49aca9f58a..72c3f10a92ae 100644 --- a/test/cmd/coreboot.c +++ b/test/cmd/coreboot.c @@ -7,12 +7,16 @@ */
#include <common.h> +#include <cedit.h> #include <command.h> #include <dm.h> +#include <expo.h> #include <rtc.h> +#include <test/cedit-test.h> #include <test/cmd.h> #include <test/test.h> #include <test/ut.h> +#include "../../boot/scene_internal.h"
enum { CSUM_LOC = 0x3f0 / 8, @@ -84,3 +88,33 @@ static int test_cmd_cbcmos(struct unit_test_state *uts) } CMD_TEST(test_cmd_cbcmos, UT_TESTF_CONSOLE_REC);
+/* test 'cedit cb_load' command */ +static int test_cmd_cedit_cb_load(struct unit_test_state *uts) +{ + struct scene_obj_menu *menu; + struct video_priv *vid_priv; + struct scene_obj_txt *txt; + struct scene *scn; + struct expo *exp; + int scn_id; + + ut_assertok(run_command("cedit cb_load", 0)); + ut_assertok(run_command("cedit read_cmos", 0)); + ut_assert_console_end(); + + exp = cur_exp; + scn_id = cedit_prepare(exp, &vid_priv, &scn); + ut_assert(scn_id > 0); + ut_assertnonnull(scn); + + /* just do a very basic test that the first menu is present */ + menu = scene_obj_find(scn, scn->highlight_id, SCENEOBJT_NONE); + ut_assertnonnull(menu); + + txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_NONE); + ut_assertnonnull(txt); + ut_asserteq_str("Boot option", expo_get_str(exp, txt->str_id)); + + return 0; +} +CMD_TEST(test_cmd_cedit_cb_load, UT_TESTF_CONSOLE_REC);

The real-time clock is needed for most X86 systems and it is useful to be able to read from it. Enable the rtc command by default.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/cmd/Kconfig b/cmd/Kconfig index e6977dc91bb2..080e104f9d76 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2164,6 +2164,7 @@ config CMD_DATE config CMD_RTC bool "rtc" depends on DM_RTC + default y if X86 help Enable the 'rtc' command for low-level access to RTC devices.

Hi Bin,
On Sun, 1 Oct 2023 at 19:16, Simon Glass sjg@chromium.org wrote:
U-Boot provides support for editing settings with an 'expo', as well as reading and writing settings to CMOS RAM.
This series integrates expo functionality with coreboot, using the sysinfo table to get a list of settings, creating an expo with them and allowing them to be edited.
A new CI test provides coverage for some coreboot-related commands. For this to work, a number of minor tweaks are made to existing tests, so that they pass on coreboot (x86) or at least are skipped when they cannot pass. Likely most of these fixes will apply to other boards too.
It includes several other fixes and improvements:
- new -m flag for 'bootflow scan' so it can display a menu automatically
- Fix for video-scrolling crash with Truetype
- menu items can now have individual integer values
- menu items are lined up according to the width of all menu labels
Simon Glass (34): test: Run tests that don't need devices test: Add a new suite for commands test: Add helper to skip to partial console line test: Make UT_LIB_ASN1 depend on sandbox test: Run bootstd tests only on sandbox test: Handle use of stack pointer in bdinfo test: bdinfo: Add missing asserts test: fdt: Add a special case for real boards test: font: Add dependencies on fonts test: event: Only run test_event_probe() on sandbox test: lmb: Move tests into the lib suite test: print: Skip test on x86 video: Add a function to clear the display sandbox: Add a dummy booti command bootstd: Add a menu option to bootflow scan video: Add a dark-grey console colour video: Avoid starting a new line to close to the bottom expo: Place menu items to the right of all labels expo: Set the initial next_id to 1 expo: Use standard numbering for save and discard expo: Allow menu items to have values expo: Add a little more cedit CMOS logging expo: Support menu-item values in cedit expo: Drop unneceesary calls to expo_str() expo: Drop scene_title_set() expo: Add forward declaration for udevice to cedit x86: coreboot: Enable unit tests x86: CI: Update coreboot x86: coreboot: Add a test for cbsysinfo command x86: coreboot: Show the option table x86: coreboot: Enable support for the configuration editor x86: coreboot: Add a command to check and update CMOS RAM x86: coreboot: Allow building an expo for editing CMOS config x86: Enable RTC command by default
.azure-pipelines.yml | 2 +- .gitlab-ci.yml | 2 +- arch/sandbox/dts/cedit.dtsi | 3 + arch/sandbox/lib/bootm.c | 7 + arch/x86/dts/coreboot.dts | 7 + boot/Makefile | 4 + boot/cedit.c | 191 +++++++++++++++-------- boot/expo.c | 3 + boot/expo_build.c | 36 ++--- boot/expo_build_cb.c | 244 ++++++++++++++++++++++++++++++ boot/scene.c | 61 ++++++-- boot/scene_internal.h | 30 +++- boot/scene_menu.c | 26 +++- boot/scene_textline.c | 3 +- cmd/Kconfig | 14 +- cmd/bootflow.c | 27 +++- cmd/booti.c | 2 +- cmd/cedit.c | 28 ++++ cmd/cls.c | 25 +-- cmd/x86/Makefile | 1 + cmd/x86/cbcmos.c | 141 +++++++++++++++++ cmd/x86/cbsysinfo.c | 73 ++++++++- common/console.c | 31 ++++ configs/coreboot64_defconfig | 2 + configs/coreboot_defconfig | 6 + configs/tools-only_defconfig | 3 +- doc/board/coreboot/coreboot.rst | 6 + doc/develop/cedit.rst | 9 +- doc/develop/expo.rst | 26 +++- doc/usage/cmd/bootflow.rst | 5 + doc/usage/cmd/cbcmos.rst | 45 ++++++ doc/usage/cmd/cbsysinfo.rst | 99 ++++++++++++ doc/usage/cmd/cedit.rst | 91 ++++++++++- doc/usage/index.rst | 1 + drivers/video/vidconsole-uclass.c | 4 +- drivers/video/video-uclass.c | 3 + include/cedit.h | 1 + include/console.h | 10 ++ include/expo.h | 51 +++++-- include/test/cedit-test.h | 30 ++-- include/test/cmd.h | 15 ++ include/test/suites.h | 1 + include/test/ut.h | 30 ++++ include/video.h | 4 +- include/video_console.h | 8 + test/Kconfig | 6 + test/Makefile | 2 +- test/boot/bootflow.c | 82 ++++++++++ test/boot/cedit.c | 22 ++- test/boot/expo.c | 26 +++- test/boot/files/expo_ids.h | 3 +- test/boot/files/expo_layout.dts | 5 +- test/cmd/Makefile | 3 + test/cmd/bdinfo.c | 23 ++- test/cmd/cmd_ut_cmd.c | 21 +++ test/cmd/coreboot.c | 120 +++++++++++++++ test/cmd/fdt.c | 8 +- test/cmd/font.c | 6 +- test/cmd_ut.c | 8 +- test/common/event.c | 3 + test/lib/lmb.c | 36 ++--- test/print_ut.c | 8 + test/test-main.c | 3 +- test/ut.c | 27 ++++ tools/expo.py | 33 +++- 65 files changed, 1640 insertions(+), 216 deletions(-) create mode 100644 boot/expo_build_cb.c create mode 100644 cmd/x86/cbcmos.c create mode 100644 doc/usage/cmd/cbcmos.rst create mode 100644 include/test/cmd.h create mode 100644 test/cmd/cmd_ut_cmd.c create mode 100644 test/cmd/coreboot.c
-- 2.42.0.582.g8ccd20d70d-goog
Any thoughts on this series, please?
Regards, Simon

Hi Simon,
On Wed, Nov 15, 2023 at 9:24 PM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Sun, 1 Oct 2023 at 19:16, Simon Glass sjg@chromium.org wrote:
U-Boot provides support for editing settings with an 'expo', as well as reading and writing settings to CMOS RAM.
This series integrates expo functionality with coreboot, using the sysinfo table to get a list of settings, creating an expo with them and allowing them to be edited.
A new CI test provides coverage for some coreboot-related commands. For this to work, a number of minor tweaks are made to existing tests, so that they pass on coreboot (x86) or at least are skipped when they cannot pass. Likely most of these fixes will apply to other boards too.
It includes several other fixes and improvements:
- new -m flag for 'bootflow scan' so it can display a menu automatically
- Fix for video-scrolling crash with Truetype
- menu items can now have individual integer values
- menu items are lined up according to the width of all menu labels
Simon Glass (34): test: Run tests that don't need devices test: Add a new suite for commands test: Add helper to skip to partial console line test: Make UT_LIB_ASN1 depend on sandbox test: Run bootstd tests only on sandbox test: Handle use of stack pointer in bdinfo test: bdinfo: Add missing asserts test: fdt: Add a special case for real boards test: font: Add dependencies on fonts test: event: Only run test_event_probe() on sandbox test: lmb: Move tests into the lib suite test: print: Skip test on x86 video: Add a function to clear the display sandbox: Add a dummy booti command bootstd: Add a menu option to bootflow scan video: Add a dark-grey console colour video: Avoid starting a new line to close to the bottom expo: Place menu items to the right of all labels expo: Set the initial next_id to 1 expo: Use standard numbering for save and discard expo: Allow menu items to have values expo: Add a little more cedit CMOS logging expo: Support menu-item values in cedit expo: Drop unneceesary calls to expo_str() expo: Drop scene_title_set() expo: Add forward declaration for udevice to cedit x86: coreboot: Enable unit tests x86: CI: Update coreboot x86: coreboot: Add a test for cbsysinfo command x86: coreboot: Show the option table x86: coreboot: Enable support for the configuration editor x86: coreboot: Add a command to check and update CMOS RAM x86: coreboot: Allow building an expo for editing CMOS config x86: Enable RTC command by default
.azure-pipelines.yml | 2 +- .gitlab-ci.yml | 2 +- arch/sandbox/dts/cedit.dtsi | 3 + arch/sandbox/lib/bootm.c | 7 + arch/x86/dts/coreboot.dts | 7 + boot/Makefile | 4 + boot/cedit.c | 191 +++++++++++++++-------- boot/expo.c | 3 + boot/expo_build.c | 36 ++--- boot/expo_build_cb.c | 244 ++++++++++++++++++++++++++++++ boot/scene.c | 61 ++++++-- boot/scene_internal.h | 30 +++- boot/scene_menu.c | 26 +++- boot/scene_textline.c | 3 +- cmd/Kconfig | 14 +- cmd/bootflow.c | 27 +++- cmd/booti.c | 2 +- cmd/cedit.c | 28 ++++ cmd/cls.c | 25 +-- cmd/x86/Makefile | 1 + cmd/x86/cbcmos.c | 141 +++++++++++++++++ cmd/x86/cbsysinfo.c | 73 ++++++++- common/console.c | 31 ++++ configs/coreboot64_defconfig | 2 + configs/coreboot_defconfig | 6 + configs/tools-only_defconfig | 3 +- doc/board/coreboot/coreboot.rst | 6 + doc/develop/cedit.rst | 9 +- doc/develop/expo.rst | 26 +++- doc/usage/cmd/bootflow.rst | 5 + doc/usage/cmd/cbcmos.rst | 45 ++++++ doc/usage/cmd/cbsysinfo.rst | 99 ++++++++++++ doc/usage/cmd/cedit.rst | 91 ++++++++++- doc/usage/index.rst | 1 + drivers/video/vidconsole-uclass.c | 4 +- drivers/video/video-uclass.c | 3 + include/cedit.h | 1 + include/console.h | 10 ++ include/expo.h | 51 +++++-- include/test/cedit-test.h | 30 ++-- include/test/cmd.h | 15 ++ include/test/suites.h | 1 + include/test/ut.h | 30 ++++ include/video.h | 4 +- include/video_console.h | 8 + test/Kconfig | 6 + test/Makefile | 2 +- test/boot/bootflow.c | 82 ++++++++++ test/boot/cedit.c | 22 ++- test/boot/expo.c | 26 +++- test/boot/files/expo_ids.h | 3 +- test/boot/files/expo_layout.dts | 5 +- test/cmd/Makefile | 3 + test/cmd/bdinfo.c | 23 ++- test/cmd/cmd_ut_cmd.c | 21 +++ test/cmd/coreboot.c | 120 +++++++++++++++ test/cmd/fdt.c | 8 +- test/cmd/font.c | 6 +- test/cmd_ut.c | 8 +- test/common/event.c | 3 + test/lib/lmb.c | 36 ++--- test/print_ut.c | 8 + test/test-main.c | 3 +- test/ut.c | 27 ++++ tools/expo.py | 33 +++- 65 files changed, 1640 insertions(+), 216 deletions(-) create mode 100644 boot/expo_build_cb.c create mode 100644 cmd/x86/cbcmos.c create mode 100644 doc/usage/cmd/cbcmos.rst create mode 100644 include/test/cmd.h create mode 100644 test/cmd/cmd_ut_cmd.c create mode 100644 test/cmd/coreboot.c
-- 2.42.0.582.g8ccd20d70d-goog
Any thoughts on this series, please?
applied patch#16-26 on u-boot-x86, thanks!
Would you please rebase patch#27-34?
Regards, Bin

Hi Bin,
On Sun, Dec 31, 2023 at 2:59 AM Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Nov 15, 2023 at 9:24 PM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Sun, 1 Oct 2023 at 19:16, Simon Glass sjg@chromium.org wrote:
U-Boot provides support for editing settings with an 'expo', as well as reading and writing settings to CMOS RAM.
This series integrates expo functionality with coreboot, using the sysinfo table to get a list of settings, creating an expo with them and allowing them to be edited.
A new CI test provides coverage for some coreboot-related commands. For this to work, a number of minor tweaks are made to existing tests, so that they pass on coreboot (x86) or at least are skipped when they cannot pass. Likely most of these fixes will apply to other boards too.
It includes several other fixes and improvements:
- new -m flag for 'bootflow scan' so it can display a menu automatically
- Fix for video-scrolling crash with Truetype
- menu items can now have individual integer values
- menu items are lined up according to the width of all menu labels
Simon Glass (34): test: Run tests that don't need devices test: Add a new suite for commands test: Add helper to skip to partial console line test: Make UT_LIB_ASN1 depend on sandbox test: Run bootstd tests only on sandbox test: Handle use of stack pointer in bdinfo test: bdinfo: Add missing asserts test: fdt: Add a special case for real boards test: font: Add dependencies on fonts test: event: Only run test_event_probe() on sandbox test: lmb: Move tests into the lib suite test: print: Skip test on x86 video: Add a function to clear the display sandbox: Add a dummy booti command bootstd: Add a menu option to bootflow scan video: Add a dark-grey console colour video: Avoid starting a new line to close to the bottom expo: Place menu items to the right of all labels expo: Set the initial next_id to 1 expo: Use standard numbering for save and discard expo: Allow menu items to have values expo: Add a little more cedit CMOS logging expo: Support menu-item values in cedit expo: Drop unneceesary calls to expo_str() expo: Drop scene_title_set() expo: Add forward declaration for udevice to cedit x86: coreboot: Enable unit tests x86: CI: Update coreboot x86: coreboot: Add a test for cbsysinfo command x86: coreboot: Show the option table x86: coreboot: Enable support for the configuration editor x86: coreboot: Add a command to check and update CMOS RAM x86: coreboot: Allow building an expo for editing CMOS config x86: Enable RTC command by default
.azure-pipelines.yml | 2 +- .gitlab-ci.yml | 2 +- arch/sandbox/dts/cedit.dtsi | 3 + arch/sandbox/lib/bootm.c | 7 + arch/x86/dts/coreboot.dts | 7 + boot/Makefile | 4 + boot/cedit.c | 191 +++++++++++++++-------- boot/expo.c | 3 + boot/expo_build.c | 36 ++--- boot/expo_build_cb.c | 244 ++++++++++++++++++++++++++++++ boot/scene.c | 61 ++++++-- boot/scene_internal.h | 30 +++- boot/scene_menu.c | 26 +++- boot/scene_textline.c | 3 +- cmd/Kconfig | 14 +- cmd/bootflow.c | 27 +++- cmd/booti.c | 2 +- cmd/cedit.c | 28 ++++ cmd/cls.c | 25 +-- cmd/x86/Makefile | 1 + cmd/x86/cbcmos.c | 141 +++++++++++++++++ cmd/x86/cbsysinfo.c | 73 ++++++++- common/console.c | 31 ++++ configs/coreboot64_defconfig | 2 + configs/coreboot_defconfig | 6 + configs/tools-only_defconfig | 3 +- doc/board/coreboot/coreboot.rst | 6 + doc/develop/cedit.rst | 9 +- doc/develop/expo.rst | 26 +++- doc/usage/cmd/bootflow.rst | 5 + doc/usage/cmd/cbcmos.rst | 45 ++++++ doc/usage/cmd/cbsysinfo.rst | 99 ++++++++++++ doc/usage/cmd/cedit.rst | 91 ++++++++++- doc/usage/index.rst | 1 + drivers/video/vidconsole-uclass.c | 4 +- drivers/video/video-uclass.c | 3 + include/cedit.h | 1 + include/console.h | 10 ++ include/expo.h | 51 +++++-- include/test/cedit-test.h | 30 ++-- include/test/cmd.h | 15 ++ include/test/suites.h | 1 + include/test/ut.h | 30 ++++ include/video.h | 4 +- include/video_console.h | 8 + test/Kconfig | 6 + test/Makefile | 2 +- test/boot/bootflow.c | 82 ++++++++++ test/boot/cedit.c | 22 ++- test/boot/expo.c | 26 +++- test/boot/files/expo_ids.h | 3 +- test/boot/files/expo_layout.dts | 5 +- test/cmd/Makefile | 3 + test/cmd/bdinfo.c | 23 ++- test/cmd/cmd_ut_cmd.c | 21 +++ test/cmd/coreboot.c | 120 +++++++++++++++ test/cmd/fdt.c | 8 +- test/cmd/font.c | 6 +- test/cmd_ut.c | 8 +- test/common/event.c | 3 + test/lib/lmb.c | 36 ++--- test/print_ut.c | 8 + test/test-main.c | 3 +- test/ut.c | 27 ++++ tools/expo.py | 33 +++- 65 files changed, 1640 insertions(+), 216 deletions(-) create mode 100644 boot/expo_build_cb.c create mode 100644 cmd/x86/cbcmos.c create mode 100644 doc/usage/cmd/cbcmos.rst create mode 100644 include/test/cmd.h create mode 100644 test/cmd/cmd_ut_cmd.c create mode 100644 test/cmd/coreboot.c
-- 2.42.0.582.g8ccd20d70d-goog
Any thoughts on this series, please?
applied patch#16-26 on u-boot-x86, thanks!
Would you please rebase patch#27-34?
The series is based on things applied to -next and it is a bit late for master. Can you try on that?
Regards, Simon

Hi Simon,
On Sun, Dec 31, 2023 at 8:43 PM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Sun, Dec 31, 2023 at 2:59 AM Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Nov 15, 2023 at 9:24 PM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Sun, 1 Oct 2023 at 19:16, Simon Glass sjg@chromium.org wrote:
U-Boot provides support for editing settings with an 'expo', as well as reading and writing settings to CMOS RAM.
This series integrates expo functionality with coreboot, using the sysinfo table to get a list of settings, creating an expo with them and allowing them to be edited.
A new CI test provides coverage for some coreboot-related commands. For this to work, a number of minor tweaks are made to existing tests, so that they pass on coreboot (x86) or at least are skipped when they cannot pass. Likely most of these fixes will apply to other boards too.
It includes several other fixes and improvements:
- new -m flag for 'bootflow scan' so it can display a menu automatically
- Fix for video-scrolling crash with Truetype
- menu items can now have individual integer values
- menu items are lined up according to the width of all menu labels
Simon Glass (34): test: Run tests that don't need devices test: Add a new suite for commands test: Add helper to skip to partial console line test: Make UT_LIB_ASN1 depend on sandbox test: Run bootstd tests only on sandbox test: Handle use of stack pointer in bdinfo test: bdinfo: Add missing asserts test: fdt: Add a special case for real boards test: font: Add dependencies on fonts test: event: Only run test_event_probe() on sandbox test: lmb: Move tests into the lib suite test: print: Skip test on x86 video: Add a function to clear the display sandbox: Add a dummy booti command bootstd: Add a menu option to bootflow scan video: Add a dark-grey console colour video: Avoid starting a new line to close to the bottom expo: Place menu items to the right of all labels expo: Set the initial next_id to 1 expo: Use standard numbering for save and discard expo: Allow menu items to have values expo: Add a little more cedit CMOS logging expo: Support menu-item values in cedit expo: Drop unneceesary calls to expo_str() expo: Drop scene_title_set() expo: Add forward declaration for udevice to cedit x86: coreboot: Enable unit tests x86: CI: Update coreboot x86: coreboot: Add a test for cbsysinfo command x86: coreboot: Show the option table x86: coreboot: Enable support for the configuration editor x86: coreboot: Add a command to check and update CMOS RAM x86: coreboot: Allow building an expo for editing CMOS config x86: Enable RTC command by default
.azure-pipelines.yml | 2 +- .gitlab-ci.yml | 2 +- arch/sandbox/dts/cedit.dtsi | 3 + arch/sandbox/lib/bootm.c | 7 + arch/x86/dts/coreboot.dts | 7 + boot/Makefile | 4 + boot/cedit.c | 191 +++++++++++++++-------- boot/expo.c | 3 + boot/expo_build.c | 36 ++--- boot/expo_build_cb.c | 244 ++++++++++++++++++++++++++++++ boot/scene.c | 61 ++++++-- boot/scene_internal.h | 30 +++- boot/scene_menu.c | 26 +++- boot/scene_textline.c | 3 +- cmd/Kconfig | 14 +- cmd/bootflow.c | 27 +++- cmd/booti.c | 2 +- cmd/cedit.c | 28 ++++ cmd/cls.c | 25 +-- cmd/x86/Makefile | 1 + cmd/x86/cbcmos.c | 141 +++++++++++++++++ cmd/x86/cbsysinfo.c | 73 ++++++++- common/console.c | 31 ++++ configs/coreboot64_defconfig | 2 + configs/coreboot_defconfig | 6 + configs/tools-only_defconfig | 3 +- doc/board/coreboot/coreboot.rst | 6 + doc/develop/cedit.rst | 9 +- doc/develop/expo.rst | 26 +++- doc/usage/cmd/bootflow.rst | 5 + doc/usage/cmd/cbcmos.rst | 45 ++++++ doc/usage/cmd/cbsysinfo.rst | 99 ++++++++++++ doc/usage/cmd/cedit.rst | 91 ++++++++++- doc/usage/index.rst | 1 + drivers/video/vidconsole-uclass.c | 4 +- drivers/video/video-uclass.c | 3 + include/cedit.h | 1 + include/console.h | 10 ++ include/expo.h | 51 +++++-- include/test/cedit-test.h | 30 ++-- include/test/cmd.h | 15 ++ include/test/suites.h | 1 + include/test/ut.h | 30 ++++ include/video.h | 4 +- include/video_console.h | 8 + test/Kconfig | 6 + test/Makefile | 2 +- test/boot/bootflow.c | 82 ++++++++++ test/boot/cedit.c | 22 ++- test/boot/expo.c | 26 +++- test/boot/files/expo_ids.h | 3 +- test/boot/files/expo_layout.dts | 5 +- test/cmd/Makefile | 3 + test/cmd/bdinfo.c | 23 ++- test/cmd/cmd_ut_cmd.c | 21 +++ test/cmd/coreboot.c | 120 +++++++++++++++ test/cmd/fdt.c | 8 +- test/cmd/font.c | 6 +- test/cmd_ut.c | 8 +- test/common/event.c | 3 + test/lib/lmb.c | 36 ++--- test/print_ut.c | 8 + test/test-main.c | 3 +- test/ut.c | 27 ++++ tools/expo.py | 33 +++- 65 files changed, 1640 insertions(+), 216 deletions(-) create mode 100644 boot/expo_build_cb.c create mode 100644 cmd/x86/cbcmos.c create mode 100644 doc/usage/cmd/cbcmos.rst create mode 100644 include/test/cmd.h create mode 100644 test/cmd/cmd_ut_cmd.c create mode 100644 test/cmd/coreboot.c
-- 2.42.0.582.g8ccd20d70d-goog
Any thoughts on this series, please?
applied patch#16-26 on u-boot-x86, thanks!
Would you please rebase patch#27-34?
The series is based on things applied to -next and it is a bit late for master. Can you try on that?
I tried that but it still fails at applying patch #27.
Regards, Bin

Hi Bin,
On Thu, Jan 4, 2024 at 5:06 AM Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Sun, Dec 31, 2023 at 8:43 PM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Sun, Dec 31, 2023 at 2:59 AM Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Nov 15, 2023 at 9:24 PM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Sun, 1 Oct 2023 at 19:16, Simon Glass sjg@chromium.org wrote:
U-Boot provides support for editing settings with an 'expo', as well as reading and writing settings to CMOS RAM.
This series integrates expo functionality with coreboot, using the sysinfo table to get a list of settings, creating an expo with them and allowing them to be edited.
A new CI test provides coverage for some coreboot-related commands. For this to work, a number of minor tweaks are made to existing tests, so that they pass on coreboot (x86) or at least are skipped when they cannot pass. Likely most of these fixes will apply to other boards too.
It includes several other fixes and improvements:
- new -m flag for 'bootflow scan' so it can display a menu automatically
- Fix for video-scrolling crash with Truetype
- menu items can now have individual integer values
- menu items are lined up according to the width of all menu labels
Simon Glass (34): test: Run tests that don't need devices test: Add a new suite for commands test: Add helper to skip to partial console line test: Make UT_LIB_ASN1 depend on sandbox test: Run bootstd tests only on sandbox test: Handle use of stack pointer in bdinfo test: bdinfo: Add missing asserts test: fdt: Add a special case for real boards test: font: Add dependencies on fonts test: event: Only run test_event_probe() on sandbox test: lmb: Move tests into the lib suite test: print: Skip test on x86 video: Add a function to clear the display sandbox: Add a dummy booti command bootstd: Add a menu option to bootflow scan video: Add a dark-grey console colour video: Avoid starting a new line to close to the bottom expo: Place menu items to the right of all labels expo: Set the initial next_id to 1 expo: Use standard numbering for save and discard expo: Allow menu items to have values expo: Add a little more cedit CMOS logging expo: Support menu-item values in cedit expo: Drop unneceesary calls to expo_str() expo: Drop scene_title_set() expo: Add forward declaration for udevice to cedit x86: coreboot: Enable unit tests x86: CI: Update coreboot x86: coreboot: Add a test for cbsysinfo command x86: coreboot: Show the option table x86: coreboot: Enable support for the configuration editor x86: coreboot: Add a command to check and update CMOS RAM x86: coreboot: Allow building an expo for editing CMOS config x86: Enable RTC command by default
.azure-pipelines.yml | 2 +- .gitlab-ci.yml | 2 +- arch/sandbox/dts/cedit.dtsi | 3 + arch/sandbox/lib/bootm.c | 7 + arch/x86/dts/coreboot.dts | 7 + boot/Makefile | 4 + boot/cedit.c | 191 +++++++++++++++-------- boot/expo.c | 3 + boot/expo_build.c | 36 ++--- boot/expo_build_cb.c | 244 ++++++++++++++++++++++++++++++ boot/scene.c | 61 ++++++-- boot/scene_internal.h | 30 +++- boot/scene_menu.c | 26 +++- boot/scene_textline.c | 3 +- cmd/Kconfig | 14 +- cmd/bootflow.c | 27 +++- cmd/booti.c | 2 +- cmd/cedit.c | 28 ++++ cmd/cls.c | 25 +-- cmd/x86/Makefile | 1 + cmd/x86/cbcmos.c | 141 +++++++++++++++++ cmd/x86/cbsysinfo.c | 73 ++++++++- common/console.c | 31 ++++ configs/coreboot64_defconfig | 2 + configs/coreboot_defconfig | 6 + configs/tools-only_defconfig | 3 +- doc/board/coreboot/coreboot.rst | 6 + doc/develop/cedit.rst | 9 +- doc/develop/expo.rst | 26 +++- doc/usage/cmd/bootflow.rst | 5 + doc/usage/cmd/cbcmos.rst | 45 ++++++ doc/usage/cmd/cbsysinfo.rst | 99 ++++++++++++ doc/usage/cmd/cedit.rst | 91 ++++++++++- doc/usage/index.rst | 1 + drivers/video/vidconsole-uclass.c | 4 +- drivers/video/video-uclass.c | 3 + include/cedit.h | 1 + include/console.h | 10 ++ include/expo.h | 51 +++++-- include/test/cedit-test.h | 30 ++-- include/test/cmd.h | 15 ++ include/test/suites.h | 1 + include/test/ut.h | 30 ++++ include/video.h | 4 +- include/video_console.h | 8 + test/Kconfig | 6 + test/Makefile | 2 +- test/boot/bootflow.c | 82 ++++++++++ test/boot/cedit.c | 22 ++- test/boot/expo.c | 26 +++- test/boot/files/expo_ids.h | 3 +- test/boot/files/expo_layout.dts | 5 +- test/cmd/Makefile | 3 + test/cmd/bdinfo.c | 23 ++- test/cmd/cmd_ut_cmd.c | 21 +++ test/cmd/coreboot.c | 120 +++++++++++++++ test/cmd/fdt.c | 8 +- test/cmd/font.c | 6 +- test/cmd_ut.c | 8 +- test/common/event.c | 3 + test/lib/lmb.c | 36 ++--- test/print_ut.c | 8 + test/test-main.c | 3 +- test/ut.c | 27 ++++ tools/expo.py | 33 +++- 65 files changed, 1640 insertions(+), 216 deletions(-) create mode 100644 boot/expo_build_cb.c create mode 100644 cmd/x86/cbcmos.c create mode 100644 doc/usage/cmd/cbcmos.rst create mode 100644 include/test/cmd.h create mode 100644 test/cmd/cmd_ut_cmd.c create mode 100644 test/cmd/coreboot.c
-- 2.42.0.582.g8ccd20d70d-goog
Any thoughts on this series, please?
applied patch#16-26 on u-boot-x86, thanks!
Would you please rebase patch#27-34?
The series is based on things applied to -next and it is a bit late for master. Can you try on that?
I tried that but it still fails at applying patch #27.
I think you are missing the prior series[1]. I will resent both, rebased to -next
Regards, Simon
[1] https://patchwork.ozlabs.org/project/uboot/list/?series=382863
participants (3)
-
Bin Meng
-
Heinrich Schuchardt
-
Simon Glass