mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-05-09 06:36:13 +02:00
Merge tag 'dm-pull-2nov24' of https://source.denx.de/u-boot/custodians/u-boot-dm
CI: https://source.denx.de/u-boot/custodians/u-boot-dm/-/pipelines/23152 CI: https://dev.azure.com/simon0972/u-boot/_build/results?buildId=71&view=results - alist enhancements and fixes - minor test and sandbox fixes - some more x86/coreboot patches
This commit is contained in:
commit
bf066dc3eb
@ -58,6 +58,13 @@ F: cmd/acpi.c
|
||||
F: include/acpi/
|
||||
F: lib/acpi/
|
||||
|
||||
ALIST:
|
||||
M: Simon Glass <sjg@chromium.org>
|
||||
S: Maintained
|
||||
F: include/alist.h
|
||||
F: lib/alist.c
|
||||
F: test/lib/alist.c
|
||||
|
||||
ANDROID AB
|
||||
M: Igor Opaniuk <igor.opaniuk@gmail.com>
|
||||
M: Mattijs Korpershoek <mkorpershoek@baylibre.com>
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -235,7 +235,7 @@ static inline void unmap_sysmem(const void *vaddr)
|
||||
* nomap_sysmem() - pass through an address unchanged
|
||||
*
|
||||
* This is used to indicate an address which should NOT be mapped, e.g. in
|
||||
* SMBIOS tables. Using this function instead of a case shows that the sandbox
|
||||
* SMBIOS tables. Using this function instead of a cast shows that the sandbox
|
||||
* conversion has been done
|
||||
*/
|
||||
static inline void *nomap_sysmem(phys_addr_t paddr, unsigned long len)
|
||||
|
||||
@ -54,6 +54,13 @@
|
||||
menu-inset = <3>;
|
||||
menuitem-gap-y = <1>;
|
||||
};
|
||||
|
||||
cedit-theme {
|
||||
font-size = <30>;
|
||||
menu-inset = <3>;
|
||||
menuitem-gap-y = <1>;
|
||||
menu-title-margin-x = <30>;
|
||||
};
|
||||
};
|
||||
|
||||
sysinfo {
|
||||
|
||||
@ -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
|
||||
|
||||
245
boot/expo_build_cb.c
Normal file
245
boot/expo_build_cb.c
Normal file
@ -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 <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#define LOG_CATEGORY LOGC_EXPO
|
||||
|
||||
#include <cedit.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <expo.h>
|
||||
#include <log.h>
|
||||
#include <malloc.h>
|
||||
#include <vsprintf.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;
|
||||
}
|
||||
11
cmd/Kconfig
11
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
|
||||
|
||||
@ -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: ");
|
||||
@ -403,7 +407,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) {
|
||||
|
||||
28
cmd/cedit.c
28
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 <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"
|
||||
@ -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),
|
||||
|
||||
42
cmd/sb.c
42
cmd/sb.c
@ -7,6 +7,7 @@
|
||||
#include <command.h>
|
||||
#include <dm.h>
|
||||
#include <spl.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/state.h>
|
||||
|
||||
@ -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[])
|
||||
{
|
||||
@ -40,29 +49,12 @@ 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 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));
|
||||
|
||||
@ -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
|
||||
|
||||
139
cmd/x86/cbcmos.c
Normal file
139
cmd/x86/cbcmos.c
Normal file
@ -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 <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;
|
||||
}
|
||||
|
||||
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));
|
||||
@ -184,6 +184,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;
|
||||
@ -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) {
|
||||
|
||||
@ -249,6 +249,8 @@ static uint32_t print_time_record(struct bootstage_record *rec, uint32_t prev)
|
||||
printf("%11s", "");
|
||||
print_grouped_ull(rec->time_us, BOOTSTAGE_DIGITS);
|
||||
} else {
|
||||
if (prev > rec->time_us)
|
||||
prev = 0;
|
||||
print_grouped_ull(rec->time_us, BOOTSTAGE_DIGITS);
|
||||
print_grouped_ull(rec->time_us - prev, BOOTSTAGE_DIGITS);
|
||||
}
|
||||
@ -257,13 +259,6 @@ static uint32_t print_time_record(struct bootstage_record *rec, uint32_t prev)
|
||||
return rec->time_us;
|
||||
}
|
||||
|
||||
static int h_compare_record(const void *r1, const void *r2)
|
||||
{
|
||||
const struct bootstage_record *rec1 = r1, *rec2 = r2;
|
||||
|
||||
return rec1->time_us > rec2->time_us ? 1 : -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF_LIBFDT
|
||||
/**
|
||||
* Add all bootstage timings to a device tree.
|
||||
@ -342,9 +337,6 @@ void bootstage_report(void)
|
||||
|
||||
prev = print_time_record(rec, 0);
|
||||
|
||||
/* Sort records by increasing time */
|
||||
qsort(data->record, data->rec_count, sizeof(*rec), h_compare_record);
|
||||
|
||||
for (i = 1, rec++; i < data->rec_count; i++, rec++) {
|
||||
if (rec->id && !rec->start_us)
|
||||
prev = print_time_record(rec, prev);
|
||||
|
||||
@ -32,6 +32,7 @@ static const char *const log_cat_name[] = {
|
||||
"fs",
|
||||
"expo",
|
||||
"console",
|
||||
"test",
|
||||
};
|
||||
|
||||
_Static_assert(ARRAY_SIZE(log_cat_name) == LOGC_COUNT - LOGC_NONE,
|
||||
|
||||
@ -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_SYS_PBSIZE=532
|
||||
CONFIG_PRE_CONSOLE_BUFFER=y
|
||||
CONFIG_SYS_CONSOLE_INFO_QUIET=y
|
||||
@ -46,6 +47,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
|
||||
|
||||
@ -16,6 +16,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
|
||||
@ -42,6 +43,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
|
||||
|
||||
@ -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`.
|
||||
|
||||
@ -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`.
|
||||
|
||||
45
doc/usage/cmd/cbcmos.rst
Normal file
45
doc/usage/cmd/cbcmos.rst
Normal file
@ -0,0 +1,45 @@
|
||||
.. 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
|
||||
=>
|
||||
|
||||
See also :ref:`cedit_cb_load` which shows an example that includes the
|
||||
configuration editor.
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
=>
|
||||
|
||||
79
doc/usage/cmd/sb.rst
Normal file
79
doc/usage/cmd/sb.rst
Normal file
@ -0,0 +1,79 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
.. index::
|
||||
single: sbi (command)
|
||||
|
||||
sbi command
|
||||
===========
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
::
|
||||
|
||||
sb handoff
|
||||
sb map
|
||||
sb state
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The *sb* command is used to display information about sandbox's internal
|
||||
operation. See :doc:`/arch/sandbox/index` for more information.
|
||||
|
||||
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
|
||||
~~~~~~~~
|
||||
|
||||
This shows basic information about the sandbox state, currently just the
|
||||
command-line with which sandbox was started.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
This shows checking for the presence of SPL-handoff information. For this to
|
||||
work, ``u-boot-spl`` must be run, with build that enables ``CONFIG_SPL``, such
|
||||
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
|
||||
Arguments:
|
||||
/tmp/b/sandbox/u-boot -D
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The *sb handoff* command is only supported if CONFIG_HANDOFF is enabled.
|
||||
@ -43,6 +43,7 @@ Shell commands
|
||||
cmd/bootz
|
||||
cmd/button
|
||||
cmd/cat
|
||||
cmd/cbcmos
|
||||
cmd/cbsysinfo
|
||||
cmd/cedit
|
||||
cmd/cli
|
||||
@ -103,6 +104,7 @@ Shell commands
|
||||
cmd/reset
|
||||
cmd/rng
|
||||
cmd/saves
|
||||
cmd/sb
|
||||
cmd/sbi
|
||||
cmd/scmi
|
||||
cmd/scp03
|
||||
|
||||
@ -304,6 +304,17 @@ int uclass_find_device_by_name(enum uclass_id id, const char *name,
|
||||
return uclass_find_device_by_namelen(id, name, strlen(name), devp);
|
||||
}
|
||||
|
||||
struct udevice *uclass_try_first_device(enum uclass_id id)
|
||||
{
|
||||
struct uclass *uc;
|
||||
|
||||
uc = uclass_find(id);
|
||||
if (!uc || list_empty(&uc->dev_head))
|
||||
return NULL;
|
||||
|
||||
return list_first_entry(&uc->dev_head, struct udevice, uclass_node);
|
||||
}
|
||||
|
||||
int uclass_find_next_free_seq(struct uclass *uc)
|
||||
{
|
||||
struct udevice *dev;
|
||||
|
||||
139
include/alist.h
139
include/alist.h
@ -71,6 +71,21 @@ static inline bool alist_has(struct alist *lst, uint index)
|
||||
return index < lst->count;
|
||||
}
|
||||
|
||||
/**
|
||||
* alist_calc_index() - Calculate the index of an item in the list
|
||||
*
|
||||
* The returned element number will be -1 if the list is empty or the pointer
|
||||
* pointers to before the list starts.
|
||||
*
|
||||
* If the pointer points to after the last item, the calculated element-number
|
||||
* will be returned, even though it is greater than lst->count
|
||||
*
|
||||
* @lst: alist to check
|
||||
* @ptr: pointer to check
|
||||
* Return: element number of the pointer
|
||||
*/
|
||||
int alist_calc_index(const struct alist *lst, const void *ptr);
|
||||
|
||||
/**
|
||||
* alist_err() - Check if the alist is still valid
|
||||
*
|
||||
@ -116,7 +131,12 @@ static inline const void *alist_getd(struct alist *lst, uint index)
|
||||
return lst->data + index * lst->obj_size;
|
||||
}
|
||||
|
||||
/** get an entry as a constant */
|
||||
/**
|
||||
* alist_get() - get an entry as a constant
|
||||
*
|
||||
* Use as (to obtain element 2 of the list):
|
||||
* const struct my_struct *ptr = alist_get(lst, 2, struct my_struct)
|
||||
*/
|
||||
#define alist_get(_lst, _index, _struct) \
|
||||
((const _struct *)alist_get_ptr(_lst, _index))
|
||||
|
||||
@ -151,8 +171,9 @@ void *alist_ensure_ptr(struct alist *lst, uint index);
|
||||
* alist_add_placeholder() - Add a new item to the end of the list
|
||||
*
|
||||
* @lst: alist to add to
|
||||
* Return: Pointer to the newly added position. Note that this is not inited so
|
||||
* the caller must copy the requested struct to the returned pointer
|
||||
* Return: Pointer to the newly added position, or NULL if out of memory. Note
|
||||
* that this is not inited so the caller must copy the requested struct to the
|
||||
* returned pointer
|
||||
*/
|
||||
void *alist_add_placeholder(struct alist *lst);
|
||||
|
||||
@ -184,6 +205,112 @@ bool alist_expand_by(struct alist *lst, uint inc_by);
|
||||
#define alist_add(_lst, _obj) \
|
||||
((typeof(_obj) *)alist_add_ptr(_lst, &(_obj)))
|
||||
|
||||
/** get next entry as a constant */
|
||||
#define alist_next(_lst, _objp) \
|
||||
((const typeof(_objp))alist_next_ptrd(_lst, _objp))
|
||||
|
||||
/** get next entry, which can be written to */
|
||||
#define alist_nextw(_lst, _objp) \
|
||||
((typeof(_objp))alist_next_ptrd(_lst, _objp))
|
||||
|
||||
/**
|
||||
* alist_next_ptrd() - Get a pointer to the next list element
|
||||
*
|
||||
* This returns NULL if the requested element is beyond lst->count
|
||||
*
|
||||
* @lst: List to check
|
||||
* @ptr: Pointer to current element (must be valid)
|
||||
* Return: Pointer to next element, or NULL if @ptr is the last
|
||||
*/
|
||||
const void *alist_next_ptrd(const struct alist *lst, const void *ptr);
|
||||
|
||||
/**
|
||||
* alist_chk_ptr() - Check whether a pointer is within a list
|
||||
*
|
||||
* Checks if the pointer points to an existing element of the list. The pointer
|
||||
* must point to the start of an element, either in the list, or just outside of
|
||||
* it. This function is only useful for handling for() loops
|
||||
*
|
||||
* Return: true if @ptr is within the list (0..count-1), else false
|
||||
*/
|
||||
bool alist_chk_ptr(const struct alist *lst, const void *ptr);
|
||||
|
||||
/**
|
||||
* alist_start() - Get the start of the list (first element)
|
||||
*
|
||||
* Note that this will always return ->data even if it is not NULL
|
||||
*
|
||||
* Usage:
|
||||
* const struct my_struct *obj; # 'const' is optional
|
||||
*
|
||||
* alist_start(&lst, struct my_struct)
|
||||
*/
|
||||
#define alist_start(_lst, _struct) \
|
||||
((_struct *)(_lst)->data)
|
||||
|
||||
/**
|
||||
* alist_end() - Get the end of the list (just after last element)
|
||||
*
|
||||
* Usage:
|
||||
* const struct my_struct *obj; # 'const' is optional
|
||||
*
|
||||
* alist_end(&lst, struct my_struct)
|
||||
*/
|
||||
#define alist_end(_lst, _struct) \
|
||||
((_struct *)(_lst)->data + (_lst)->count)
|
||||
|
||||
/**
|
||||
* alist_for_each() - Iterate over an alist (with constant pointer)
|
||||
*
|
||||
* Use as:
|
||||
* const struct my_struct *obj; # 'const' is optional
|
||||
*
|
||||
* alist_for_each(obj, &lst) {
|
||||
* obj->...
|
||||
* }
|
||||
*/
|
||||
#define alist_for_each(_pos, _lst) \
|
||||
for (_pos = alist_start(_lst, typeof(*(_pos))); \
|
||||
_pos < alist_end(_lst, typeof(*(_pos))); \
|
||||
_pos++)
|
||||
|
||||
/**
|
||||
* alist_for_each_filter() - version which sets up a 'from' pointer too
|
||||
*
|
||||
* This is used for filtering out information in the list. It works by iterating
|
||||
* through the list, copying elements down over the top of elements to be
|
||||
* deleted.
|
||||
*
|
||||
* In this example, 'from' iterates through the list from start to end,, 'to'
|
||||
* also begins at the start, but only increments if the element at 'from' should
|
||||
* be kept. This provides an O(n) filtering operation. Note that
|
||||
* alist_update_end() must be called after the loop, to update the count.
|
||||
*
|
||||
* alist_for_each_filter(from, to, &lst) {
|
||||
* if (from->val != 2)
|
||||
* *to++ = *from;
|
||||
* }
|
||||
* alist_update_end(&lst, to);
|
||||
*/
|
||||
#define alist_for_each_filter(_pos, _from, _lst) \
|
||||
for (_pos = _from = alist_start(_lst, typeof(*(_pos))); \
|
||||
_pos < alist_end(_lst, typeof(*(_pos))); \
|
||||
_pos++)
|
||||
|
||||
/**
|
||||
* alist_update_end() - Set the element count based on a given pointer
|
||||
*
|
||||
* Set the given element as the final one
|
||||
*/
|
||||
void alist_update_end(struct alist *lst, const void *end);
|
||||
|
||||
/**
|
||||
* alist_empty() - Empty an alist
|
||||
*
|
||||
* This removes all entries from the list, without changing the allocated size
|
||||
*/
|
||||
void alist_empty(struct alist *lst);
|
||||
|
||||
/**
|
||||
* alist_init() - Set up a new object list
|
||||
*
|
||||
@ -197,6 +324,12 @@ bool alist_expand_by(struct alist *lst, uint inc_by);
|
||||
*/
|
||||
bool alist_init(struct alist *lst, uint obj_size, uint alloc_size);
|
||||
|
||||
/**
|
||||
* alist_init_struct() - Typed version of alist_init()
|
||||
*
|
||||
* Use as:
|
||||
* alist_init(&lst, struct my_struct);
|
||||
*/
|
||||
#define alist_init_struct(_lst, _struct) \
|
||||
alist_init(_lst, sizeof(_struct), 0)
|
||||
|
||||
|
||||
@ -545,8 +545,10 @@ static_assert(sizeof(struct global_data) == GD_SIZE);
|
||||
|
||||
#if CONFIG_IS_ENABLED(BLOBLIST)
|
||||
#define gd_bloblist() gd->bloblist
|
||||
#define gd_set_bloblist(_val) gd->bloblist = (_val)
|
||||
#else
|
||||
#define gd_bloblist() NULL
|
||||
#define gd_set_bloblist(_val)
|
||||
#endif
|
||||
|
||||
#if CONFIG_IS_ENABLED(BOOTSTAGE)
|
||||
|
||||
@ -435,6 +435,17 @@ int uclass_next_device_check(struct udevice **devp);
|
||||
int uclass_first_device_drvdata(enum uclass_id id, ulong driver_data,
|
||||
struct udevice **devp);
|
||||
|
||||
/**
|
||||
* uclass_try_first_device()- See if there is a device for a uclass
|
||||
*
|
||||
* If the uclass exists, this returns the first device on that uclass, without
|
||||
* probing it. If the uclass does not exist, it gives up
|
||||
*
|
||||
* @id: Uclass ID to check
|
||||
* Return: Pointer to device, if found, else NULL
|
||||
*/
|
||||
struct udevice *uclass_try_first_device(enum uclass_id id);
|
||||
|
||||
/**
|
||||
* uclass_probe_all() - Probe all devices based on an uclass ID
|
||||
*
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -106,6 +106,8 @@ enum log_category_t {
|
||||
LOGC_EXPO,
|
||||
/** @LOGC_CONSOLE: Related to the console and stdio */
|
||||
LOGC_CONSOLE,
|
||||
/** @LOGC_TEST: Related to testing */
|
||||
LOGC_TEST,
|
||||
/** @LOGC_COUNT: Number of log categories */
|
||||
LOGC_COUNT,
|
||||
/** @LOGC_END: Sentinel value for lists of log categories */
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
* @of_other: Live tree for the other FDT
|
||||
* @runs_per_test: Number of times to run each test (typically 1)
|
||||
* @force_run: true to run tests marked with the UTF_MANUAL flag
|
||||
* @old_bloblist: stores the old gd->bloblist pointer
|
||||
* @expect_str: Temporary string used to hold expected string value
|
||||
* @actual_str: Temporary string used to hold actual string value
|
||||
*/
|
||||
@ -50,6 +51,7 @@ struct unit_test_state {
|
||||
struct device_node *of_other;
|
||||
int runs_per_test;
|
||||
bool force_run;
|
||||
void *old_bloblist;
|
||||
char expect_str[512];
|
||||
char actual_str[512];
|
||||
};
|
||||
@ -73,6 +75,7 @@ enum ut_flags {
|
||||
UTF_MANUAL = BIT(8),
|
||||
UTF_ETH_BOOTDEV = BIT(9), /* enable Ethernet bootdevs */
|
||||
UTF_SF_BOOTDEV = BIT(10), /* enable SPI flash bootdevs */
|
||||
UFT_BLOBLIST = BIT(11), /* test changes gd->bloblist */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
41
lib/alist.c
41
lib/alist.c
@ -41,6 +41,11 @@ void alist_uninit(struct alist *lst)
|
||||
memset(lst, '\0', sizeof(struct alist));
|
||||
}
|
||||
|
||||
void alist_empty(struct alist *lst)
|
||||
{
|
||||
lst->count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* alist_expand_to() - Expand a list to the given size
|
||||
*
|
||||
@ -106,6 +111,42 @@ const void *alist_get_ptr(const struct alist *lst, uint index)
|
||||
return lst->data + index * lst->obj_size;
|
||||
}
|
||||
|
||||
int alist_calc_index(const struct alist *lst, const void *ptr)
|
||||
{
|
||||
uint index;
|
||||
|
||||
if (!lst->count || ptr < lst->data)
|
||||
return -1;
|
||||
|
||||
index = (ptr - lst->data) / lst->obj_size;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void alist_update_end(struct alist *lst, const void *ptr)
|
||||
{
|
||||
int index;
|
||||
|
||||
index = alist_calc_index(lst, ptr);
|
||||
lst->count = index == -1 ? 0 : index;
|
||||
}
|
||||
|
||||
bool alist_chk_ptr(const struct alist *lst, const void *ptr)
|
||||
{
|
||||
int index = alist_calc_index(lst, ptr);
|
||||
|
||||
return index >= 0 && index < lst->count;
|
||||
}
|
||||
|
||||
const void *alist_next_ptrd(const struct alist *lst, const void *ptr)
|
||||
{
|
||||
int index = alist_calc_index(lst, ptr);
|
||||
|
||||
assert(index != -1);
|
||||
|
||||
return alist_get_ptr(lst, index + 1);
|
||||
}
|
||||
|
||||
void *alist_ensure_ptr(struct alist *lst, uint index)
|
||||
{
|
||||
uint minsize = index + 1;
|
||||
|
||||
@ -94,7 +94,7 @@ static int bloblist_test_init(struct unit_test_state *uts)
|
||||
|
||||
return 1;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_init, 0);
|
||||
BLOBLIST_TEST(bloblist_test_init, UFT_BLOBLIST);
|
||||
|
||||
static int bloblist_test_blob(struct unit_test_state *uts)
|
||||
{
|
||||
@ -134,7 +134,7 @@ static int bloblist_test_blob(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_blob, 0);
|
||||
BLOBLIST_TEST(bloblist_test_blob, UFT_BLOBLIST);
|
||||
|
||||
/* Check bloblist_ensure_size_ret() */
|
||||
static int bloblist_test_blob_ensure(struct unit_test_state *uts)
|
||||
@ -168,7 +168,7 @@ static int bloblist_test_blob_ensure(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
|
||||
BLOBLIST_TEST(bloblist_test_blob_ensure, UFT_BLOBLIST);
|
||||
|
||||
static int bloblist_test_bad_blob(struct unit_test_state *uts)
|
||||
{
|
||||
@ -184,7 +184,7 @@ static int bloblist_test_bad_blob(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_bad_blob, 0);
|
||||
BLOBLIST_TEST(bloblist_test_bad_blob, UFT_BLOBLIST);
|
||||
|
||||
static int bloblist_test_checksum(struct unit_test_state *uts)
|
||||
{
|
||||
@ -257,7 +257,7 @@ static int bloblist_test_checksum(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_checksum, 0);
|
||||
BLOBLIST_TEST(bloblist_test_checksum, UFT_BLOBLIST);
|
||||
|
||||
/* Test the 'bloblist info' command */
|
||||
static int bloblist_test_cmd_info(struct unit_test_state *uts)
|
||||
@ -278,7 +278,7 @@ static int bloblist_test_cmd_info(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_cmd_info, UTF_CONSOLE);
|
||||
BLOBLIST_TEST(bloblist_test_cmd_info, UFT_BLOBLIST | UTF_CONSOLE);
|
||||
|
||||
/* Test the 'bloblist list' command */
|
||||
static int bloblist_test_cmd_list(struct unit_test_state *uts)
|
||||
@ -300,7 +300,7 @@ static int bloblist_test_cmd_list(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_cmd_list, UTF_CONSOLE);
|
||||
BLOBLIST_TEST(bloblist_test_cmd_list, UFT_BLOBLIST | UTF_CONSOLE);
|
||||
|
||||
/* Test alignment of bloblist blobs */
|
||||
static int bloblist_test_align(struct unit_test_state *uts)
|
||||
@ -358,7 +358,7 @@ static int bloblist_test_align(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_align, 0);
|
||||
BLOBLIST_TEST(bloblist_test_align, UFT_BLOBLIST);
|
||||
|
||||
/* Test relocation of a bloblist */
|
||||
static int bloblist_test_reloc(struct unit_test_state *uts)
|
||||
@ -392,7 +392,7 @@ static int bloblist_test_reloc(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_reloc, 0);
|
||||
BLOBLIST_TEST(bloblist_test_reloc, UFT_BLOBLIST);
|
||||
|
||||
/* Test expansion of a blob */
|
||||
static int bloblist_test_grow(struct unit_test_state *uts)
|
||||
@ -445,7 +445,7 @@ static int bloblist_test_grow(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_grow, 0);
|
||||
BLOBLIST_TEST(bloblist_test_grow, UFT_BLOBLIST);
|
||||
|
||||
/* Test shrinking of a blob */
|
||||
static int bloblist_test_shrink(struct unit_test_state *uts)
|
||||
@ -495,7 +495,7 @@ static int bloblist_test_shrink(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_shrink, 0);
|
||||
BLOBLIST_TEST(bloblist_test_shrink, UFT_BLOBLIST);
|
||||
|
||||
/* Test failing to adjust a blob size */
|
||||
static int bloblist_test_resize_fail(struct unit_test_state *uts)
|
||||
@ -530,7 +530,7 @@ static int bloblist_test_resize_fail(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_resize_fail, 0);
|
||||
BLOBLIST_TEST(bloblist_test_resize_fail, UFT_BLOBLIST);
|
||||
|
||||
/* Test expanding the last blob in a bloblist */
|
||||
static int bloblist_test_resize_last(struct unit_test_state *uts)
|
||||
@ -581,7 +581,7 @@ static int bloblist_test_resize_last(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_resize_last, 0);
|
||||
BLOBLIST_TEST(bloblist_test_resize_last, UFT_BLOBLIST);
|
||||
|
||||
/* Check a completely full bloblist */
|
||||
static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
|
||||
@ -604,7 +604,7 @@ static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BLOBLIST_TEST(bloblist_test_blob_maxsize, 0);
|
||||
BLOBLIST_TEST(bloblist_test_blob_maxsize, UFT_BLOBLIST);
|
||||
|
||||
int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
|
||||
@ -370,7 +370,7 @@ static int bootflow_iter(struct unit_test_state *uts)
|
||||
|
||||
return 0;
|
||||
}
|
||||
BOOTSTD_TEST(bootflow_iter, UTF_DM | UTF_SCAN_FDT);
|
||||
BOOTSTD_TEST(bootflow_iter, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
|
||||
|
||||
#if defined(CONFIG_SANDBOX) && defined(CONFIG_BOOTMETH_GLOBAL)
|
||||
/* Check using the system bootdev */
|
||||
@ -542,7 +542,7 @@ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
|
||||
/* Enable the script bootmeth too */
|
||||
ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
|
||||
ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_2script),
|
||||
"bootmeth_script", 0, ofnode_null(), &dev));
|
||||
"script", 0, ofnode_null(), &dev));
|
||||
|
||||
/* Enable the cros bootmeth if needed */
|
||||
if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros_android) {
|
||||
|
||||
@ -15,6 +15,7 @@ obj-y += exit.o mem.o
|
||||
obj-$(CONFIG_X86) += cpuid.o msr.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
|
||||
|
||||
119
test/cmd/coreboot.c
Normal file
119
test/cmd/coreboot.c
Normal file
@ -0,0 +1,119 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Test for coreboot commands
|
||||
*
|
||||
* Copyright 2023 Google LLC
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#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,
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 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");
|
||||
|
||||
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, 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);
|
||||
|
||||
/* 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);
|
||||
@ -1351,3 +1351,25 @@ static int dm_test_dev_get_mem(struct unit_test_state *uts)
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_dev_get_mem, UTF_SCAN_FDT);
|
||||
|
||||
/* Test uclass_try_first_device() */
|
||||
static int dm_test_try_first_device(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *dev;
|
||||
|
||||
/* Check that it doesn't create a device or uclass */
|
||||
ut_assertnull(uclass_find(UCLASS_TEST));
|
||||
ut_assertnull(uclass_try_first_device(UCLASS_TEST));
|
||||
ut_assertnull(uclass_try_first_device(UCLASS_TEST));
|
||||
ut_assertnull(uclass_find(UCLASS_TEST));
|
||||
|
||||
/* Create a test device */
|
||||
ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
|
||||
&dev));
|
||||
dev = uclass_try_first_device(UCLASS_TEST);
|
||||
ut_assertnonnull(dev);
|
||||
ut_asserteq(UCLASS_TEST, device_get_uclass_id(dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_try_first_device, 0);
|
||||
|
||||
253
test/lib/alist.c
253
test/lib/alist.c
@ -240,3 +240,256 @@ static int lib_test_alist_add(struct unit_test_state *uts)
|
||||
return 0;
|
||||
}
|
||||
LIB_TEST(lib_test_alist_add, 0);
|
||||
|
||||
/* Test alist_next() */
|
||||
static int lib_test_alist_next(struct unit_test_state *uts)
|
||||
{
|
||||
const struct my_struct *ptr;
|
||||
struct my_struct data, *ptr2;
|
||||
struct alist lst;
|
||||
ulong start;
|
||||
|
||||
start = ut_check_free();
|
||||
|
||||
ut_assert(alist_init_struct(&lst, struct my_struct));
|
||||
data.val = 123;
|
||||
data.other_val = 0;
|
||||
alist_add(&lst, data);
|
||||
|
||||
data.val = 321;
|
||||
alist_add(&lst, data);
|
||||
|
||||
data.val = 789;
|
||||
alist_add(&lst, data);
|
||||
|
||||
ptr = alist_get(&lst, 0, struct my_struct);
|
||||
ut_assertnonnull(ptr);
|
||||
ut_asserteq(123, ptr->val);
|
||||
|
||||
ptr = alist_next(&lst, ptr);
|
||||
ut_assertnonnull(ptr);
|
||||
ut_asserteq(321, ptr->val);
|
||||
|
||||
ptr2 = (struct my_struct *)ptr;
|
||||
ptr2 = alist_nextw(&lst, ptr2);
|
||||
ut_assertnonnull(ptr2);
|
||||
|
||||
ptr = alist_next(&lst, ptr);
|
||||
ut_assertnonnull(ptr);
|
||||
ut_asserteq(789, ptr->val);
|
||||
ut_asserteq_ptr(ptr, ptr2);
|
||||
ptr2->val = 89;
|
||||
ut_asserteq(89, ptr->val);
|
||||
|
||||
ptr = alist_next(&lst, ptr);
|
||||
ut_assertnull(ptr);
|
||||
|
||||
alist_uninit(&lst);
|
||||
|
||||
/* Check for memory leaks */
|
||||
ut_assertok(ut_check_delta(start));
|
||||
|
||||
return 0;
|
||||
}
|
||||
LIB_TEST(lib_test_alist_next, 0);
|
||||
|
||||
/* Test alist_for_each() */
|
||||
static int lib_test_alist_for_each(struct unit_test_state *uts)
|
||||
{
|
||||
const struct my_struct *ptr;
|
||||
struct my_struct data, *ptr2;
|
||||
struct alist lst;
|
||||
ulong start;
|
||||
int sum;
|
||||
|
||||
start = ut_check_free();
|
||||
|
||||
ut_assert(alist_init_struct(&lst, struct my_struct));
|
||||
ut_asserteq_ptr(NULL, alist_end(&lst, struct my_struct));
|
||||
|
||||
sum = 0;
|
||||
alist_for_each(ptr, &lst)
|
||||
sum++;
|
||||
ut_asserteq(0, sum);
|
||||
|
||||
alist_for_each(ptr, &lst)
|
||||
sum++;
|
||||
ut_asserteq(0, sum);
|
||||
|
||||
/* add three items */
|
||||
data.val = 1;
|
||||
data.other_val = 0;
|
||||
alist_add(&lst, data);
|
||||
|
||||
ptr = lst.data;
|
||||
ut_asserteq_ptr(ptr + 1, alist_end(&lst, struct my_struct));
|
||||
|
||||
data.val = 2;
|
||||
alist_add(&lst, data);
|
||||
ut_asserteq_ptr(ptr + 2, alist_end(&lst, struct my_struct));
|
||||
|
||||
data.val = 3;
|
||||
alist_add(&lst, data);
|
||||
ut_asserteq_ptr(ptr + 3, alist_end(&lst, struct my_struct));
|
||||
|
||||
/* check alist_chk_ptr() */
|
||||
ut_asserteq(true, alist_chk_ptr(&lst, ptr + 2));
|
||||
ut_asserteq(false, alist_chk_ptr(&lst, ptr + 3));
|
||||
ut_asserteq(false, alist_chk_ptr(&lst, ptr + 4));
|
||||
ut_asserteq(true, alist_chk_ptr(&lst, ptr));
|
||||
ut_asserteq(false, alist_chk_ptr(&lst, ptr - 1));
|
||||
|
||||
/* sum all items */
|
||||
sum = 0;
|
||||
alist_for_each(ptr, &lst)
|
||||
sum += ptr->val;
|
||||
ut_asserteq(6, sum);
|
||||
|
||||
/* increment all items */
|
||||
alist_for_each(ptr2, &lst)
|
||||
ptr2->val += 1;
|
||||
|
||||
/* sum all items again */
|
||||
sum = 0;
|
||||
alist_for_each(ptr, &lst)
|
||||
sum += ptr->val;
|
||||
ut_asserteq(9, sum);
|
||||
|
||||
ptr = lst.data;
|
||||
ut_asserteq_ptr(ptr + 3, alist_end(&lst, struct my_struct));
|
||||
|
||||
/* empty the list and try again */
|
||||
alist_empty(&lst);
|
||||
ut_asserteq_ptr(ptr, alist_end(&lst, struct my_struct));
|
||||
ut_assertnull(alist_get(&lst, 0, struct my_struct));
|
||||
|
||||
sum = 0;
|
||||
alist_for_each(ptr, &lst)
|
||||
sum += ptr->val;
|
||||
ut_asserteq(0, sum);
|
||||
|
||||
alist_uninit(&lst);
|
||||
|
||||
/* Check for memory leaks */
|
||||
ut_assertok(ut_check_delta(start));
|
||||
|
||||
return 0;
|
||||
}
|
||||
LIB_TEST(lib_test_alist_for_each, 0);
|
||||
|
||||
/* Test alist_empty() */
|
||||
static int lib_test_alist_empty(struct unit_test_state *uts)
|
||||
{
|
||||
struct my_struct data;
|
||||
struct alist lst;
|
||||
ulong start;
|
||||
|
||||
start = ut_check_free();
|
||||
|
||||
ut_assert(alist_init_struct(&lst, struct my_struct));
|
||||
ut_asserteq(0, lst.count);
|
||||
data.val = 1;
|
||||
data.other_val = 0;
|
||||
alist_add(&lst, data);
|
||||
ut_asserteq(1, lst.count);
|
||||
ut_asserteq(4, lst.alloc);
|
||||
|
||||
alist_empty(&lst);
|
||||
ut_asserteq(0, lst.count);
|
||||
ut_asserteq(4, lst.alloc);
|
||||
ut_assertnonnull(lst.data);
|
||||
ut_asserteq(sizeof(data), lst.obj_size);
|
||||
|
||||
alist_uninit(&lst);
|
||||
|
||||
/* Check for memory leaks */
|
||||
ut_assertok(ut_check_delta(start));
|
||||
|
||||
return 0;
|
||||
}
|
||||
LIB_TEST(lib_test_alist_empty, 0);
|
||||
|
||||
static int lib_test_alist_filter(struct unit_test_state *uts)
|
||||
{
|
||||
struct my_struct *from, *to, *ptr;
|
||||
struct my_struct data;
|
||||
struct alist lst;
|
||||
ulong start;
|
||||
int count;
|
||||
|
||||
start = ut_check_free();
|
||||
|
||||
ut_assert(alist_init_struct(&lst, struct my_struct));
|
||||
data.val = 1;
|
||||
data.other_val = 0;
|
||||
alist_add(&lst, data);
|
||||
|
||||
data.val = 2;
|
||||
alist_add(&lst, data);
|
||||
|
||||
data.val = 3;
|
||||
alist_add(&lst, data);
|
||||
ptr = lst.data;
|
||||
|
||||
/* filter out all values except 2 */
|
||||
alist_for_each_filter(from, to, &lst) {
|
||||
if (from->val != 2)
|
||||
*to++ = *from;
|
||||
}
|
||||
alist_update_end(&lst, to);
|
||||
|
||||
ut_asserteq(2, lst.count);
|
||||
ut_assertnonnull(lst.data);
|
||||
|
||||
ut_asserteq(1, alist_get(&lst, 0, struct my_struct)->val);
|
||||
ut_asserteq(3, alist_get(&lst, 1, struct my_struct)->val);
|
||||
ut_asserteq_ptr(ptr + 3, from);
|
||||
ut_asserteq_ptr(ptr + 2, to);
|
||||
|
||||
/* filter out nothing */
|
||||
alist_for_each_filter(from, to, &lst) {
|
||||
if (from->val != 2)
|
||||
*to++ = *from;
|
||||
}
|
||||
alist_update_end(&lst, to);
|
||||
ut_asserteq_ptr(ptr + 2, from);
|
||||
ut_asserteq_ptr(ptr + 2, to);
|
||||
|
||||
ut_asserteq(2, lst.count);
|
||||
ut_assertnonnull(lst.data);
|
||||
|
||||
ut_asserteq(1, alist_get(&lst, 0, struct my_struct)->val);
|
||||
ut_asserteq(3, alist_get(&lst, 1, struct my_struct)->val);
|
||||
|
||||
/* filter out everything */
|
||||
alist_for_each_filter(from, to, &lst) {
|
||||
if (from->val == 2)
|
||||
*to++ = *from;
|
||||
}
|
||||
alist_update_end(&lst, to);
|
||||
ut_asserteq_ptr(ptr + 2, from);
|
||||
ut_asserteq_ptr(ptr, to);
|
||||
|
||||
/* filter out everything (nop) */
|
||||
count = 0;
|
||||
alist_for_each_filter(from, to, &lst) {
|
||||
if (from->val == 2)
|
||||
*to++ = *from;
|
||||
count++;
|
||||
}
|
||||
alist_update_end(&lst, to);
|
||||
ut_asserteq_ptr(ptr, from);
|
||||
ut_asserteq_ptr(ptr, to);
|
||||
ut_asserteq(0, count);
|
||||
|
||||
ut_asserteq(0, lst.count);
|
||||
ut_assertnonnull(lst.data);
|
||||
|
||||
alist_uninit(&lst);
|
||||
|
||||
/* Check for memory leaks */
|
||||
ut_assertok(ut_check_delta(start));
|
||||
|
||||
return 0;
|
||||
}
|
||||
LIB_TEST(lib_test_alist_filter, 0);
|
||||
|
||||
@ -208,8 +208,6 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}
|
||||
cons, f'echo here {kernel} {symlink}')
|
||||
os.symlink(kernel, symlink)
|
||||
|
||||
u_boot_utils.run_and_log(
|
||||
cons, f'mkimage -C none -A arm -T script -d {cmd_fname} {scr_fname}')
|
||||
complete = True
|
||||
|
||||
except ValueError as exc:
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#define LOG_CATEGORY LOGC_TEST
|
||||
|
||||
#include <blk.h>
|
||||
#include <console.h>
|
||||
#include <cyclic.h>
|
||||
@ -240,15 +242,22 @@ static bool test_matches(const char *prefix, const char *test_name,
|
||||
* ut_list_has_dm_tests() - Check if a list of tests has driver model ones
|
||||
*
|
||||
* @tests: List of tests to run
|
||||
* @count: Number of tests to ru
|
||||
* @count: Number of tests to run
|
||||
* @prefix: String prefix for the tests. Any tests that have this prefix will be
|
||||
* printed without the prefix, so that it is easier to see the unique part
|
||||
* of the test name. If NULL, no prefix processing is done
|
||||
* @select_name: Name of a single test being run (from the list provided). If
|
||||
* NULL all tests are being run
|
||||
* Return: true if any of the tests have the UTF_DM flag
|
||||
*/
|
||||
static bool ut_list_has_dm_tests(struct unit_test *tests, int count)
|
||||
static bool ut_list_has_dm_tests(struct unit_test *tests, int count,
|
||||
const char *prefix, const char *select_name)
|
||||
{
|
||||
struct unit_test *test;
|
||||
|
||||
for (test = tests; test < tests + count; test++) {
|
||||
if (test->flags & UTF_DM)
|
||||
if (test_matches(prefix, test->name, select_name) &&
|
||||
(test->flags & UTF_DM))
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -379,6 +388,12 @@ static int test_pre_run(struct unit_test_state *uts, struct unit_test *test)
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
if (test->flags & UFT_BLOBLIST) {
|
||||
log_debug("save bloblist %p\n", gd_bloblist());
|
||||
uts->old_bloblist = gd_bloblist();
|
||||
gd_set_bloblist(NULL);
|
||||
}
|
||||
|
||||
ut_silence_console(uts);
|
||||
|
||||
return 0;
|
||||
@ -402,6 +417,11 @@ static int test_post_run(struct unit_test_state *uts, struct unit_test *test)
|
||||
free(uts->of_other);
|
||||
uts->of_other = NULL;
|
||||
|
||||
if (test->flags & UFT_BLOBLIST) {
|
||||
gd_set_bloblist(uts->old_bloblist);
|
||||
log_debug("restore bloblist %p\n", gd_bloblist());
|
||||
}
|
||||
|
||||
blkcache_free();
|
||||
|
||||
return 0;
|
||||
@ -550,6 +570,9 @@ static int ut_run_test_live_flat(struct unit_test_state *uts,
|
||||
* @count: Number of tests to run
|
||||
* @select_name: Name of a single test to run (from the list provided). If NULL
|
||||
* then all tests are run
|
||||
* @test_insert: String describing a test to run after n other tests run, in the
|
||||
* format n:name where n is the number of tests to run before this one and
|
||||
* name is the name of the test to run
|
||||
* Return: 0 if all tests passed, -ENOENT if test @select_name was not found,
|
||||
* -EBADF if any failed
|
||||
*/
|
||||
@ -646,7 +669,7 @@ int ut_run_list(const char *category, const char *prefix,
|
||||
int ret;
|
||||
|
||||
if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
|
||||
ut_list_has_dm_tests(tests, count)) {
|
||||
ut_list_has_dm_tests(tests, count, prefix, select_name)) {
|
||||
has_dm_tests = true;
|
||||
/*
|
||||
* If we have no device tree, or it only has a root node, then
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user