From bdf4269f39c2c39129fa57d2702ab4e4ee550e5e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 19 Oct 2024 09:21:59 -0600 Subject: bootstd: cros: Correct the x86-setup address This should really use an address rather than the buffer. Update it in the command. Signed-off-by: Simon Glass --- cmd/bootflow.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/bootflow.c b/cmd/bootflow.c index 1588f277a4a..5b6e003df77 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -403,7 +403,8 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc, puts("(none)"); putc('\n'); if (bflow->x86_setup) - printf("X86 setup: %p\n", bflow->x86_setup); + printf("X86 setup: %lx\n", + (ulong)map_to_sysmem(bflow->x86_setup)); printf("Logo: %s\n", bflow->logo ? simple_xtoa((ulong)map_to_sysmem(bflow->logo)) : "(none)"); if (bflow->logo) { -- cgit v1.3.1 From 482eedf9f391cab4f055f531be961376a38ae46e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 19 Oct 2024 09:22:09 -0600 Subject: bootstd: Avoid showing an invalid buffer address When the buffer address is not set, say so, rather than showing an address which looks very strange, on sandbox. Signed-off-by: Simon Glass --- cmd/bootflow.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/bootflow.c b/cmd/bootflow.c index 5b6e003df77..f67948d7368 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -393,7 +393,11 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc, printf("Partition: %d\n", bflow->part); printf("Subdir: %s\n", bflow->subdir ? bflow->subdir : "(none)"); printf("Filename: %s\n", bflow->fname); - printf("Buffer: %lx\n", (ulong)map_to_sysmem(bflow->buf)); + printf("Buffer: "); + if (bflow->buf) + printf("%lx\n", (ulong)map_to_sysmem(bflow->buf)); + else + printf("(not loaded)\n"); printf("Size: %x (%d bytes)\n", bflow->size, bflow->size); printf("OS: %s\n", bflow->os_name ? bflow->os_name : "(none)"); printf("Cmdline: "); -- cgit v1.3.1 From d04c23f1c5ee68134543eaa0c5b918d7c9988fe0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 14 Oct 2024 16:32:08 -0600 Subject: x86: coreboot: Show the option table 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 --- cmd/x86/cbsysinfo.c | 73 ++++++++++++++++++++++++++++++++- doc/usage/cmd/cbsysinfo.rst | 99 +++++++++++++++++++++++++++++++++++++++++++++ test/cmd/coreboot.c | 7 ++++ 3 files changed, 178 insertions(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/x86/cbsysinfo.c b/cmd/x86/cbsysinfo.c index 7ca2e13ae2f..ea4d89616f6 100644 --- a/cmd/x86/cbsysinfo.c +++ b/cmd/x86/cbsysinfo.c @@ -184,6 +184,77 @@ static const char *timestamp_name(uint32_t id) return ""; } +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; @@ -218,7 +289,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 80d8ba1b662..28f61d9c63e 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 4a00bad2b8f..0fcf66ac71b 100644 --- a/test/cmd/coreboot.c +++ b/test/cmd/coreboot.c @@ -22,6 +22,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"); -- cgit v1.3.1 From e25c34ddb524043c26ff1db820584a40c0f094b8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 14 Oct 2024 16:32:10 -0600 Subject: x86: coreboot: Add a command to check and update CMOS RAM 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 --- cmd/Kconfig | 11 ++++ cmd/x86/Makefile | 1 + cmd/x86/cbcmos.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++ doc/usage/cmd/cbcmos.rst | 42 ++++++++++++++ doc/usage/index.rst | 1 + test/cmd/coreboot.c | 41 ++++++++++++++ 6 files changed, 235 insertions(+) create mode 100644 cmd/x86/cbcmos.c create mode 100644 doc/usage/cmd/cbcmos.rst (limited to 'cmd') diff --git a/cmd/Kconfig b/cmd/Kconfig index 4fba9fe6703..636833646f6 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2871,6 +2871,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 925215235d3..5f3f5be2882 100644 --- a/cmd/x86/Makefile +++ b/cmd/x86/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_CMD_CBSYSINFO) += cbsysinfo.o obj-y += cpuid.o msr.o mtrr.o +obj-$(CONFIG_CMD_CBCMOS) += cbcmos.o obj-$(CONFIG_CMD_EXCEPTION) += exception.o obj-$(CONFIG_USE_HOB) += hob.o obj-$(CONFIG_HAVE_FSP) += fsp.o diff --git a/cmd/x86/cbcmos.c b/cmd/x86/cbcmos.c new file mode 100644 index 00000000000..fe5582fbf51 --- /dev/null +++ b/cmd/x86/cbcmos.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Support for booting from coreboot + * + * Copyright 2021 Google LLC + */ + +#define LOG_CATEGORY UCLASS_RTC + +#include +#include +#include +#include +#include + +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; +} + +U_BOOT_LONGHELP(cbcmos, + "check - check CMOS RAM\n" + "cbcmos update - Update CMOS-RAM checksum"; +); + +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 00000000000..156521dd02b --- /dev/null +++ b/doc/usage/cmd/cbcmos.rst @@ -0,0 +1,42 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +cbcmos +====== + +Synopis +------- + +:: + + cbcmos check [] + cbcmos update [] + + +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 `` 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 db71711c393..b7c80ef3b12 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -43,6 +43,7 @@ Shell commands cmd/bootz cmd/button cmd/cat + cmd/cbcmos cmd/cbsysinfo cmd/cedit cmd/cli diff --git a/test/cmd/coreboot.c b/test/cmd/coreboot.c index 0fcf66ac71b..e1acf8697e8 100644 --- a/test/cmd/coreboot.c +++ b/test/cmd/coreboot.c @@ -7,10 +7,16 @@ */ #include +#include +#include #include #include #include +enum { + CSUM_LOC = 0x3f0 / 8, +}; + /** * test_cmd_cbsysinfo() - test the cbsysinfo command produces expected output * @@ -41,3 +47,38 @@ static int test_cmd_cbsysinfo(struct unit_test_state *uts) return 0; } CMD_TEST(test_cmd_cbsysinfo, UTF_CONSOLE); + +/* 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, UTF_CONSOLE); -- cgit v1.3.1 From ae3b5928d61190d0faef7dfb2bbfc415a25b6ca5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 14 Oct 2024 16:32:11 -0600 Subject: x86: coreboot: Allow building an expo for editing CMOS config 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 --- boot/Makefile | 3 + boot/expo_build_cb.c | 245 ++++++++++++++++++++++++++++++++++++++++ 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 | 35 ++++++ 9 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 boot/expo_build_cb.c (limited to 'cmd') diff --git a/boot/Makefile b/boot/Makefile index 0e0afad68d1..43def7c33d7 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -59,6 +59,9 @@ obj-$(CONFIG_$(PHASE_)LOAD_FIT) += common_fit.o obj-$(CONFIG_$(PHASE_)EXPO) += expo.o scene.o expo_build.o obj-$(CONFIG_$(PHASE_)EXPO) += scene_menu.o scene_textline.o +ifdef CONFIG_COREBOOT_SYSINFO +obj-$(CONFIG_$(SPL_TPL_)EXPO) += expo_build_cb.o +endif obj-$(CONFIG_$(PHASE_)BOOTMETH_VBE) += vbe.o obj-$(CONFIG_$(PHASE_)BOOTMETH_VBE_REQUEST) += vbe_request.o diff --git a/boot/expo_build_cb.c b/boot/expo_build_cb.c new file mode 100644 index 00000000000..442ad760e79 --- /dev/null +++ b/boot/expo_build_cb.c @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Building an expo from an FDT description + * + * Copyright 2022 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY LOGC_EXPO + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * 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 fec67a8e334..f696356419e 100644 --- a/cmd/cedit.c +++ b/cmd/cedit.c @@ -67,6 +67,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[]) { @@ -271,6 +293,9 @@ static int do_cedit_run(struct cmd_tbl *cmdtp, int flag, int argc, U_BOOT_LONGHELP(cedit, "load - load config editor\n" +#ifdef CONFIG_COREBOOT_SYSINFO + "cb_load - load coreboot CMOS editor\n" +#endif "cedit read_fdt - read settings\n" "cedit write_fdt - write settings\n" "cedit read_env [-v] - read settings from env vars\n" @@ -281,6 +306,9 @@ U_BOOT_LONGHELP(cedit, 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 a177265c16e..f52b24ff43d 100644 --- a/doc/board/coreboot/coreboot.rst +++ b/doc/board/coreboot/coreboot.rst @@ -182,3 +182,9 @@ CI runs tests using a pre-built coreboot image. This ensures that U-Boot can boot as a coreboot payload, based on a known-good build of coreboot. To update the `coreboot.rom` file which is used, see ``tools/Dockerfile`` + +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 310be889240..1ac55ab1219 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 156521dd02b..9395cf1cbd7 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 f29f1b3f388..e54ea204b9f 100644 --- a/doc/usage/cmd/cedit.rst +++ b/doc/usage/cmd/cedit.rst @@ -18,6 +18,7 @@ Synopsis cedit write_env [-v] cedit read_env [-v] cedit write_cmos [-v] [dev] + cedit cb_load Description ----------- @@ -92,6 +93,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 ------- @@ -158,3 +166,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 8cb37260db5..3c383d2e2ee 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 e1acf8697e8..a99898d15c4 100644 --- a/test/cmd/coreboot.c +++ b/test/cmd/coreboot.c @@ -6,12 +6,16 @@ * Written by Simon Glass */ +#include #include #include +#include #include +#include #include #include #include +#include "../../boot/scene_internal.h" enum { CSUM_LOC = 0x3f0 / 8, @@ -82,3 +86,34 @@ static int test_cmd_cbcmos(struct unit_test_state *uts) return 0; } CMD_TEST(test_cmd_cbcmos, UTF_CONSOLE); + +/* 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, UTF_CONSOLE); -- cgit v1.3.1 From d2e1c8a34876dd9e71c2a194fd83f8586716f480 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 28 Oct 2024 13:47:55 +0100 Subject: sandbox: Convert sb command to use new macro Ise the new U_BOOT_CMD_WITH_SUBCMDS() macro instead of writing the code out manually. Signed-off-by: Simon Glass --- cmd/sb.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) (limited to 'cmd') diff --git a/cmd/sb.c b/cmd/sb.c index db485fddfca..9dbb53275b3 100644 --- a/cmd/sb.c +++ b/cmd/sb.c @@ -40,29 +40,10 @@ static int do_sb_state(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } -static struct cmd_tbl cmd_sb_sub[] = { - U_BOOT_CMD_MKENT(handoff, 1, 0, do_sb_handoff, "", ""), - U_BOOT_CMD_MKENT(state, 1, 0, do_sb_state, "", ""), -}; - -static int do_sb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{ - struct cmd_tbl *c; - - /* Skip past 'sb' */ - argc--; - argv++; - - c = find_cmd_tbl(argv[0], cmd_sb_sub, ARRAY_SIZE(cmd_sb_sub)); - if (c) - return c->cmd(cmdtp, flag, argc, argv); - else - return CMD_RET_USAGE; -} - -U_BOOT_CMD( - sb, 8, 1, do_sb, - "Sandbox status commands", +U_BOOT_LONGHELP(sb, "handoff - Show handoff data received from SPL\n" - "sb state - Show sandbox state" -); + "sb state - Show sandbox state"); + +U_BOOT_CMD_WITH_SUBCMDS(sb, "Sandbox status commands", sb_help_text, + U_BOOT_SUBCMD_MKENT(handoff, 1, 1, do_sb_handoff), + U_BOOT_SUBCMD_MKENT(state, 1, 1, do_sb_state)); -- cgit v1.3.1 From 5400c4bc0528b1f2bebd97de1deed62cbd65039b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 28 Oct 2024 13:47:57 +0100 Subject: sandbox: Add a way to show the sandbox memory-mapping This is mostly hidden in the background, but it is sometimes useful to look at it. Add a function to allow this. Signed-off-by: Simon Glass --- arch/sandbox/cpu/cpu.c | 13 +++++++++++++ arch/sandbox/include/asm/cpu.h | 3 +++ cmd/sb.c | 11 +++++++++++ doc/usage/cmd/sb.rst | 25 +++++++++++++++++++++++++ 4 files changed, 52 insertions(+) (limited to 'cmd') diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index 06f8c13fab9..d1c4dcf0764 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -253,6 +253,19 @@ phys_addr_t map_to_sysmem(const void *ptr) return mentry->tag; } +void sandbox_map_list(void) +{ + struct sandbox_mapmem_entry *mentry; + struct sandbox_state *state = state_get_current(); + + printf("Sandbox memory-mapping\n"); + printf("%8s %16s %6s\n", "Addr", "Mapping", "Refcnt"); + list_for_each_entry(mentry, &state->mapmem_head, sibling_node) { + printf("%8lx %p %6d\n", mentry->tag, mentry->ptr, + mentry->refcnt); + } +} + unsigned long sandbox_read(const void *addr, enum sandboxio_size_t size) { struct sandbox_state *state = state_get_current(); diff --git a/arch/sandbox/include/asm/cpu.h b/arch/sandbox/include/asm/cpu.h index c97ac7ba95b..682bb3376d1 100644 --- a/arch/sandbox/include/asm/cpu.h +++ b/arch/sandbox/include/asm/cpu.h @@ -8,4 +8,7 @@ void cpu_sandbox_set_current(const char *name); +/* show the mapping of sandbox addresses to pointers */ +void sandbox_map_list(void); + #endif /* __SANDBOX_CPU_H */ diff --git a/cmd/sb.c b/cmd/sb.c index 9dbb53275b3..9245052492e 100644 --- a/cmd/sb.c +++ b/cmd/sb.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -29,6 +30,14 @@ static int do_sb_handoff(struct cmd_tbl *cmdtp, int flag, int argc, #endif } +static int do_sb_map(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + sandbox_map_list(); + + return 0; +} + static int do_sb_state(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -42,8 +51,10 @@ static int do_sb_state(struct cmd_tbl *cmdtp, int flag, int argc, U_BOOT_LONGHELP(sb, "handoff - Show handoff data received from SPL\n" + "sb map - Show mapped memory\n" "sb state - Show sandbox state"); U_BOOT_CMD_WITH_SUBCMDS(sb, "Sandbox status commands", sb_help_text, U_BOOT_SUBCMD_MKENT(handoff, 1, 1, do_sb_handoff), + U_BOOT_SUBCMD_MKENT(map, 1, 1, do_sb_map), U_BOOT_SUBCMD_MKENT(state, 1, 1, do_sb_state)); diff --git a/doc/usage/cmd/sb.rst b/doc/usage/cmd/sb.rst index 6f54f9d9eb7..37431aff7c8 100644 --- a/doc/usage/cmd/sb.rst +++ b/doc/usage/cmd/sb.rst @@ -12,6 +12,7 @@ Synopsis :: sb handoff + sb map sb state Description @@ -26,6 +27,24 @@ sb handoff This shows information about any handoff information received from SPL. If U-Boot is started from an SPL build, it shows a valid magic number. +sb map +~~~~~~ + +This shows any mappings between sandbox's emulated RAM and the underlying host +address-space. + +Fields shown are: + +Addr + Address in emulated RAM + +Mapping + Equivalent address in the host address-space. While sandbox requests address + ``0x10000000`` from the OS, this is not always available. + +Refcnt + Shows the number of references to this mapping. + sb state ~~~~~~~~ @@ -42,6 +61,12 @@ as ``sandbox_spl``:: => sb handoff SPL handoff magic 14f93c7b +This shows output from the *sb map* subcommand, with a single mapping:: + + Sandbox memory-mapping + Addr Mapping Refcnt + ff000000 000056185b46d6d0 2 + This shows output from the *sb state* subcommand:: => sb state -- cgit v1.3.1