mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-23 13:56:20 +00:00
A few new x86 commands and minor improvements
expo improvements binman support for signing FIT images -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEslwAIq+Gp8wWVbYnfxc6PpAIreYFAmcSwRQRHHNqZ0BjaHJv bWl1bS5vcmcACgkQfxc6PpAIreYWLgf/dnh+7hFENA/pIp57kiihzLc4sH+XaCiR A6MDkSnYWFCJpklz2rPPGsyuxEVtNgVtHEpPwA8OPaXitfuyLW/u5woBN6Sdtcvw Fqvq72IIMIt3BR6pU2uYZ6w/4t0r0/2pdSYG7L77QJjGsFSe35/RbVaGeln//SEk 7/5tnqQ13QbhfazwLWNGT7+8R65NcpSwywxGqMcKWMPLt0CW+DMmon4oBuya20pv i5uDIp7WWtyxFaCxB3vzKmaXVmX74x9wyWA/K6uWsWt0/9JnEpQh5+IcgKw5ifGF sz2kVyZgCXilw1itrmO67O98KPfbRSFIQO2gSZ5NnNB4wrIgFXK2KA== =1pdb -----END PGP SIGNATURE----- Merge tag 'dm-pull-17oct24-take2' of https://gitlab.denx.de/u-boot/custodians/u-boot-dm A few new x86 commands and minor improvements expo improvements binman support for signing FIT images
This commit is contained in:
commit
7036abbd5c
85 changed files with 2237 additions and 345 deletions
|
@ -916,6 +916,7 @@ BINMAN
|
||||||
M: Simon Glass <sjg@chromium.org>
|
M: Simon Glass <sjg@chromium.org>
|
||||||
M: Alper Nebi Yasak <alpernebiyasak@gmail.com>
|
M: Alper Nebi Yasak <alpernebiyasak@gmail.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
F: doc/develop/binman_tests.rst
|
||||||
F: tools/binman/
|
F: tools/binman/
|
||||||
|
|
||||||
BLKMAP
|
BLKMAP
|
||||||
|
|
|
@ -55,9 +55,10 @@ void board_init_f(ulong flag)
|
||||||
|
|
||||||
void board_boot_order(u32 *spl_boot_list)
|
void board_boot_order(u32 *spl_boot_list)
|
||||||
{
|
{
|
||||||
|
struct sandbox_state *state = state_get_current();
|
||||||
|
|
||||||
spl_boot_list[0] = BOOT_DEVICE_VBE;
|
spl_boot_list[0] = BOOT_DEVICE_VBE;
|
||||||
spl_boot_list[1] = BOOT_DEVICE_UPL;
|
spl_boot_list[1] = state->upl ? BOOT_DEVICE_UPL : BOOT_DEVICE_BOARD;
|
||||||
spl_boot_list[2] = BOOT_DEVICE_BOARD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int spl_board_load_file(struct spl_image_info *spl_image,
|
static int spl_board_load_file(struct spl_image_info *spl_image,
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
/* IDs for the menu items */
|
/* IDs for the menu items */
|
||||||
item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2
|
item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2
|
||||||
ID_CPU_SPEED_3>;
|
ID_CPU_SPEED_3>;
|
||||||
|
|
||||||
|
/* values for the menu items */
|
||||||
|
item-value = <0 3 6>;
|
||||||
};
|
};
|
||||||
|
|
||||||
power-loss {
|
power-loss {
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
&sandbox_pmic {
|
&sandbox_pmic {
|
||||||
compatible = "sandbox,pmic";
|
compatible = "sandbox,pmic";
|
||||||
|
sandbox,emul = <&emul_pmic0>;
|
||||||
|
|
||||||
buck1 {
|
buck1 {
|
||||||
regulator-name = "SUPPLY_1.2V";
|
regulator-name = "SUPPLY_1.2V";
|
||||||
|
|
|
@ -88,18 +88,6 @@ int checkcpu(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
|
||||||
{
|
|
||||||
char processor_name[CPU_MAX_NAME_LEN];
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
/* Print processor name */
|
|
||||||
name = cpu_get_name(processor_name);
|
|
||||||
printf("CPU: %s\n", name);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void board_debug_uart_init(void)
|
void board_debug_uart_init(void)
|
||||||
{
|
{
|
||||||
/* com1 / com2 decode range */
|
/* com1 / com2 decode range */
|
||||||
|
|
|
@ -38,16 +38,6 @@ int arch_cpu_init(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int checkcpu(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
|
||||||
{
|
|
||||||
return default_print_cpuinfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void board_final_init(void)
|
static void board_final_init(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -82,6 +72,8 @@ static void board_final_init(void)
|
||||||
|
|
||||||
static int last_stage_init(void)
|
static int last_stage_init(void)
|
||||||
{
|
{
|
||||||
|
timestamp_add_to_bootstage();
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_XPL_BUILD))
|
if (IS_ENABLED(CONFIG_XPL_BUILD))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <bootstage.h>
|
#include <bootstage.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <asm/arch/timestamp.h>
|
#include <asm/arch/timestamp.h>
|
||||||
#include <asm/cb_sysinfo.h>
|
#include <asm/cb_sysinfo.h>
|
||||||
#include <asm/u-boot-x86.h>
|
#include <asm/u-boot-x86.h>
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
|
|
||||||
static struct timestamp_table *ts_table __section(".data");
|
|
||||||
|
|
||||||
void timestamp_init(void)
|
void timestamp_init(void)
|
||||||
{
|
{
|
||||||
timestamp_add_now(TS_U_BOOT_INITTED);
|
timestamp_add_now(TS_U_BOOT_INITTED);
|
||||||
|
@ -20,6 +19,8 @@ void timestamp_init(void)
|
||||||
|
|
||||||
void timestamp_add(enum timestamp_id id, uint64_t ts_time)
|
void timestamp_add(enum timestamp_id id, uint64_t ts_time)
|
||||||
{
|
{
|
||||||
|
const struct sysinfo_t *info = cb_get_sysinfo();
|
||||||
|
struct timestamp_table *ts_table = info->tstamp_table;
|
||||||
struct timestamp_entry *tse;
|
struct timestamp_entry *tse;
|
||||||
|
|
||||||
if (!ts_table || (ts_table->num_entries == ts_table->max_entries))
|
if (!ts_table || (ts_table->num_entries == ts_table->max_entries))
|
||||||
|
@ -37,13 +38,15 @@ void timestamp_add_now(enum timestamp_id id)
|
||||||
|
|
||||||
int timestamp_add_to_bootstage(void)
|
int timestamp_add_to_bootstage(void)
|
||||||
{
|
{
|
||||||
|
const struct sysinfo_t *info = cb_get_sysinfo();
|
||||||
|
const struct timestamp_table *ts_table = info->tstamp_table;
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
if (!ts_table)
|
if (!ts_table)
|
||||||
return -1;
|
return -ENOENT;
|
||||||
|
|
||||||
for (i = 0; i < ts_table->num_entries; i++) {
|
for (i = 0; i < ts_table->num_entries; i++) {
|
||||||
struct timestamp_entry *tse = &ts_table->entries[i];
|
const struct timestamp_entry *tse = &ts_table->entries[i];
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
|
|
||||||
switch (tse->entry_id) {
|
switch (tse->entry_id) {
|
||||||
|
|
|
@ -163,8 +163,11 @@ char *cpu_get_name(char *name)
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int default_print_cpuinfo(void)
|
#if !CONFIG_IS_ENABLED(CPU)
|
||||||
|
int print_cpuinfo(void)
|
||||||
{
|
{
|
||||||
|
post_code(POST_CPU_INFO);
|
||||||
|
|
||||||
printf("CPU: %s, vendor %s, device %xh\n",
|
printf("CPU: %s, vendor %s, device %xh\n",
|
||||||
cpu_has_64bit() ? "x86_64" : "x86",
|
cpu_has_64bit() ? "x86_64" : "x86",
|
||||||
cpu_vendor_name(gd->arch.x86_vendor), gd->arch.x86_device);
|
cpu_vendor_name(gd->arch.x86_vendor), gd->arch.x86_device);
|
||||||
|
@ -176,6 +179,7 @@ int default_print_cpuinfo(void)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(SHOW_BOOT_PROGRESS)
|
#if CONFIG_IS_ENABLED(SHOW_BOOT_PROGRESS)
|
||||||
void show_boot_progress(int val)
|
void show_boot_progress(int val)
|
||||||
|
@ -336,7 +340,7 @@ int reserve_arch(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
long detect_coreboot_table_at(ulong start, ulong size)
|
static long detect_coreboot_table_at(ulong start, ulong size)
|
||||||
{
|
{
|
||||||
u32 *ptr, *end;
|
u32 *ptr, *end;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
#include <asm/cpu_x86.h>
|
||||||
#include <asm/global_data.h>
|
#include <asm/global_data.h>
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
|
@ -19,11 +19,6 @@ int checkcpu(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
|
||||||
{
|
|
||||||
return default_print_cpuinfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
void board_final_init(void)
|
void board_final_init(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,11 +144,6 @@ int checkcpu(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
|
||||||
{
|
|
||||||
return default_print_cpuinfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find any available tables and copy them to a safe place */
|
/* Find any available tables and copy them to a safe place */
|
||||||
int reserve_arch(void)
|
int reserve_arch(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -263,6 +263,49 @@ static int build_vendor_name(char *vendor_name)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int x86_cpu_vendor_info(char *name)
|
||||||
|
{
|
||||||
|
uint cpu_device;
|
||||||
|
|
||||||
|
cpu_device = 0;
|
||||||
|
|
||||||
|
/* gcc 7.3 does not want to drop x86_vendors, so use #ifdef */
|
||||||
|
#ifndef CONFIG_TPL_BUILD
|
||||||
|
*name = '\0'; /* Unset */
|
||||||
|
|
||||||
|
/* Find the id and vendor_name */
|
||||||
|
if (!has_cpuid()) {
|
||||||
|
/* Its a 486 if we can modify the AC flag */
|
||||||
|
if (flag_is_changeable_p(X86_EFLAGS_AC))
|
||||||
|
cpu_device = 0x00000400; /* 486 */
|
||||||
|
else
|
||||||
|
cpu_device = 0x00000300; /* 386 */
|
||||||
|
if (cpu_device == 0x00000400 && test_cyrix_52div()) {
|
||||||
|
/* If we ever care we can enable cpuid here */
|
||||||
|
memcpy(name, "CyrixInstead", 13);
|
||||||
|
|
||||||
|
/* Detect NexGen with old hypercode */
|
||||||
|
} else if (deep_magic_nexgen_probe()) {
|
||||||
|
memcpy(name, "NexGenDriven", 13);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int cpuid_level;
|
||||||
|
|
||||||
|
cpuid_level = build_vendor_name(name);
|
||||||
|
name[12] = '\0';
|
||||||
|
|
||||||
|
/* Intel-defined flags: level 0x00000001 */
|
||||||
|
if (cpuid_level >= 0x00000001)
|
||||||
|
cpu_device = cpuid_eax(0x00000001);
|
||||||
|
else
|
||||||
|
/* Have CPUID level 0 only unheard of */
|
||||||
|
cpu_device = 0x00000400;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TPL_BUILD */
|
||||||
|
|
||||||
|
return cpu_device;
|
||||||
|
}
|
||||||
|
|
||||||
static void identify_cpu(struct cpu_device_id *cpu)
|
static void identify_cpu(struct cpu_device_id *cpu)
|
||||||
{
|
{
|
||||||
cpu->device = 0; /* fix gcc 4.4.4 warning */
|
cpu->device = 0; /* fix gcc 4.4.4 warning */
|
||||||
|
@ -289,41 +332,13 @@ static void identify_cpu(struct cpu_device_id *cpu)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gcc 7.3 does not want to drop x86_vendors, so use #ifdef */
|
|
||||||
#ifndef CONFIG_TPL_BUILD
|
#ifndef CONFIG_TPL_BUILD
|
||||||
|
{
|
||||||
char vendor_name[16];
|
char vendor_name[16];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
vendor_name[0] = '\0'; /* Unset */
|
cpu->device = x86_cpu_vendor_info(vendor_name);
|
||||||
|
|
||||||
/* Find the id and vendor_name */
|
|
||||||
if (!has_cpuid()) {
|
|
||||||
/* Its a 486 if we can modify the AC flag */
|
|
||||||
if (flag_is_changeable_p(X86_EFLAGS_AC))
|
|
||||||
cpu->device = 0x00000400; /* 486 */
|
|
||||||
else
|
|
||||||
cpu->device = 0x00000300; /* 386 */
|
|
||||||
if ((cpu->device == 0x00000400) && test_cyrix_52div()) {
|
|
||||||
memcpy(vendor_name, "CyrixInstead", 13);
|
|
||||||
/* If we ever care we can enable cpuid here */
|
|
||||||
}
|
|
||||||
/* Detect NexGen with old hypercode */
|
|
||||||
else if (deep_magic_nexgen_probe())
|
|
||||||
memcpy(vendor_name, "NexGenDriven", 13);
|
|
||||||
} else {
|
|
||||||
int cpuid_level;
|
|
||||||
|
|
||||||
cpuid_level = build_vendor_name(vendor_name);
|
|
||||||
vendor_name[12] = '\0';
|
|
||||||
|
|
||||||
/* Intel-defined flags: level 0x00000001 */
|
|
||||||
if (cpuid_level >= 0x00000001) {
|
|
||||||
cpu->device = cpuid_eax(0x00000001);
|
|
||||||
} else {
|
|
||||||
/* Have CPUID level 0 only unheard of */
|
|
||||||
cpu->device = 0x00000400;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cpu->vendor = X86_VENDOR_UNKNOWN;
|
cpu->vendor = X86_VENDOR_UNKNOWN;
|
||||||
for (i = 0; i < ARRAY_SIZE(x86_vendors); i++) {
|
for (i = 0; i < ARRAY_SIZE(x86_vendors); i++) {
|
||||||
if (memcmp(vendor_name, x86_vendors[i].name, 12) == 0) {
|
if (memcmp(vendor_name, x86_vendors[i].name, 12) == 0) {
|
||||||
|
@ -331,6 +346,7 @@ static void identify_cpu(struct cpu_device_id *cpu)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,6 +501,11 @@ int x86_cpu_reinit_f(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void x86_get_identity_for_timer(void)
|
||||||
|
{
|
||||||
|
setup_identity();
|
||||||
|
}
|
||||||
|
|
||||||
void x86_enable_caches(void)
|
void x86_enable_caches(void)
|
||||||
{
|
{
|
||||||
unsigned long cr0;
|
unsigned long cr0;
|
||||||
|
|
|
@ -237,7 +237,7 @@ void *x86_get_idt(void)
|
||||||
return &idt_ptr;
|
return &idt_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __do_irq(int irq)
|
static void __do_irq(int irq)
|
||||||
{
|
{
|
||||||
printf("Unhandled IRQ : %d\n", irq);
|
printf("Unhandled IRQ : %d\n", irq);
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,20 +182,6 @@ int checkcpu(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
|
||||||
{
|
|
||||||
char processor_name[CPU_MAX_NAME_LEN];
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
/* Print processor name */
|
|
||||||
name = cpu_get_name(processor_name);
|
|
||||||
printf("CPU: %s\n", name);
|
|
||||||
|
|
||||||
post_code(POST_CPU_INFO);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void board_debug_uart_init(void)
|
void board_debug_uart_init(void)
|
||||||
{
|
{
|
||||||
/* This enables the debug UART */
|
/* This enables the debug UART */
|
||||||
|
|
|
@ -87,7 +87,7 @@ void mtrr_read_all(struct mtrr_info *info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mtrr_write_all(struct mtrr_info *info)
|
static void mtrr_write_all(struct mtrr_info *info)
|
||||||
{
|
{
|
||||||
int reg_count = mtrr_get_var_count();
|
int reg_count = mtrr_get_var_count();
|
||||||
struct mtrr_state state;
|
struct mtrr_state state;
|
||||||
|
|
|
@ -109,12 +109,6 @@ int checkcpu(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
|
||||||
{
|
|
||||||
post_code(POST_CPU_INFO);
|
|
||||||
return default_print_cpuinfo();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int arch_early_init_r(void)
|
int arch_early_init_r(void)
|
||||||
|
|
|
@ -266,12 +266,6 @@ int checkcpu(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
|
||||||
{
|
|
||||||
post_code(POST_CPU_INFO);
|
|
||||||
return default_print_cpuinfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void quark_pcie_init(void)
|
static void quark_pcie_init(void)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
|
@ -54,8 +54,3 @@ int checkcpu(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
|
||||||
{
|
|
||||||
return default_print_cpuinfo();
|
|
||||||
}
|
|
||||||
|
|
|
@ -19,8 +19,3 @@ int checkcpu(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
|
||||||
{
|
|
||||||
return default_print_cpuinfo();
|
|
||||||
}
|
|
||||||
|
|
|
@ -75,3 +75,9 @@ void board_debug_uart_init(void)
|
||||||
/* this was already done in SPL */
|
/* this was already done in SPL */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void x86_get_identity_for_timer(void)
|
||||||
|
{
|
||||||
|
/* set the vendor to Intel so that native_calibrate_tsc() works */
|
||||||
|
gd->arch.x86_vendor = X86_VENDOR_INTEL;
|
||||||
|
}
|
||||||
|
|
|
@ -32,9 +32,4 @@ int checkcpu(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -293,4 +293,11 @@ u32 cpu_get_stepping(void);
|
||||||
*/
|
*/
|
||||||
int cpu_phys_address_size(void);
|
int cpu_phys_address_size(void);
|
||||||
|
|
||||||
|
void board_final_init(void);
|
||||||
|
void board_final_cleanup(void);
|
||||||
|
|
||||||
|
#ifndef CONFIG_EFI_STUB
|
||||||
|
int reserve_arch(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,6 +43,15 @@ int x86_cpu_reinit_f(void);
|
||||||
*/
|
*/
|
||||||
int x86_cpu_init_tpl(void);
|
int x86_cpu_init_tpl(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* x86_get_identity_for_timer() - Set up CPU identity for use by the early timer
|
||||||
|
*
|
||||||
|
* The timer can be needed early in board_f if bootstage is enabled. This
|
||||||
|
* function can be called from the TSC timer to make sure that the CPU-identity
|
||||||
|
* info has been set up
|
||||||
|
*/
|
||||||
|
void x86_get_identity_for_timer(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cpu_reinit_fpu() - Reinit the FPU if something is wrong with it
|
* cpu_reinit_fpu() - Reinit the FPU if something is wrong with it
|
||||||
*
|
*
|
||||||
|
@ -51,6 +60,14 @@ int x86_cpu_init_tpl(void);
|
||||||
*/
|
*/
|
||||||
void cpu_reinit_fpu(void);
|
void cpu_reinit_fpu(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* x86_cpu_vendor_info() - Get the CPU-vendor name and device number
|
||||||
|
*
|
||||||
|
* @name: 13-byte area to hold the returned string
|
||||||
|
* Return: CPU device number read from cpuid
|
||||||
|
*/
|
||||||
|
int x86_cpu_vendor_info(char *name);
|
||||||
|
|
||||||
int cpu_init_f(void);
|
int cpu_init_f(void);
|
||||||
void setup_gdt(struct global_data *id, u64 *gdt_addr);
|
void setup_gdt(struct global_data *id, u64 *gdt_addr);
|
||||||
/*
|
/*
|
||||||
|
@ -78,7 +95,6 @@ void x86_enable_caches(void);
|
||||||
void x86_disable_caches(void);
|
void x86_disable_caches(void);
|
||||||
int x86_init_cache(void);
|
int x86_init_cache(void);
|
||||||
phys_addr_t board_get_usable_ram_top(phys_size_t total_size);
|
phys_addr_t board_get_usable_ram_top(phys_size_t total_size);
|
||||||
int default_print_cpuinfo(void);
|
|
||||||
|
|
||||||
/* Set up a UART which can be used with printch(), printhex8(), etc. */
|
/* Set up a UART which can be used with printch(), printhex8(), etc. */
|
||||||
int setup_internal_uart(int enable);
|
int setup_internal_uart(int enable);
|
||||||
|
|
|
@ -19,7 +19,12 @@ void arch_print_bdinfo(void)
|
||||||
bdinfo_print_num_l("clock_rate", gd->arch.clock_rate);
|
bdinfo_print_num_l("clock_rate", gd->arch.clock_rate);
|
||||||
bdinfo_print_num_l("tsc_base", gd->arch.tsc_base);
|
bdinfo_print_num_l("tsc_base", gd->arch.tsc_base);
|
||||||
bdinfo_print_num_l("vendor", gd->arch.x86_vendor);
|
bdinfo_print_num_l("vendor", gd->arch.x86_vendor);
|
||||||
bdinfo_print_str(" name", cpu_vendor_name(gd->arch.x86_vendor));
|
if (!IS_ENABLED(CONFIG_X86_64)) {
|
||||||
|
char vendor_name[16];
|
||||||
|
|
||||||
|
x86_cpu_vendor_info(vendor_name);
|
||||||
|
bdinfo_print_str(" name", vendor_name);
|
||||||
|
}
|
||||||
bdinfo_print_num_l("model", gd->arch.x86_model);
|
bdinfo_print_num_l("model", gd->arch.x86_model);
|
||||||
bdinfo_print_num_l("phys_addr in bits", cpu_phys_address_size());
|
bdinfo_print_num_l("phys_addr in bits", cpu_phys_address_size());
|
||||||
bdinfo_print_num_l("table start", gd->arch.table_start);
|
bdinfo_print_num_l("table start", gd->arch.table_start);
|
||||||
|
|
|
@ -26,12 +26,6 @@ int checkcpu(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
|
||||||
{
|
|
||||||
post_code(POST_CPU_INFO);
|
|
||||||
return default_print_cpuinfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
int fsp_init_phase_pci(void)
|
int fsp_init_phase_pci(void)
|
||||||
{
|
{
|
||||||
u32 status;
|
u32 status;
|
||||||
|
|
|
@ -434,6 +434,9 @@ int bootdev_find_by_label(const char *label, struct udevice **devp,
|
||||||
struct uclass *uc;
|
struct uclass *uc;
|
||||||
enum uclass_id id;
|
enum uclass_id id;
|
||||||
|
|
||||||
|
if (!CONFIG_IS_ENABLED(BLK))
|
||||||
|
return -ENOSYS;
|
||||||
|
|
||||||
ret = label_to_uclass(label, &seq, &method_flags);
|
ret = label_to_uclass(label, &seq, &method_flags);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return log_msg_ret("uc", ret);
|
return log_msg_ret("uc", ret);
|
||||||
|
|
189
boot/cedit.c
189
boot/cedit.c
|
@ -51,10 +51,11 @@ struct cedit_iter_priv {
|
||||||
|
|
||||||
int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
|
int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
|
||||||
{
|
{
|
||||||
|
struct expo_arrange_info arr;
|
||||||
struct scene_obj_txt *txt;
|
struct scene_obj_txt *txt;
|
||||||
struct scene_obj *obj;
|
struct scene_obj *obj;
|
||||||
struct scene *scn;
|
struct scene *scn;
|
||||||
int y;
|
int y, ret;
|
||||||
|
|
||||||
scn = expo_lookup_scene_id(exp, scene_id);
|
scn = expo_lookup_scene_id(exp, scene_id);
|
||||||
if (!scn)
|
if (!scn)
|
||||||
|
@ -68,6 +69,11 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
|
||||||
if (txt)
|
if (txt)
|
||||||
scene_obj_set_pos(scn, txt->obj.id, 200, 10);
|
scene_obj_set_pos(scn, txt->obj.id, 200, 10);
|
||||||
|
|
||||||
|
memset(&arr, '\0', sizeof(arr));
|
||||||
|
ret = scene_calc_arrange(scn, &arr);
|
||||||
|
if (ret < 0)
|
||||||
|
return log_msg_ret("arr", ret);
|
||||||
|
|
||||||
y = 100;
|
y = 100;
|
||||||
list_for_each_entry(obj, &scn->obj_head, sibling) {
|
list_for_each_entry(obj, &scn->obj_head, sibling) {
|
||||||
switch (obj->type) {
|
switch (obj->type) {
|
||||||
|
@ -77,12 +83,13 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
|
||||||
break;
|
break;
|
||||||
case SCENEOBJT_MENU:
|
case SCENEOBJT_MENU:
|
||||||
scene_obj_set_pos(scn, obj->id, 50, y);
|
scene_obj_set_pos(scn, obj->id, 50, y);
|
||||||
scene_menu_arrange(scn, (struct scene_obj_menu *)obj);
|
scene_menu_arrange(scn, &arr,
|
||||||
|
(struct scene_obj_menu *)obj);
|
||||||
y += 50;
|
y += 50;
|
||||||
break;
|
break;
|
||||||
case SCENEOBJT_TEXTLINE:
|
case SCENEOBJT_TEXTLINE:
|
||||||
scene_obj_set_pos(scn, obj->id, 50, y);
|
scene_obj_set_pos(scn, obj->id, 50, y);
|
||||||
scene_textline_arrange(scn,
|
scene_textline_arrange(scn, &arr,
|
||||||
(struct scene_obj_textline *)obj);
|
(struct scene_obj_textline *)obj);
|
||||||
y += 50;
|
y += 50;
|
||||||
break;
|
break;
|
||||||
|
@ -147,7 +154,7 @@ int cedit_run(struct expo *exp)
|
||||||
struct video_priv *vid_priv;
|
struct video_priv *vid_priv;
|
||||||
uint scene_id;
|
uint scene_id;
|
||||||
struct scene *scn;
|
struct scene *scn;
|
||||||
bool done;
|
bool done, save;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cli_ch_init(cch);
|
cli_ch_init(cch);
|
||||||
|
@ -157,6 +164,7 @@ int cedit_run(struct expo *exp)
|
||||||
scene_id = ret;
|
scene_id = ret;
|
||||||
|
|
||||||
done = false;
|
done = false;
|
||||||
|
save = false;
|
||||||
do {
|
do {
|
||||||
struct expo_action act;
|
struct expo_action act;
|
||||||
int ichar, key;
|
int ichar, key;
|
||||||
|
@ -201,6 +209,15 @@ int cedit_run(struct expo *exp)
|
||||||
case EXPOACT_OPEN:
|
case EXPOACT_OPEN:
|
||||||
scene_set_open(scn, act.select.id, true);
|
scene_set_open(scn, act.select.id, true);
|
||||||
cedit_arange(exp, vid_priv, scene_id);
|
cedit_arange(exp, vid_priv, scene_id);
|
||||||
|
switch (scn->highlight_id) {
|
||||||
|
case EXPOID_SAVE:
|
||||||
|
done = true;
|
||||||
|
save = true;
|
||||||
|
break;
|
||||||
|
case EXPOID_DISCARD:
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EXPOACT_CLOSE:
|
case EXPOACT_CLOSE:
|
||||||
scene_set_open(scn, act.select.id, false);
|
scene_set_open(scn, act.select.id, false);
|
||||||
|
@ -222,6 +239,8 @@ int cedit_run(struct expo *exp)
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return log_msg_ret("end", ret);
|
return log_msg_ret("end", ret);
|
||||||
|
if (!save)
|
||||||
|
return -EACCES;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -274,14 +293,84 @@ static int get_cur_menuitem_text(const struct scene_obj_menu *menu,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_cur_menuitem_val() - Get the value of a menu's current item
|
||||||
|
*
|
||||||
|
* Obtains the value of the current item in the menu. If no value, then
|
||||||
|
* enumerates the items of a menu (0, 1, 2) and returns the sequence number of
|
||||||
|
* the currently selected item. If the first item is selected, this returns 0;
|
||||||
|
* if the second, 1; etc.
|
||||||
|
*
|
||||||
|
* @menu: Menu to check
|
||||||
|
* @valp: Returns current-item value / sequence number
|
||||||
|
* Return: 0 on success, else -ve error value
|
||||||
|
*/
|
||||||
|
static int get_cur_menuitem_val(const struct scene_obj_menu *menu, int *valp)
|
||||||
|
{
|
||||||
|
const struct scene_menitem *mi;
|
||||||
|
int seq;
|
||||||
|
|
||||||
|
seq = 0;
|
||||||
|
list_for_each_entry(mi, &menu->item_head, sibling) {
|
||||||
|
if (mi->id == menu->cur_item_id) {
|
||||||
|
*valp = mi->value == INT_MAX ? seq : mi->value;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
seq++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return log_msg_ret("nf", -ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write_dt_string() - Write a string to the devicetree, expanding if needed
|
||||||
|
*
|
||||||
|
* If this fails, it tries again after expanding the devicetree a little
|
||||||
|
*
|
||||||
|
* @buf: Buffer containing the devicetree
|
||||||
|
* @name: Property name to use
|
||||||
|
* @str: String value
|
||||||
|
* Return: 0 if OK, -EFAULT if something went horribly wrong
|
||||||
|
*/
|
||||||
static int write_dt_string(struct abuf *buf, const char *name, const char *str)
|
static int write_dt_string(struct abuf *buf, const char *name, const char *str)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
|
ret = -EAGAIN;
|
||||||
|
for (i = 0; ret && i < 2; i++) {
|
||||||
|
ret = fdt_property_string(abuf_data(buf), name, str);
|
||||||
|
if (!i) {
|
||||||
|
ret = check_space(ret, buf);
|
||||||
|
if (ret)
|
||||||
|
return log_msg_ret("rs2", -ENOMEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this should not happen */
|
||||||
|
if (ret)
|
||||||
|
return log_msg_ret("str", -EFAULT);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write_dt_u32() - Write an int to the devicetree, expanding if needed
|
||||||
|
*
|
||||||
|
* If this fails, it tries again after expanding the devicetree a little
|
||||||
|
*
|
||||||
|
* @buf: Buffer containing the devicetree
|
||||||
|
* @name: Property name to use
|
||||||
|
* @lva: Integer value
|
||||||
|
* Return: 0 if OK, -EFAULT if something went horribly wrong
|
||||||
|
*/
|
||||||
|
static int write_dt_u32(struct abuf *buf, const char *name, uint val)
|
||||||
|
{
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
/* write the text of the current item */
|
/* write the text of the current item */
|
||||||
ret = -EAGAIN;
|
ret = -EAGAIN;
|
||||||
for (i = 0; ret && i < 2; i++) {
|
for (i = 0; ret && i < 2; i++) {
|
||||||
ret = fdt_property_string(abuf_data(buf), name, str);
|
ret = fdt_property_u32(abuf_data(buf), name, val);
|
||||||
if (!i) {
|
if (!i) {
|
||||||
ret = check_space(ret, buf);
|
ret = check_space(ret, buf);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -320,23 +409,21 @@ static int h_write_settings(struct scene_obj *obj, void *vpriv)
|
||||||
const struct scene_obj_menu *menu;
|
const struct scene_obj_menu *menu;
|
||||||
const char *str;
|
const char *str;
|
||||||
char name[80];
|
char name[80];
|
||||||
int i;
|
int val;
|
||||||
|
|
||||||
/* write the ID of the current item */
|
/* write the ID of the current item */
|
||||||
menu = (struct scene_obj_menu *)obj;
|
menu = (struct scene_obj_menu *)obj;
|
||||||
ret = -EAGAIN;
|
ret = write_dt_u32(buf, obj->name, menu->cur_item_id);
|
||||||
for (i = 0; ret && i < 2; i++) {
|
|
||||||
ret = fdt_property_u32(abuf_data(buf), obj->name,
|
|
||||||
menu->cur_item_id);
|
|
||||||
if (!i) {
|
|
||||||
ret = check_space(ret, buf);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return log_msg_ret("res", -ENOMEM);
|
return log_msg_ret("wrt", ret);
|
||||||
}
|
|
||||||
}
|
snprintf(name, sizeof(name), "%s-value", obj->name);
|
||||||
/* this should not happen */
|
ret = get_cur_menuitem_val(menu, &val);
|
||||||
|
if (ret < 0)
|
||||||
|
return log_msg_ret("cur", ret);
|
||||||
|
ret = write_dt_u32(buf, name, val);
|
||||||
if (ret)
|
if (ret)
|
||||||
return log_msg_ret("wrt", -EFAULT);
|
return log_msg_ret("wr2", ret);
|
||||||
|
|
||||||
ret = get_cur_menuitem_text(menu, &str);
|
ret = get_cur_menuitem_text(menu, &str);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -470,6 +557,9 @@ static int h_write_settings_env(struct scene_obj *obj, void *vpriv)
|
||||||
const char *str;
|
const char *str;
|
||||||
int val, ret;
|
int val, ret;
|
||||||
|
|
||||||
|
if (obj->id < EXPOID_BASE_ID)
|
||||||
|
return 0;
|
||||||
|
|
||||||
snprintf(var, sizeof(var), "c.%s", obj->name);
|
snprintf(var, sizeof(var), "c.%s", obj->name);
|
||||||
|
|
||||||
switch (obj->type) {
|
switch (obj->type) {
|
||||||
|
@ -499,6 +589,14 @@ static int h_write_settings_env(struct scene_obj *obj, void *vpriv)
|
||||||
ret = env_set(name, str);
|
ret = env_set(name, str);
|
||||||
if (ret)
|
if (ret)
|
||||||
return log_msg_ret("st2", ret);
|
return log_msg_ret("st2", ret);
|
||||||
|
|
||||||
|
ret = get_cur_menuitem_val(menu, &val);
|
||||||
|
if (ret < 0)
|
||||||
|
return log_msg_ret("cur", ret);
|
||||||
|
snprintf(name, sizeof(name), "c.%s-value", obj->name);
|
||||||
|
if (priv->verbose)
|
||||||
|
printf("%s=%d\n", name, val);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SCENEOBJT_TEXTLINE: {
|
case SCENEOBJT_TEXTLINE: {
|
||||||
const struct scene_obj_textline *tline;
|
const struct scene_obj_textline *tline;
|
||||||
|
@ -542,6 +640,9 @@ static int h_read_settings_env(struct scene_obj *obj, void *vpriv)
|
||||||
char var[60];
|
char var[60];
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
|
if (obj->id < EXPOID_BASE_ID)
|
||||||
|
return 0;
|
||||||
|
|
||||||
snprintf(var, sizeof(var), "c.%s", obj->name);
|
snprintf(var, sizeof(var), "c.%s", obj->name);
|
||||||
|
|
||||||
switch (obj->type) {
|
switch (obj->type) {
|
||||||
|
@ -559,7 +660,7 @@ static int h_read_settings_env(struct scene_obj *obj, void *vpriv)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* note that no validation is done here, to make sure the ID is
|
* note that no validation is done here, to make sure the ID is
|
||||||
* valid * and actually points to a menu item
|
* valid and actually points to a menu item
|
||||||
*/
|
*/
|
||||||
menu->cur_item_id = val;
|
menu->cur_item_id = val;
|
||||||
break;
|
break;
|
||||||
|
@ -599,55 +700,23 @@ int cedit_read_settings_env(struct expo *exp, bool verbose)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* get_cur_menuitem_seq() - Get the sequence number of a menu's current item
|
|
||||||
*
|
|
||||||
* Enumerates the items of a menu (0, 1, 2) and returns the sequence number of
|
|
||||||
* the currently selected item. If the first item is selected, this returns 0;
|
|
||||||
* if the second, 1; etc.
|
|
||||||
*
|
|
||||||
* @menu: Menu to check
|
|
||||||
* Return: Sequence number on success, else -ve error value
|
|
||||||
*/
|
|
||||||
static int get_cur_menuitem_seq(const struct scene_obj_menu *menu)
|
|
||||||
{
|
|
||||||
const struct scene_menitem *mi;
|
|
||||||
int seq, found;
|
|
||||||
|
|
||||||
seq = 0;
|
|
||||||
found = -1;
|
|
||||||
list_for_each_entry(mi, &menu->item_head, sibling) {
|
|
||||||
if (mi->id == menu->cur_item_id) {
|
|
||||||
found = seq;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
seq++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found == -1)
|
|
||||||
return log_msg_ret("nf", -ENOENT);
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int h_write_settings_cmos(struct scene_obj *obj, void *vpriv)
|
static int h_write_settings_cmos(struct scene_obj *obj, void *vpriv)
|
||||||
{
|
{
|
||||||
const struct scene_obj_menu *menu;
|
const struct scene_obj_menu *menu;
|
||||||
struct cedit_iter_priv *priv = vpriv;
|
struct cedit_iter_priv *priv = vpriv;
|
||||||
int val, ret;
|
int val, ret;
|
||||||
uint i, seq;
|
uint i;
|
||||||
|
|
||||||
if (obj->type != SCENEOBJT_MENU)
|
if (obj->type != SCENEOBJT_MENU || obj->id < EXPOID_BASE_ID)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
menu = (struct scene_obj_menu *)obj;
|
menu = (struct scene_obj_menu *)obj;
|
||||||
val = menu->cur_item_id;
|
val = menu->cur_item_id;
|
||||||
|
|
||||||
ret = get_cur_menuitem_seq(menu);
|
ret = get_cur_menuitem_val(menu, &val);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return log_msg_ret("cur", ret);
|
return log_msg_ret("cur", ret);
|
||||||
seq = ret;
|
log_debug("%s: val=%d\n", menu->obj.name, val);
|
||||||
log_debug("%s: seq=%d\n", menu->obj.name, seq);
|
|
||||||
|
|
||||||
/* figure out where to place this item */
|
/* figure out where to place this item */
|
||||||
if (!obj->bit_length)
|
if (!obj->bit_length)
|
||||||
|
@ -655,11 +724,11 @@ static int h_write_settings_cmos(struct scene_obj *obj, void *vpriv)
|
||||||
if (obj->start_bit + obj->bit_length > CMOS_MAX_BITS)
|
if (obj->start_bit + obj->bit_length > CMOS_MAX_BITS)
|
||||||
return log_msg_ret("bit", -E2BIG);
|
return log_msg_ret("bit", -E2BIG);
|
||||||
|
|
||||||
for (i = 0; i < obj->bit_length; i++, seq >>= 1) {
|
for (i = 0; i < obj->bit_length; i++, val >>= 1) {
|
||||||
uint bitnum = obj->start_bit + i;
|
uint bitnum = obj->start_bit + i;
|
||||||
|
|
||||||
priv->mask[CMOS_BYTE(bitnum)] |= 1 << CMOS_BIT(bitnum);
|
priv->mask[CMOS_BYTE(bitnum)] |= 1 << CMOS_BIT(bitnum);
|
||||||
if (seq & 1)
|
if (val & 1)
|
||||||
priv->value[CMOS_BYTE(bitnum)] |= BIT(CMOS_BIT(bitnum));
|
priv->value[CMOS_BYTE(bitnum)] |= BIT(CMOS_BIT(bitnum));
|
||||||
log_debug("bit %x %x %x\n", bitnum,
|
log_debug("bit %x %x %x\n", bitnum,
|
||||||
priv->mask[CMOS_BYTE(bitnum)],
|
priv->mask[CMOS_BYTE(bitnum)],
|
||||||
|
@ -693,6 +762,7 @@ int cedit_write_settings_cmos(struct expo *exp, struct udevice *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write the data to the RTC */
|
/* write the data to the RTC */
|
||||||
|
log_debug("Writing CMOS\n");
|
||||||
first = CMOS_MAX_BYTES;
|
first = CMOS_MAX_BYTES;
|
||||||
last = -1;
|
last = -1;
|
||||||
for (i = 0, count = 0; i < CMOS_MAX_BYTES; i++) {
|
for (i = 0, count = 0; i < CMOS_MAX_BYTES; i++) {
|
||||||
|
@ -727,7 +797,7 @@ static int h_read_settings_cmos(struct scene_obj *obj, void *vpriv)
|
||||||
int val, ret;
|
int val, ret;
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
if (obj->type != SCENEOBJT_MENU)
|
if (obj->type != SCENEOBJT_MENU || obj->id < EXPOID_BASE_ID)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
menu = (struct scene_obj_menu *)obj;
|
menu = (struct scene_obj_menu *)obj;
|
||||||
|
@ -760,7 +830,8 @@ static int h_read_settings_cmos(struct scene_obj *obj, void *vpriv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update the current item */
|
/* update the current item */
|
||||||
mi = scene_menuitem_find_seq(menu, val);
|
log_debug("look for menuitem value %d in menu %d\n", val, menu->obj.id);
|
||||||
|
mi = scene_menuitem_find_val(menu, val);
|
||||||
if (!mi)
|
if (!mi)
|
||||||
return log_msg_ret("seq", -ENOENT);
|
return log_msg_ret("seq", -ENOENT);
|
||||||
|
|
||||||
|
@ -794,7 +865,7 @@ int cedit_read_settings_cmos(struct expo *exp, struct udevice *dev,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read the data to the RTC */
|
/* indicate what bytes were read from the RTC */
|
||||||
first = CMOS_MAX_BYTES;
|
first = CMOS_MAX_BYTES;
|
||||||
last = -1;
|
last = -1;
|
||||||
for (i = 0, count = 0; i < CMOS_MAX_BYTES; i++) {
|
for (i = 0, count = 0; i < CMOS_MAX_BYTES; i++) {
|
||||||
|
|
|
@ -29,6 +29,7 @@ int expo_new(const char *name, void *priv, struct expo **expp)
|
||||||
exp->priv = priv;
|
exp->priv = priv;
|
||||||
INIT_LIST_HEAD(&exp->scene_head);
|
INIT_LIST_HEAD(&exp->scene_head);
|
||||||
INIT_LIST_HEAD(&exp->str_head);
|
INIT_LIST_HEAD(&exp->str_head);
|
||||||
|
exp->next_id = EXPOID_BASE_ID;
|
||||||
|
|
||||||
*expp = exp;
|
*expp = exp;
|
||||||
|
|
||||||
|
@ -258,6 +259,8 @@ int expo_apply_theme(struct expo *exp, ofnode node)
|
||||||
ofnode_read_u32(node, "font-size", &theme->font_size);
|
ofnode_read_u32(node, "font-size", &theme->font_size);
|
||||||
ofnode_read_u32(node, "menu-inset", &theme->menu_inset);
|
ofnode_read_u32(node, "menu-inset", &theme->menu_inset);
|
||||||
ofnode_read_u32(node, "menuitem-gap-y", &theme->menuitem_gap_y);
|
ofnode_read_u32(node, "menuitem-gap-y", &theme->menuitem_gap_y);
|
||||||
|
ofnode_read_u32(node, "menu-title-margin-x",
|
||||||
|
&theme->menu_title_margin_x);
|
||||||
|
|
||||||
list_for_each_entry(scn, &exp->scene_head, sibling) {
|
list_for_each_entry(scn, &exp->scene_head, sibling) {
|
||||||
ret = scene_apply_theme(scn, theme);
|
ret = scene_apply_theme(scn, theme);
|
||||||
|
|
|
@ -46,7 +46,6 @@ int add_txt_str(struct build_info *info, ofnode node, struct scene *scn,
|
||||||
const char *find_name, uint obj_id)
|
const char *find_name, uint obj_id)
|
||||||
{
|
{
|
||||||
const char *text;
|
const char *text;
|
||||||
uint str_id;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
info->err_prop = find_name;
|
info->err_prop = find_name;
|
||||||
|
@ -67,12 +66,7 @@ int add_txt_str(struct build_info *info, ofnode node, struct scene *scn,
|
||||||
return log_msg_ret("id", -EINVAL);
|
return log_msg_ret("id", -EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = expo_str(scn->expo, find_name, 0, text);
|
ret = scene_txt_str(scn, find_name, obj_id, 0, text, NULL);
|
||||||
if (ret < 0)
|
|
||||||
return log_msg_ret("add", ret);
|
|
||||||
str_id = ret;
|
|
||||||
|
|
||||||
ret = scene_txt_str(scn, find_name, obj_id, str_id, text, NULL);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return log_msg_ret("add", ret);
|
return log_msg_ret("add", ret);
|
||||||
|
|
||||||
|
@ -94,7 +88,6 @@ int add_txt_str_list(struct build_info *info, ofnode node, struct scene *scn,
|
||||||
const char *find_name, int index, uint obj_id)
|
const char *find_name, int index, uint obj_id)
|
||||||
{
|
{
|
||||||
const char *text;
|
const char *text;
|
||||||
uint str_id;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ofnode_read_string_index(node, find_name, index, &text);
|
ret = ofnode_read_string_index(node, find_name, index, &text);
|
||||||
|
@ -114,12 +107,7 @@ int add_txt_str_list(struct build_info *info, ofnode node, struct scene *scn,
|
||||||
return log_msg_ret("id", -EINVAL);
|
return log_msg_ret("id", -EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = expo_str(scn->expo, find_name, 0, text);
|
ret = scene_txt_str(scn, find_name, obj_id, 0, text, NULL);
|
||||||
if (ret < 0)
|
|
||||||
return log_msg_ret("add", ret);
|
|
||||||
str_id = ret;
|
|
||||||
|
|
||||||
ret = scene_txt_str(scn, find_name, obj_id, str_id, text, NULL);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return log_msg_ret("add", ret);
|
return log_msg_ret("add", ret);
|
||||||
|
|
||||||
|
@ -227,10 +215,10 @@ static void list_strings(struct build_info *info)
|
||||||
static int menu_build(struct build_info *info, ofnode node, struct scene *scn,
|
static int menu_build(struct build_info *info, ofnode node, struct scene *scn,
|
||||||
uint id, struct scene_obj **objp)
|
uint id, struct scene_obj **objp)
|
||||||
{
|
{
|
||||||
|
const u32 *item_ids, *item_values;
|
||||||
struct scene_obj_menu *menu;
|
struct scene_obj_menu *menu;
|
||||||
|
int ret, size, i, num_items;
|
||||||
uint title_id, menu_id;
|
uint title_id, menu_id;
|
||||||
const u32 *item_ids;
|
|
||||||
int ret, size, i;
|
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
name = ofnode_get_name(node);
|
name = ofnode_get_name(node);
|
||||||
|
@ -254,9 +242,15 @@ static int menu_build(struct build_info *info, ofnode node, struct scene *scn,
|
||||||
return log_msg_ret("itm", -EINVAL);
|
return log_msg_ret("itm", -EINVAL);
|
||||||
if (!size || size % sizeof(u32))
|
if (!size || size % sizeof(u32))
|
||||||
return log_msg_ret("isz", -EINVAL);
|
return log_msg_ret("isz", -EINVAL);
|
||||||
size /= sizeof(u32);
|
num_items = size / sizeof(u32);
|
||||||
|
|
||||||
for (i = 0; i < size; i++) {
|
item_values = ofnode_read_prop(node, "item-value", &size);
|
||||||
|
if (item_values) {
|
||||||
|
if (size != num_items * sizeof(u32))
|
||||||
|
return log_msg_ret("vsz", -EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_items; i++) {
|
||||||
struct scene_menitem *item;
|
struct scene_menitem *item;
|
||||||
uint label, key, desc;
|
uint label, key, desc;
|
||||||
|
|
||||||
|
@ -280,6 +274,8 @@ static int menu_build(struct build_info *info, ofnode node, struct scene *scn,
|
||||||
desc, 0, 0, &item);
|
desc, 0, 0, &item);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return log_msg_ret("mi", ret);
|
return log_msg_ret("mi", ret);
|
||||||
|
if (item_values)
|
||||||
|
item->value = fdt32_to_cpu(item_values[i]);
|
||||||
}
|
}
|
||||||
*objp = &menu->obj;
|
*objp = &menu->obj;
|
||||||
|
|
||||||
|
@ -408,7 +404,7 @@ static int scene_build(struct build_info *info, ofnode scn_node,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return log_msg_ret("tit", ret);
|
return log_msg_ret("tit", ret);
|
||||||
title_id = ret;
|
title_id = ret;
|
||||||
scene_title_set(scn, title_id);
|
scn->title_id = title_id;
|
||||||
|
|
||||||
ret = add_txt_str(info, scn_node, scn, "prompt", 0);
|
ret = add_txt_str(info, scn_node, scn, "prompt", 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -424,7 +420,7 @@ static int scene_build(struct build_info *info, ofnode scn_node,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int build_it(struct build_info *info, ofnode root, struct expo **expp)
|
static int build_it(struct build_info *info, ofnode root, struct expo **expp)
|
||||||
{
|
{
|
||||||
ofnode scenes, node;
|
ofnode scenes, node;
|
||||||
struct expo *exp;
|
struct expo *exp;
|
||||||
|
|
63
boot/scene.c
63
boot/scene.c
|
@ -70,13 +70,6 @@ void scene_destroy(struct scene *scn)
|
||||||
free(scn);
|
free(scn);
|
||||||
}
|
}
|
||||||
|
|
||||||
int scene_title_set(struct scene *scn, uint id)
|
|
||||||
{
|
|
||||||
scn->title_id = id;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int scene_obj_count(struct scene *scn)
|
int scene_obj_count(struct scene *scn)
|
||||||
{
|
{
|
||||||
return list_count_nodes(&scn->obj_head);
|
return list_count_nodes(&scn->obj_head);
|
||||||
|
@ -339,7 +332,7 @@ static void scene_render_background(struct scene_obj *obj, bool box_only)
|
||||||
|
|
||||||
/* draw a background for the object */
|
/* draw a background for the object */
|
||||||
if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) {
|
if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) {
|
||||||
fore = VID_BLACK;
|
fore = VID_DARK_GREY;
|
||||||
back = VID_WHITE;
|
back = VID_WHITE;
|
||||||
} else {
|
} else {
|
||||||
fore = VID_LIGHT_GRAY;
|
fore = VID_LIGHT_GRAY;
|
||||||
|
@ -471,11 +464,59 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int scene_arrange(struct scene *scn)
|
int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr)
|
||||||
{
|
{
|
||||||
struct scene_obj *obj;
|
struct scene_obj *obj;
|
||||||
|
|
||||||
|
arr->label_width = 0;
|
||||||
|
list_for_each_entry(obj, &scn->obj_head, sibling) {
|
||||||
|
uint label_id = 0;
|
||||||
|
int width;
|
||||||
|
|
||||||
|
switch (obj->type) {
|
||||||
|
case SCENEOBJT_NONE:
|
||||||
|
case SCENEOBJT_IMAGE:
|
||||||
|
case SCENEOBJT_TEXT:
|
||||||
|
break;
|
||||||
|
case SCENEOBJT_MENU: {
|
||||||
|
struct scene_obj_menu *menu;
|
||||||
|
|
||||||
|
menu = (struct scene_obj_menu *)obj,
|
||||||
|
label_id = menu->title_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCENEOBJT_TEXTLINE: {
|
||||||
|
struct scene_obj_textline *tline;
|
||||||
|
|
||||||
|
tline = (struct scene_obj_textline *)obj,
|
||||||
|
label_id = tline->label_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (label_id) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
ret = scene_obj_get_hw(scn, label_id, &width);
|
||||||
|
if (ret < 0)
|
||||||
|
return log_msg_ret("hei", ret);
|
||||||
|
arr->label_width = max(arr->label_width, width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scene_arrange(struct scene *scn)
|
||||||
|
{
|
||||||
|
struct expo_arrange_info arr;
|
||||||
|
struct scene_obj *obj;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = scene_calc_arrange(scn, &arr);
|
||||||
|
if (ret < 0)
|
||||||
|
return log_msg_ret("arr", ret);
|
||||||
|
|
||||||
list_for_each_entry(obj, &scn->obj_head, sibling) {
|
list_for_each_entry(obj, &scn->obj_head, sibling) {
|
||||||
switch (obj->type) {
|
switch (obj->type) {
|
||||||
case SCENEOBJT_NONE:
|
case SCENEOBJT_NONE:
|
||||||
|
@ -486,7 +527,7 @@ int scene_arrange(struct scene *scn)
|
||||||
struct scene_obj_menu *menu;
|
struct scene_obj_menu *menu;
|
||||||
|
|
||||||
menu = (struct scene_obj_menu *)obj,
|
menu = (struct scene_obj_menu *)obj,
|
||||||
ret = scene_menu_arrange(scn, menu);
|
ret = scene_menu_arrange(scn, &arr, menu);
|
||||||
if (ret)
|
if (ret)
|
||||||
return log_msg_ret("arr", ret);
|
return log_msg_ret("arr", ret);
|
||||||
break;
|
break;
|
||||||
|
@ -495,7 +536,7 @@ int scene_arrange(struct scene *scn)
|
||||||
struct scene_obj_textline *tline;
|
struct scene_obj_textline *tline;
|
||||||
|
|
||||||
tline = (struct scene_obj_textline *)obj,
|
tline = (struct scene_obj_textline *)obj,
|
||||||
ret = scene_textline_arrange(scn, tline);
|
ret = scene_textline_arrange(scn, &arr, tline);
|
||||||
if (ret)
|
if (ret)
|
||||||
return log_msg_ret("arr", ret);
|
return log_msg_ret("arr", ret);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -96,10 +96,12 @@ int scene_calc_dims(struct scene *scn, bool do_menus);
|
||||||
* if not already done
|
* if not already done
|
||||||
*
|
*
|
||||||
* @scn: Scene to update
|
* @scn: Scene to update
|
||||||
|
* @arr: Arrangement information
|
||||||
* @menu: Menu to process
|
* @menu: Menu to process
|
||||||
* Returns: 0 if OK, -ve on error
|
* Returns: 0 if OK, -ve on error
|
||||||
*/
|
*/
|
||||||
int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu);
|
int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr,
|
||||||
|
struct scene_obj_menu *menu);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* scene_textline_arrange() - Set the position of things in a textline
|
* scene_textline_arrange() - Set the position of things in a textline
|
||||||
|
@ -108,10 +110,12 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu);
|
||||||
* positioned correctly relative to the textline.
|
* positioned correctly relative to the textline.
|
||||||
*
|
*
|
||||||
* @scn: Scene to update
|
* @scn: Scene to update
|
||||||
|
* @arr: Arrangement information
|
||||||
* @tline: textline to process
|
* @tline: textline to process
|
||||||
* Returns: 0 if OK, -ve on error
|
* Returns: 0 if OK, -ve on error
|
||||||
*/
|
*/
|
||||||
int scene_textline_arrange(struct scene *scn, struct scene_obj_textline *tline);
|
int scene_textline_arrange(struct scene *scn, struct expo_arrange_info *arr,
|
||||||
|
struct scene_obj_textline *tline);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* scene_apply_theme() - Apply a theme to a scene
|
* scene_apply_theme() - Apply a theme to a scene
|
||||||
|
@ -277,6 +281,16 @@ struct scene_menitem *scene_menuitem_find(const struct scene_obj_menu *menu,
|
||||||
struct scene_menitem *scene_menuitem_find_seq(const struct scene_obj_menu *menu,
|
struct scene_menitem *scene_menuitem_find_seq(const struct scene_obj_menu *menu,
|
||||||
uint seq);
|
uint seq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* scene_menuitem_find_val() - Find the menu item with a given value
|
||||||
|
*
|
||||||
|
* @menu: Menu to check
|
||||||
|
* @find_val: Value to look for
|
||||||
|
* Return: menu item if found, else NULL
|
||||||
|
*/
|
||||||
|
struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu,
|
||||||
|
int val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* scene_bbox_union() - update bouding box with the demensions of an object
|
* scene_bbox_union() - update bouding box with the demensions of an object
|
||||||
*
|
*
|
||||||
|
@ -358,4 +372,16 @@ int scene_textline_open(struct scene *scn, struct scene_obj_textline *tline);
|
||||||
*/
|
*/
|
||||||
int scene_textline_close(struct scene *scn, struct scene_obj_textline *tline);
|
int scene_textline_close(struct scene *scn, struct scene_obj_textline *tline);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* scene_calc_arrange() - Calculate sizes needed to arrange a scene
|
||||||
|
*
|
||||||
|
* Checks the size of some objects and stores this info to help with a later
|
||||||
|
* scene arrangement
|
||||||
|
*
|
||||||
|
* @scn: Scene to check
|
||||||
|
* @arr: Place to put scene-arrangement info
|
||||||
|
* Returns: 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr);
|
||||||
|
|
||||||
#endif /* __SCENE_INTERNAL_H */
|
#endif /* __SCENE_INTERNAL_H */
|
||||||
|
|
|
@ -61,6 +61,22 @@ struct scene_menitem *scene_menuitem_find_seq(const struct scene_obj_menu *menu,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu,
|
||||||
|
int val)
|
||||||
|
{
|
||||||
|
struct scene_menitem *item;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
list_for_each_entry(item, &menu->item_head, sibling) {
|
||||||
|
if (item->value == INT_MAX ? val == i : item->value == val)
|
||||||
|
return item;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update_pointers() - Update the pointer object and handle highlights
|
* update_pointers() - Update the pointer object and handle highlights
|
||||||
*
|
*
|
||||||
|
@ -168,7 +184,8 @@ int scene_menu_calc_dims(struct scene_obj_menu *menu)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu)
|
int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr,
|
||||||
|
struct scene_obj_menu *menu)
|
||||||
{
|
{
|
||||||
const bool open = menu->obj.flags & SCENEOF_OPEN;
|
const bool open = menu->obj.flags & SCENEOF_OPEN;
|
||||||
struct expo *exp = scn->expo;
|
struct expo *exp = scn->expo;
|
||||||
|
@ -182,16 +199,18 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu)
|
||||||
x = menu->obj.dim.x;
|
x = menu->obj.dim.x;
|
||||||
y = menu->obj.dim.y;
|
y = menu->obj.dim.y;
|
||||||
if (menu->title_id) {
|
if (menu->title_id) {
|
||||||
|
int width;
|
||||||
|
|
||||||
ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.dim.x, y);
|
ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.dim.x, y);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return log_msg_ret("tit", ret);
|
return log_msg_ret("tit", ret);
|
||||||
|
|
||||||
ret = scene_obj_get_hw(scn, menu->title_id, NULL);
|
ret = scene_obj_get_hw(scn, menu->title_id, &width);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return log_msg_ret("hei", ret);
|
return log_msg_ret("hei", ret);
|
||||||
|
|
||||||
if (stack)
|
if (stack)
|
||||||
x += 200;
|
x += arr->label_width + theme->menu_title_margin_x;
|
||||||
else
|
else
|
||||||
y += ret * 2;
|
y += ret * 2;
|
||||||
}
|
}
|
||||||
|
@ -413,6 +432,7 @@ int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id,
|
||||||
item->desc_id = desc_id;
|
item->desc_id = desc_id;
|
||||||
item->preview_id = preview_id;
|
item->preview_id = preview_id;
|
||||||
item->flags = flags;
|
item->flags = flags;
|
||||||
|
item->value = INT_MAX;
|
||||||
list_add_tail(&item->sibling, &menu->item_head);
|
list_add_tail(&item->sibling, &menu->item_head);
|
||||||
|
|
||||||
if (itemp)
|
if (itemp)
|
||||||
|
|
|
@ -87,7 +87,8 @@ int scene_textline_calc_dims(struct scene_obj_textline *tline)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int scene_textline_arrange(struct scene *scn, struct scene_obj_textline *tline)
|
int scene_textline_arrange(struct scene *scn, struct expo_arrange_info *arr,
|
||||||
|
struct scene_obj_textline *tline)
|
||||||
{
|
{
|
||||||
const bool open = tline->obj.flags & SCENEOF_OPEN;
|
const bool open = tline->obj.flags & SCENEOF_OPEN;
|
||||||
bool point;
|
bool point;
|
||||||
|
|
|
@ -2291,6 +2291,7 @@ config CMD_DATE
|
||||||
config CMD_RTC
|
config CMD_RTC
|
||||||
bool "rtc"
|
bool "rtc"
|
||||||
depends on DM_RTC
|
depends on DM_RTC
|
||||||
|
default y if X86
|
||||||
help
|
help
|
||||||
Enable the 'rtc' command for low-level access to RTC devices.
|
Enable the 'rtc' command for low-level access to RTC devices.
|
||||||
|
|
||||||
|
|
|
@ -55,9 +55,6 @@ static int do_font_size(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
uint size;
|
uint size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (argc != 2)
|
|
||||||
return CMD_RET_USAGE;
|
|
||||||
|
|
||||||
if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev))
|
if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev))
|
||||||
return CMD_RET_FAILURE;
|
return CMD_RET_FAILURE;
|
||||||
ret = vidconsole_get_font_size(dev, &font_name, &size);
|
ret = vidconsole_get_font_size(dev, &font_name, &size);
|
||||||
|
@ -66,6 +63,9 @@ static int do_font_size(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
return CMD_RET_FAILURE;
|
return CMD_RET_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("%d\n", size);
|
||||||
|
} else {
|
||||||
size = dectoul(argv[1], NULL);
|
size = dectoul(argv[1], NULL);
|
||||||
|
|
||||||
ret = vidconsole_select_font(dev, font_name, size);
|
ret = vidconsole_select_font(dev, font_name, size);
|
||||||
|
@ -73,6 +73,7 @@ static int do_font_size(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
printf("Failed (error %d)\n", ret);
|
printf("Failed (error %d)\n", ret);
|
||||||
return CMD_RET_FAILURE;
|
return CMD_RET_FAILURE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0+
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
obj-$(CONFIG_CMD_CBSYSINFO) += cbsysinfo.o
|
obj-$(CONFIG_CMD_CBSYSINFO) += cbsysinfo.o
|
||||||
obj-y += mtrr.o
|
obj-y += cpuid.o msr.o mtrr.o
|
||||||
obj-$(CONFIG_CMD_EXCEPTION) += exception.o
|
obj-$(CONFIG_CMD_EXCEPTION) += exception.o
|
||||||
obj-$(CONFIG_USE_HOB) += hob.o
|
obj-$(CONFIG_USE_HOB) += hob.o
|
||||||
obj-$(CONFIG_HAVE_FSP) += fsp.o
|
obj-$(CONFIG_HAVE_FSP) += fsp.o
|
||||||
|
|
37
cmd/x86/cpuid.c
Normal file
37
cmd/x86/cpuid.c
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* The 'cpuid' command provides access to the CPU's cpuid information
|
||||||
|
*
|
||||||
|
* Copyright 2024 Google, LLC
|
||||||
|
* Written by Simon Glass <sjg@chromium.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <command.h>
|
||||||
|
#include <vsprintf.h>
|
||||||
|
#include <asm/cpu.h>
|
||||||
|
|
||||||
|
static int do_cpuid(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
char *const argv[])
|
||||||
|
{
|
||||||
|
struct cpuid_result res;
|
||||||
|
ulong op;
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
return CMD_RET_USAGE;
|
||||||
|
|
||||||
|
op = hextoul(argv[1], NULL);
|
||||||
|
res = cpuid(op);
|
||||||
|
printf("eax %08x\n", res.eax);
|
||||||
|
printf("ebx %08x\n", res.ebx);
|
||||||
|
printf("ecx %08x\n", res.ecx);
|
||||||
|
printf("edx %08x\n", res.edx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
U_BOOT_LONGHELP(cpuid, "Show CPU Identification information");
|
||||||
|
|
||||||
|
U_BOOT_CMD(
|
||||||
|
cpuid, 2, 1, do_cpuid,
|
||||||
|
"cpuid <op>", cpuid_help_text
|
||||||
|
);
|
52
cmd/x86/msr.c
Normal file
52
cmd/x86/msr.c
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* The 'cpuid' command provides access to the CPU's cpuid information
|
||||||
|
*
|
||||||
|
* Copyright 2024 Google, LLC
|
||||||
|
* Written by Simon Glass <sjg@chromium.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <command.h>
|
||||||
|
#include <vsprintf.h>
|
||||||
|
#include <asm/msr.h>
|
||||||
|
|
||||||
|
static int do_read(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
char *const argv[])
|
||||||
|
{
|
||||||
|
struct msr_t msr;
|
||||||
|
ulong op;
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
return CMD_RET_USAGE;
|
||||||
|
|
||||||
|
op = hextoul(argv[1], NULL);
|
||||||
|
msr = msr_read(op);
|
||||||
|
printf("%08x %08x\n", msr.hi, msr.lo);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_write(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
char *const argv[])
|
||||||
|
{
|
||||||
|
struct msr_t msr;
|
||||||
|
ulong op;
|
||||||
|
|
||||||
|
if (argc < 4)
|
||||||
|
return CMD_RET_USAGE;
|
||||||
|
|
||||||
|
op = hextoul(argv[1], NULL);
|
||||||
|
msr.hi = hextoul(argv[2], NULL);
|
||||||
|
msr.lo = hextoul(argv[3], NULL);
|
||||||
|
msr_write(op, msr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
U_BOOT_LONGHELP(msr,
|
||||||
|
"read <op> - read a machine-status register (MSR) as <hi 32-bits> <lo 32-bits>\n"
|
||||||
|
"write <op< <hi> <lo> - write an MSR");
|
||||||
|
|
||||||
|
U_BOOT_CMD_WITH_SUBCMDS(msr, "Machine Status Registers", msr_help_text,
|
||||||
|
U_BOOT_CMD_MKENT(read, CONFIG_SYS_MAXARGS, 1, do_read, "", ""),
|
||||||
|
U_BOOT_CMD_MKENT(write, CONFIG_SYS_MAXARGS, 1, do_write, "", ""));
|
|
@ -61,6 +61,9 @@ CONFIG_SOUND=y
|
||||||
CONFIG_SOUND_I8254=y
|
CONFIG_SOUND_I8254=y
|
||||||
CONFIG_VIDEO_COPY=y
|
CONFIG_VIDEO_COPY=y
|
||||||
CONFIG_CONSOLE_TRUETYPE=y
|
CONFIG_CONSOLE_TRUETYPE=y
|
||||||
|
CONFIG_CONSOLE_TRUETYPE_SIZE=20
|
||||||
|
# CONFIG_CONSOLE_TRUETYPE_NIMBUS is not set
|
||||||
|
CONFIG_CONSOLE_TRUETYPE_ANKACODER=y
|
||||||
CONFIG_CONSOLE_SCROLL_LINES=5
|
CONFIG_CONSOLE_SCROLL_LINES=5
|
||||||
CONFIG_SPL_ACPI=y
|
CONFIG_SPL_ACPI=y
|
||||||
CONFIG_CMD_DHRYSTONE=y
|
CONFIG_CMD_DHRYSTONE=y
|
||||||
|
|
|
@ -11,6 +11,7 @@ CONFIG_SYS_MONITOR_BASE=0x01110000
|
||||||
CONFIG_FIT=y
|
CONFIG_FIT=y
|
||||||
CONFIG_FIT_SIGNATURE=y
|
CONFIG_FIT_SIGNATURE=y
|
||||||
CONFIG_BOOTSTD_FULL=y
|
CONFIG_BOOTSTD_FULL=y
|
||||||
|
CONFIG_BOOTSTAGE=y
|
||||||
CONFIG_SHOW_BOOT_PROGRESS=y
|
CONFIG_SHOW_BOOT_PROGRESS=y
|
||||||
CONFIG_USE_BOOTARGS=y
|
CONFIG_USE_BOOTARGS=y
|
||||||
CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro"
|
CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro"
|
||||||
|
@ -30,6 +31,7 @@ CONFIG_CMD_USB=y
|
||||||
CONFIG_BOOTP_BOOTFILESIZE=y
|
CONFIG_BOOTP_BOOTFILESIZE=y
|
||||||
CONFIG_CMD_TIME=y
|
CONFIG_CMD_TIME=y
|
||||||
CONFIG_CMD_SOUND=y
|
CONFIG_CMD_SOUND=y
|
||||||
|
CONFIG_CMD_BOOTSTAGE=y
|
||||||
CONFIG_CMD_EXT4_WRITE=y
|
CONFIG_CMD_EXT4_WRITE=y
|
||||||
CONFIG_MAC_PARTITION=y
|
CONFIG_MAC_PARTITION=y
|
||||||
CONFIG_ENV_OVERWRITE=y
|
CONFIG_ENV_OVERWRITE=y
|
||||||
|
@ -55,6 +57,9 @@ CONFIG_SOUND=y
|
||||||
CONFIG_SOUND_I8254=y
|
CONFIG_SOUND_I8254=y
|
||||||
CONFIG_VIDEO_COPY=y
|
CONFIG_VIDEO_COPY=y
|
||||||
CONFIG_CONSOLE_TRUETYPE=y
|
CONFIG_CONSOLE_TRUETYPE=y
|
||||||
|
CONFIG_CONSOLE_TRUETYPE_SIZE=20
|
||||||
|
# CONFIG_CONSOLE_TRUETYPE_NIMBUS is not set
|
||||||
|
CONFIG_CONSOLE_TRUETYPE_ANKACODER=y
|
||||||
CONFIG_CONSOLE_SCROLL_LINES=5
|
CONFIG_CONSOLE_SCROLL_LINES=5
|
||||||
CONFIG_CMD_DHRYSTONE=y
|
CONFIG_CMD_DHRYSTONE=y
|
||||||
# CONFIG_GZIP is not set
|
# CONFIG_GZIP is not set
|
||||||
|
|
|
@ -181,16 +181,4 @@ coreboot in CI
|
||||||
CI runs tests using a pre-built coreboot image. This ensures that U-Boot can
|
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.
|
boot as a coreboot payload, based on a known-good build of coreboot.
|
||||||
|
|
||||||
To update the `coreboot.rom` file which is used:
|
To update the `coreboot.rom` file which is used, see ``tools/Dockerfile``
|
||||||
|
|
||||||
#. Build coreboot with `CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y`. If using
|
|
||||||
`make menuconfig`, this is under
|
|
||||||
`Devices->Display->Framebuffer mode->Linear "high resolution" framebuffer`.
|
|
||||||
|
|
||||||
#. Compress the resulting `coreboot.rom`::
|
|
||||||
|
|
||||||
xz -c /path/to/coreboot/build/coreboot.rom > coreboot.rom.xz
|
|
||||||
|
|
||||||
#. Upload the file to Google drive
|
|
||||||
|
|
||||||
#. Send a patch to change the file ID used by wget in the CI yaml files.
|
|
||||||
|
|
734
doc/develop/binman_tests.rst
Normal file
734
doc/develop/binman_tests.rst
Normal file
|
@ -0,0 +1,734 @@
|
||||||
|
.. SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
Binman Tests
|
||||||
|
============
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:depth: 2
|
||||||
|
:local:
|
||||||
|
|
||||||
|
There is some material on writing tests in the main Binman documentation
|
||||||
|
(see :doc:`package/index`). This short guide is separate so people don't
|
||||||
|
feel they have to read as much.
|
||||||
|
|
||||||
|
Code and output is mostly included verbatim, which makes the doc longer, but
|
||||||
|
avoids its becoming confusing when the output or referenced code changes in the
|
||||||
|
future.
|
||||||
|
|
||||||
|
Purpose
|
||||||
|
-------
|
||||||
|
|
||||||
|
The main purpose of tests in Binman is to make sure that Binman actually does
|
||||||
|
what it is supposed to. Various people contribute code, refactoring is done
|
||||||
|
over time, but U-Boot users (developers, SoC vendors, board vendors) rely on
|
||||||
|
Binman producing images which function correctly. Without tests, a one-line
|
||||||
|
change could unintentionally break a corner-case and the problem might not be
|
||||||
|
noticed for months. Debugging an image-generation problem with a board you
|
||||||
|
don't have can be very hard.
|
||||||
|
|
||||||
|
A secondary purpose is productivity. U-Boot contributors are busy and often
|
||||||
|
have too much on their plate. Trying to figure out why their patch broke
|
||||||
|
some other vendor's workflow can be very time-consuming and frustrating. By
|
||||||
|
building in tests from the start, this is largely avoided. If your change has
|
||||||
|
full test coverage and doesn't break any test, all is well and no one can
|
||||||
|
complain.
|
||||||
|
|
||||||
|
A lessor purpose is to document what Binman actually does. If a test covers a
|
||||||
|
feature, it works. If there is no test coverage, no one can say for sure
|
||||||
|
whether it works in all expected situations, certainly not wihout manual
|
||||||
|
effort.
|
||||||
|
|
||||||
|
In fact, strictly speaking it isn't completely clear what 'works' even means in
|
||||||
|
the case where these is no test to cover the code. We are often left guessing
|
||||||
|
as to what the documentation means, what was actually intended, etc.
|
||||||
|
|
||||||
|
Finally, code-coverage helps to remove 'zombie code', copied from elsewhere
|
||||||
|
because it looks reasonable, but not actually needed. The same situation arises
|
||||||
|
in silicon-chip design, where a part of the chip is not validated. If it isn't
|
||||||
|
validated, it can be assumed not to work, either now or later, so it is best to
|
||||||
|
remove that logic to avoid it causing problems.
|
||||||
|
|
||||||
|
Setting up
|
||||||
|
----------
|
||||||
|
|
||||||
|
Binman tests use various utility programs. Most of these are documented in
|
||||||
|
:doc:`../build/gcc`. But some are SoC-specific. To fetch these, tell Binman to
|
||||||
|
fetch or build any missing tools:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ binman tool -f missing
|
||||||
|
|
||||||
|
When this completes successfully, you can list the tools. You should see
|
||||||
|
something like this:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ binman tool -l
|
||||||
|
Name Version Description Path
|
||||||
|
--------------- ----------- ------------------------- ------------------------------
|
||||||
|
bootgen ****** Bootg Xilinx Bootgen /home/sglass/.binman-tools/bootgen
|
||||||
|
bzip2 1.0.8 bzip2 compression /usr/bin/bzip2
|
||||||
|
cbfstool unknown Manipulate CBFS files /home/sglass/bin/cbfstool
|
||||||
|
fdt_add_pubkey unknown Generate image for U-Boot /home/sglass/bin/fdt_add_pubkey
|
||||||
|
fdtgrep unknown Grep devicetree files /home/sglass/bin/fdtgrep
|
||||||
|
fiptool v2.11.0(rele Manipulate ATF FIP files /home/sglass/.binman-tools/fiptool
|
||||||
|
futility v0.0.1-9f2e9 Chromium OS firmware utili /home/sglass/.binman-tools/futility
|
||||||
|
gzip 1.12 gzip compression /usr/bin/gzip
|
||||||
|
ifwitool unknown Manipulate Intel IFWI file /home/sglass/.binman-tools/ifwitool
|
||||||
|
lz4 v1.9.4 lz4 compression /usr/bin/lz4
|
||||||
|
lzma_alone 9.22 beta lzma_alone compression /usr/bin/lzma_alone
|
||||||
|
lzop v1.04 lzo compression /usr/bin/lzop
|
||||||
|
mkeficapsule 2024.10-rc5- mkeficapsule tool for gene /home/sglass/bin/mkeficapsule
|
||||||
|
mkimage 2024.10-rc5- Generate image for U-Boot /home/sglass/bin/mkimage
|
||||||
|
openssl 3.0.13 30 Ja openssl cryptography toolk /usr/bin/openssl
|
||||||
|
xz 5.4.5 xz compression /usr/bin/xz
|
||||||
|
zstd v1.5.5 zstd compression /usr/bin/zstd
|
||||||
|
|
||||||
|
The tools are written to ``~/.binman-tools`` so add that to your ``PATH``.
|
||||||
|
It's fine to have some of the tools elsewhere (e.g. ``~/bin``) so long as they
|
||||||
|
are up-to-date. This allows you use the version of the tools intended for
|
||||||
|
running tests.
|
||||||
|
|
||||||
|
Now you should be able to actually run the tests:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ binman test
|
||||||
|
======================== Running binman tests ========================
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
........
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Ran 568 tests in 2.578s
|
||||||
|
|
||||||
|
OK
|
||||||
|
|
||||||
|
If this doesn't work, see if you can have some missing tools. Check that the
|
||||||
|
dependencies are all there as above. If it is very slow, try installing
|
||||||
|
concurrencytest so that the tests run in parallel.
|
||||||
|
|
||||||
|
The next thing to set up is code coverage, using the -T flag:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ binman test -T
|
||||||
|
======================== Running binman tests ========================
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
......................................................................
|
||||||
|
........
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Ran 568 tests in 17.367s
|
||||||
|
|
||||||
|
OK
|
||||||
|
|
||||||
|
99%
|
||||||
|
Name Stmts Miss Cover
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
tools/binman/__init__.py 0 0 100%
|
||||||
|
tools/binman/bintool.py 263 0 100%
|
||||||
|
tools/binman/btool/bootgen.py 21 0 100%
|
||||||
|
tools/binman/btool/btool_gzip.py 5 0 100%
|
||||||
|
tools/binman/btool/bzip2.py 5 0 100%
|
||||||
|
tools/binman/btool/cbfstool.py 24 0 100%
|
||||||
|
tools/binman/btool/cst.py 15 4 73%
|
||||||
|
tools/binman/btool/fdt_add_pubkey.py 21 0 100%
|
||||||
|
tools/binman/btool/fdtgrep.py 26 0 100%
|
||||||
|
tools/binman/btool/fiptool.py 19 0 100%
|
||||||
|
tools/binman/btool/futility.py 19 0 100%
|
||||||
|
tools/binman/btool/ifwitool.py 22 0 100%
|
||||||
|
tools/binman/btool/lz4.py 22 0 100%
|
||||||
|
tools/binman/btool/lzma_alone.py 34 0 100%
|
||||||
|
tools/binman/btool/lzop.py 5 0 100%
|
||||||
|
tools/binman/btool/mkeficapsule.py 27 0 100%
|
||||||
|
tools/binman/btool/mkimage.py 23 0 100%
|
||||||
|
tools/binman/btool/openssl.py 42 0 100%
|
||||||
|
tools/binman/btool/xz.py 5 0 100%
|
||||||
|
tools/binman/btool/zstd.py 5 0 100%
|
||||||
|
tools/binman/cbfs_util.py 376 0 100%
|
||||||
|
tools/binman/cmdline.py 90 0 100%
|
||||||
|
tools/binman/control.py 409 0 100%
|
||||||
|
tools/binman/elf.py 241 0 100%
|
||||||
|
tools/binman/entry.py 548 0 100%
|
||||||
|
tools/binman/etype/alternates_fdt.py 58 0 100%
|
||||||
|
tools/binman/etype/atf_bl31.py 5 0 100%
|
||||||
|
tools/binman/etype/atf_fip.py 67 0 100%
|
||||||
|
tools/binman/etype/blob.py 49 0 100%
|
||||||
|
tools/binman/etype/blob_dtb.py 46 0 100%
|
||||||
|
tools/binman/etype/blob_ext.py 9 0 100%
|
||||||
|
tools/binman/etype/blob_ext_list.py 32 0 100%
|
||||||
|
tools/binman/etype/blob_named_by_arg.py 9 0 100%
|
||||||
|
tools/binman/etype/blob_phase.py 22 0 100%
|
||||||
|
tools/binman/etype/cbfs.py 101 0 100%
|
||||||
|
tools/binman/etype/collection.py 30 0 100%
|
||||||
|
tools/binman/etype/cros_ec_rw.py 5 0 100%
|
||||||
|
tools/binman/etype/efi_capsule.py 59 0 100%
|
||||||
|
tools/binman/etype/efi_empty_capsule.py 33 0 100%
|
||||||
|
tools/binman/etype/encrypted.py 34 0 100%
|
||||||
|
tools/binman/etype/fdtmap.py 62 0 100%
|
||||||
|
tools/binman/etype/files.py 35 0 100%
|
||||||
|
tools/binman/etype/fill.py 13 0 100%
|
||||||
|
tools/binman/etype/fit.py 311 0 100%
|
||||||
|
tools/binman/etype/fmap.py 37 0 100%
|
||||||
|
tools/binman/etype/gbb.py 37 0 100%
|
||||||
|
tools/binman/etype/image_header.py 53 0 100%
|
||||||
|
tools/binman/etype/intel_cmc.py 4 0 100%
|
||||||
|
tools/binman/etype/intel_descriptor.py 39 0 100%
|
||||||
|
tools/binman/etype/intel_fit.py 12 0 100%
|
||||||
|
tools/binman/etype/intel_fit_ptr.py 17 0 100%
|
||||||
|
tools/binman/etype/intel_fsp.py 4 0 100%
|
||||||
|
tools/binman/etype/intel_fsp_m.py 4 0 100%
|
||||||
|
tools/binman/etype/intel_fsp_s.py 4 0 100%
|
||||||
|
tools/binman/etype/intel_fsp_t.py 4 0 100%
|
||||||
|
tools/binman/etype/intel_ifwi.py 67 0 100%
|
||||||
|
tools/binman/etype/intel_me.py 4 0 100%
|
||||||
|
tools/binman/etype/intel_mrc.py 6 0 100%
|
||||||
|
tools/binman/etype/intel_refcode.py 6 0 100%
|
||||||
|
tools/binman/etype/intel_vbt.py 4 0 100%
|
||||||
|
tools/binman/etype/intel_vga.py 4 0 100%
|
||||||
|
tools/binman/etype/mkimage.py 84 0 100%
|
||||||
|
tools/binman/etype/null.py 9 0 100%
|
||||||
|
tools/binman/etype/nxp_imx8mcst.py 78 59 24%
|
||||||
|
tools/binman/etype/nxp_imx8mimage.py 38 6 84%
|
||||||
|
tools/binman/etype/opensbi.py 5 0 100%
|
||||||
|
tools/binman/etype/powerpc_mpc85xx_bootpg_resetvec.py 6 0 100%
|
||||||
|
tools/binman/etype/pre_load.py 76 0 100%
|
||||||
|
tools/binman/etype/rockchip_tpl.py 5 0 100%
|
||||||
|
tools/binman/etype/scp.py 5 0 100%
|
||||||
|
tools/binman/etype/section.py 418 0 100%
|
||||||
|
tools/binman/etype/tee_os.py 31 0 100%
|
||||||
|
tools/binman/etype/text.py 21 0 100%
|
||||||
|
tools/binman/etype/ti_board_config.py 139 0 100%
|
||||||
|
tools/binman/etype/ti_dm.py 5 0 100%
|
||||||
|
tools/binman/etype/ti_secure.py 65 0 100%
|
||||||
|
tools/binman/etype/ti_secure_rom.py 117 0 100%
|
||||||
|
tools/binman/etype/u_boot.py 7 0 100%
|
||||||
|
tools/binman/etype/u_boot_dtb.py 9 0 100%
|
||||||
|
tools/binman/etype/u_boot_dtb_with_ucode.py 51 0 100%
|
||||||
|
tools/binman/etype/u_boot_elf.py 19 0 100%
|
||||||
|
tools/binman/etype/u_boot_env.py 27 0 100%
|
||||||
|
tools/binman/etype/u_boot_expanded.py 4 0 100%
|
||||||
|
tools/binman/etype/u_boot_img.py 7 0 100%
|
||||||
|
tools/binman/etype/u_boot_nodtb.py 7 0 100%
|
||||||
|
tools/binman/etype/u_boot_spl.py 8 0 100%
|
||||||
|
tools/binman/etype/u_boot_spl_bss_pad.py 14 0 100%
|
||||||
|
tools/binman/etype/u_boot_spl_dtb.py 9 0 100%
|
||||||
|
tools/binman/etype/u_boot_spl_elf.py 8 0 100%
|
||||||
|
tools/binman/etype/u_boot_spl_expanded.py 12 0 100%
|
||||||
|
tools/binman/etype/u_boot_spl_nodtb.py 8 0 100%
|
||||||
|
tools/binman/etype/u_boot_spl_pubkey_dtb.py 32 0 100%
|
||||||
|
tools/binman/etype/u_boot_spl_with_ucode_ptr.py 8 0 100%
|
||||||
|
tools/binman/etype/u_boot_tpl.py 8 0 100%
|
||||||
|
tools/binman/etype/u_boot_tpl_bss_pad.py 14 0 100%
|
||||||
|
tools/binman/etype/u_boot_tpl_dtb.py 9 0 100%
|
||||||
|
tools/binman/etype/u_boot_tpl_dtb_with_ucode.py 8 0 100%
|
||||||
|
tools/binman/etype/u_boot_tpl_elf.py 8 0 100%
|
||||||
|
tools/binman/etype/u_boot_tpl_expanded.py 12 0 100%
|
||||||
|
tools/binman/etype/u_boot_tpl_nodtb.py 8 0 100%
|
||||||
|
tools/binman/etype/u_boot_tpl_with_ucode_ptr.py 12 0 100%
|
||||||
|
tools/binman/etype/u_boot_ucode.py 33 0 100%
|
||||||
|
tools/binman/etype/u_boot_vpl.py 8 0 100%
|
||||||
|
tools/binman/etype/u_boot_vpl_bss_pad.py 14 0 100%
|
||||||
|
tools/binman/etype/u_boot_vpl_dtb.py 9 0 100%
|
||||||
|
tools/binman/etype/u_boot_vpl_elf.py 8 0 100%
|
||||||
|
tools/binman/etype/u_boot_vpl_expanded.py 12 0 100%
|
||||||
|
tools/binman/etype/u_boot_vpl_nodtb.py 8 0 100%
|
||||||
|
tools/binman/etype/u_boot_with_ucode_ptr.py 42 0 100%
|
||||||
|
tools/binman/etype/vblock.py 38 0 100%
|
||||||
|
tools/binman/etype/x86_reset16.py 7 0 100%
|
||||||
|
tools/binman/etype/x86_reset16_spl.py 7 0 100%
|
||||||
|
tools/binman/etype/x86_reset16_tpl.py 7 0 100%
|
||||||
|
tools/binman/etype/x86_start16.py 7 0 100%
|
||||||
|
tools/binman/etype/x86_start16_spl.py 7 0 100%
|
||||||
|
tools/binman/etype/x86_start16_tpl.py 7 0 100%
|
||||||
|
tools/binman/etype/x509_cert.py 71 0 100%
|
||||||
|
tools/binman/etype/xilinx_bootgen.py 72 0 100%
|
||||||
|
tools/binman/fip_util.py 202 0 100%
|
||||||
|
tools/binman/fmap_util.py 49 0 100%
|
||||||
|
tools/binman/image.py 181 0 100%
|
||||||
|
tools/binman/state.py 201 0 100%
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
TOTAL 5954 69 99%
|
||||||
|
|
||||||
|
To get a report in 'htmlcov/index.html', type: python3-coverage html
|
||||||
|
Coverage error: 99%, but should be 100%
|
||||||
|
ValueError: Test coverage failure
|
||||||
|
|
||||||
|
Unfortunately the run failed. As it suggests, create a report:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ python3-coverage html
|
||||||
|
Wrote HTML report to htmlcov/index.html
|
||||||
|
|
||||||
|
If you open that file in the browser, you can see which files are not reaching
|
||||||
|
100% and click on them. Here is ``nxp_imx8mimage.py``, for example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
43 # Generate mkimage configuration file similar to imx8mimage.cfg
|
||||||
|
44 # and pass it to mkimage to generate SPL image for us here.
|
||||||
|
45 cfg_fname = tools.get_output_filename('nxp.imx8mimage.cfg.%s' % uniq)
|
||||||
|
46 with open(cfg_fname, 'w') as outf:
|
||||||
|
47 print('ROM_VERSION v%d' % self.rom_version, file=outf)
|
||||||
|
48 print('BOOT_FROM %s' % self.boot_from, file=outf)
|
||||||
|
49 print('LOADER %s %#x' % (input_fname, self.loader_address), file=outf)
|
||||||
|
50
|
||||||
|
51 output_fname = tools.get_output_filename(f'cfg-out.{uniq}')
|
||||||
|
52 args = ['-d', input_fname, '-n', cfg_fname, '-T', 'imx8mimage',
|
||||||
|
53 output_fname]
|
||||||
|
54 if self.mkimage.run_cmd(*args) is not None:
|
||||||
|
55 return tools.read_file(output_fname)
|
||||||
|
56 else:
|
||||||
|
57 # Bintool is missing; just use the input data as the output
|
||||||
|
58 x self.record_missing_bintool(self.mkimage)
|
||||||
|
59 x return data
|
||||||
|
60
|
||||||
|
61 def SetImagePos(self, image_pos):
|
||||||
|
62 # Customized SoC specific SetImagePos which skips the mkimage etype
|
||||||
|
63 # implementation and removes the 0x48 offset introduced there. That
|
||||||
|
64 # offset is only used for uImage/fitImage, which is not the case in
|
||||||
|
65 # here.
|
||||||
|
66 upto = 0x00
|
||||||
|
67 for entry in super().GetEntries().values():
|
||||||
|
68 x entry.SetOffsetSize(upto, None)
|
||||||
|
69
|
||||||
|
70 # Give up if any entries lack a size
|
||||||
|
71 x if entry.size is None:
|
||||||
|
72 x return
|
||||||
|
73 x upto += entry.size
|
||||||
|
74
|
||||||
|
75 Entry_section.SetImagePos(self, image_pos)
|
||||||
|
|
||||||
|
Most of the file is covered, but the lines marked with ``x`` indicate missing
|
||||||
|
coverage. The will show up red in your browser.
|
||||||
|
|
||||||
|
What is a test?
|
||||||
|
---------------
|
||||||
|
|
||||||
|
A test is a function in ``ftest.py`` which uses an image description in
|
||||||
|
``tools/binman/test`` to perform some operations and exercise the code. Some
|
||||||
|
tests are just a few lines; some are more complicated.
|
||||||
|
|
||||||
|
Here is a simple test:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def testSimple(self):
|
||||||
|
"""Test a simple binman with a single file"""
|
||||||
|
data = self._DoReadFile('005_simple.dts')
|
||||||
|
self.assertEqual(U_BOOT_DATA, data)
|
||||||
|
|
||||||
|
This test tells Binman to build an image using the description. Then it checks
|
||||||
|
that the resulting image looks correct. The image description is:
|
||||||
|
|
||||||
|
.. code-block:: devicetree
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
u-boot {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
As you will know from the Binman documentation, this says that there is
|
||||||
|
one image and it contains the U-Boot binary. So this test builds an image
|
||||||
|
consisting of a U-Boot binary, then checks that it does indeed have just a
|
||||||
|
U-Boot binary in it.
|
||||||
|
|
||||||
|
Test data
|
||||||
|
---------
|
||||||
|
|
||||||
|
Using real binaries (like ``u-boot.bin``) to test Binman would be quite tedious.
|
||||||
|
Every output file would be large and it would be hard to tell by looking at the
|
||||||
|
output (e.g. with a hex dump) if a particular entry contains ``u-boot.bin`` or
|
||||||
|
``u-boot-spl.bin`` or something else.
|
||||||
|
|
||||||
|
Binman gets around this by using simple placeholders. Here is the placeholder
|
||||||
|
for u-boot.bin:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
U_BOOT_DATA = b'1234'
|
||||||
|
|
||||||
|
This is just bytes. So the test above checks that the output image contains
|
||||||
|
these four bytes. This makes verification fast for Binman and very easy for
|
||||||
|
humans.
|
||||||
|
|
||||||
|
Even the devicetree is a placeholder:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
U_BOOT_DTB_DATA = b'udtb'
|
||||||
|
|
||||||
|
But for some tests you need to use the real devicetree. In that case you can
|
||||||
|
use ``_DoReadFileRealDtb()``. See ``testUpdateFdtAll()`` for an example of how
|
||||||
|
to check the devicetree updated by Binman.
|
||||||
|
|
||||||
|
Test structure
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Each test is designed to test just one thing. Binman tests are named according
|
||||||
|
to what they are testing. Individually they don't do very much, but as a whole
|
||||||
|
they test every line of code in Binman.
|
||||||
|
|
||||||
|
So ``testSimple()`` is designed to check that Binman can build the
|
||||||
|
simplest-possible image that isn't completely empty.
|
||||||
|
|
||||||
|
Another type of test is one which checks error-handling, for example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def testFillNoSize(self):
|
||||||
|
"""Test for an fill entry type with no size"""
|
||||||
|
with self.assertRaises(ValueError) as e:
|
||||||
|
self._DoReadFile('070_fill_no_size.dts')
|
||||||
|
self.assertIn("'fill' entry is missing properties: size",
|
||||||
|
str(e.exception))
|
||||||
|
|
||||||
|
This test deliberately tries to provoke an error. The image description is:
|
||||||
|
|
||||||
|
.. code-block:: devicetree
|
||||||
|
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
size = <16>;
|
||||||
|
fill {
|
||||||
|
fill-byte = [ff];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
You can see that there is no size for the 'fill' entry, so we would expect
|
||||||
|
Binman to complain. The test checks that it actually does. It also checks the
|
||||||
|
error message produced by Binman. Sometimes you need to add several tests, each
|
||||||
|
with their own broken image description, in order to check all the error cases.
|
||||||
|
|
||||||
|
Sometimes you need to capture the console output of Binman, to check it is
|
||||||
|
correct. You can to this with ``test_util.capture_sys_output()``, for example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
with test_util.capture_sys_output() as (_, stderr):
|
||||||
|
self._DoTestFile('071_gbb.dts', force_missing_bintools='futility',
|
||||||
|
entry_args=entry_args)
|
||||||
|
err = stderr.getvalue()
|
||||||
|
self.assertRegex(err, "Image 'image'.*missing bintools.*: futility")
|
||||||
|
|
||||||
|
The test collects the output and checks it with a regular expression. If you
|
||||||
|
need to see the test output (e.g. to debug it), you will have to remove that
|
||||||
|
capture line.
|
||||||
|
|
||||||
|
How to add a new test
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
This section explains the process of writing a new test. It uses an example to
|
||||||
|
help with this, but your code will be different.
|
||||||
|
|
||||||
|
Generally you are adding a test because you are adding a new entry type
|
||||||
|
('etype'). So start by creating the shortest and simplest image-description you
|
||||||
|
can, which contains the new etype. Put it in a numbered file in
|
||||||
|
``tool/binman/test`` so that it comes last. All the numbers are unique and there
|
||||||
|
are no gaps.
|
||||||
|
|
||||||
|
Example from ``tools/binman/test/339_nxp_imx8.dts``:
|
||||||
|
|
||||||
|
.. code-block:: devicetree
|
||||||
|
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
nxp-imx8mimage {
|
||||||
|
args; /* TODO: Needed by mkimage etype superclass */
|
||||||
|
nxp,boot-from = "sd";
|
||||||
|
nxp,rom-version = <1>;
|
||||||
|
nxp,loader-address = <0x10>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Note that you should use tabs in the file, not spaces. You can see that this has
|
||||||
|
been cut down to the bare minimum, just enough to include the etype and the
|
||||||
|
arguments it needs. This is of course not a real image. It will not boot on
|
||||||
|
anything. But that's fine; we are just trying to test this one etype. Try not
|
||||||
|
to add any other sections and etypes unless they are absolutely essential for
|
||||||
|
your test to work. This helps others too: they don't need to understand the full
|
||||||
|
complexity of your etype just to read your test.
|
||||||
|
|
||||||
|
Then create your test by adding a new function at the end of ``ftest.py``:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def testNxpImx8Image(self):
|
||||||
|
"""Test that binman can produce an iMX8 image"""
|
||||||
|
self._DoTestFile('339_nxp_imx8.dts')
|
||||||
|
|
||||||
|
This uses the test file that you created. It doesn't check anything, it just
|
||||||
|
runs the image description through binman.
|
||||||
|
|
||||||
|
Let's run it:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ binman test testNxpImx8Image
|
||||||
|
======================== Running binman tests ========================
|
||||||
|
.
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Ran 1 test in 0.242s
|
||||||
|
|
||||||
|
OK
|
||||||
|
|
||||||
|
So the test passes. It doesn't really do a lot, but it does exercise the etype.
|
||||||
|
The next step is to update it to actually check the output:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def testNxpImx8Image(self):
|
||||||
|
"""Test that binman can produce an iMX8 image"""
|
||||||
|
data = self._DoReadFile('339_nxp_imx8.dts')
|
||||||
|
print('data', len(data))
|
||||||
|
|
||||||
|
The ``_DoReadFile()`` function is documented in the code. It returns the image
|
||||||
|
contents as the first part of a tuple.
|
||||||
|
|
||||||
|
Running this we see:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
data 2200
|
||||||
|
|
||||||
|
So it is producing a little over 8K of data. Your etype will be different, but
|
||||||
|
in any case you can add Python code to check that this data is actually correct,
|
||||||
|
based on your knowledge of your etype. Note that you should not be checking
|
||||||
|
whether the external tools (called 'bintools' in Binman) are actually working,
|
||||||
|
since presumably they have their own tests. You just need to check that the
|
||||||
|
image seems reasonable, e.g. is not empty, contains the expected sections, etc.
|
||||||
|
|
||||||
|
When your etype does use a bintool, it also needs tests, but generally it will
|
||||||
|
be tested by virtue of the etype test. This is because your etype must call the
|
||||||
|
bintool to create the image. Sometimes you might need to add a test for a
|
||||||
|
bintool error-condition, though.
|
||||||
|
|
||||||
|
Finishing code coverage
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
The objective is to have test-coverage for every line of code that you add to
|
||||||
|
Binman. So how can you tell? First, get a coverage report as described above.
|
||||||
|
Look through the output for any files which are not at 100%. Add more test cases
|
||||||
|
(image descriptions and new functions in ``ftest.py``) until you have covered
|
||||||
|
each line.
|
||||||
|
|
||||||
|
In the above example, here are some possible steps:
|
||||||
|
|
||||||
|
#. The first red bit is where the ``mkimage`` call returns None. This can be
|
||||||
|
traced to ``Bintoolmkimage.mkimage()`` which calls
|
||||||
|
``Bintool.run_cmd_result()`` and ``None`` means that ``mkimage`` is missing.
|
||||||
|
So the etype has code to handle that case, but it is never used. You can
|
||||||
|
look for other examples of ``self.mkimage`` returning ``None`` - e.g.
|
||||||
|
``Entry_mkimage.BuildSectionData()`` does this. The clue for finding this is
|
||||||
|
that the ``nxp-imx8mimage`` etype is based on ``Entry_mkimage``:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class Entry_nxp_imx8mimage(Entry_mkimage):
|
||||||
|
|
||||||
|
It must be tested somewhere...in this case ``testMkimage()`` doesn't do it,
|
||||||
|
but ``testMkimageMissing()`` immediately below that does. So you can create a
|
||||||
|
similar test, e.g.:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def testNxpImx8ImageMkimageMissing(self):
|
||||||
|
"""Test that binman can produce an iMX8 image"""
|
||||||
|
with test_util.capture_sys_output() as (_, stderr):
|
||||||
|
self._DoTestFile('339_nxp_imx8.dts',
|
||||||
|
force_missing_bintools='mkimage')
|
||||||
|
err = stderr.getvalue()
|
||||||
|
self.assertRegex(err, "Image 'image'.*missing bintools.*: mkimage")
|
||||||
|
|
||||||
|
Note that this uses exactly the same image description as the first test.
|
||||||
|
It just checks what happens when the tool is missing. Checking the coverage
|
||||||
|
again, you will see that the first red bit has gone:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ binman test -T
|
||||||
|
$ python3-coverage html
|
||||||
|
|
||||||
|
#. The second red bit is for ``SetImagePos()``. You can see that it is iterating
|
||||||
|
through the sub-entries inside the ``nxp-imx8mimage`` entry. In the case of
|
||||||
|
the 339 file, there are no such entries, so this code inside the for() loop
|
||||||
|
isn't used:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def SetImagePos(self, image_pos):
|
||||||
|
# Customized SoC specific SetImagePos which skips the mkimage etype
|
||||||
|
# implementation and removes the 0x48 offset introduced there. That
|
||||||
|
# offset is only used for uImage/fitImage, which is not the case in
|
||||||
|
# here.
|
||||||
|
upto = 0x00
|
||||||
|
for entry in super().GetEntries().values():
|
||||||
|
entry.SetOffsetSize(upto, None)
|
||||||
|
|
||||||
|
# Give up if any entries lack a size
|
||||||
|
if entry.size is None:
|
||||||
|
return
|
||||||
|
upto += entry.size
|
||||||
|
|
||||||
|
Entry_section.SetImagePos(self, image_pos)
|
||||||
|
|
||||||
|
The solution is to add an entry, e.g. in ``340_nxp_imx8_non_empty.dts``:
|
||||||
|
|
||||||
|
.. code-block:: devicetree
|
||||||
|
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
nxp-imx8mimage {
|
||||||
|
args; /* TODO: Needed by mkimage etype superclass */
|
||||||
|
nxp,boot-from = "sd";
|
||||||
|
nxp,rom-version = <1>;
|
||||||
|
nxp,loader-address = <0x10>;
|
||||||
|
|
||||||
|
u-boot {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Now write a little test to use it:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def testNxpImx8ImageNonEmpty(self):
|
||||||
|
"""Test that binman can produce an iMX8 image with something in it"""
|
||||||
|
data = self._DoReadFile('340_nxp_imx8_non_empty.dts')
|
||||||
|
# check data here
|
||||||
|
|
||||||
|
With that, the second red bit goes away, because the for() loop is now used.
|
||||||
|
|
||||||
|
#. There is one more red bit left, the ``return`` in ``SetImagePos()``. The
|
||||||
|
above effort got the for() loop to be executed, but it doesn't cover the
|
||||||
|
``return``. It might have been copied from some other etype, e.g. the mkimage
|
||||||
|
one. See ``Entry_mkimage.SetImagePos()`` which contains the code:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
for entry in self.GetEntries().values():
|
||||||
|
entry.SetOffsetSize(upto, None)
|
||||||
|
|
||||||
|
# Give up if any entries lack a size
|
||||||
|
if entry.size is None:
|
||||||
|
return
|
||||||
|
upto += entry.size
|
||||||
|
|
||||||
|
But which test covers that code for mkimage? By figuring that out, you could
|
||||||
|
use a similar technique. One way to find out is to delete the two lines in
|
||||||
|
``Entry_mkimage`` which check for entry.size being None and returning, then
|
||||||
|
see what breaks with ``binman test``:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
ERROR: binman.ftest.TestFunctional.testMkimageCollection (subunit.RemotedTestCase)
|
||||||
|
binman.ftest.TestFunctional.testMkimageCollection
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
testtools.testresult.real._StringException: Traceback (most recent call last):
|
||||||
|
TypeError: unsupported operand type(s) for +=: 'int' and 'NoneType'
|
||||||
|
|
||||||
|
======================================================================
|
||||||
|
ERROR: binman.ftest.TestFunctional.testMkimageImage (subunit.RemotedTestCase)
|
||||||
|
binman.ftest.TestFunctional.testMkimageImage
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
testtools.testresult.real._StringException: Traceback (most recent call last):
|
||||||
|
TypeError: unsupported operand type(s) for +=: 'int' and 'NoneType'
|
||||||
|
|
||||||
|
======================================================================
|
||||||
|
ERROR: binman.ftest.TestFunctional.testMkimageSpecial (subunit.RemotedTestCase)
|
||||||
|
binman.ftest.TestFunctional.testMkimageSpecial
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
testtools.testresult.real._StringException: Traceback (most recent call last):
|
||||||
|
TypeError: unsupported operand type(s) for +=: 'int' and 'NoneType'
|
||||||
|
|
||||||
|
We can verify that you got the right test, by putting the lines back in and
|
||||||
|
getting coverage for just that test:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
binman test -T testMkimageCollection
|
||||||
|
python3-coverage html
|
||||||
|
|
||||||
|
You will see a lot of red since we are seeing test coverage just for one
|
||||||
|
test, but if you look in ``mkimage.py`` at ``SetImagePos()`` you will see
|
||||||
|
that the ``return`` is covered (i.e. it is marked green).
|
||||||
|
|
||||||
|
Looking at the ``.dts`` files for each of these tests, none jumps out as
|
||||||
|
being relevant to our case. It seems that this code just isn't needed, so the
|
||||||
|
best solution is to delete those two lines from the function:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def SetImagePos(self, image_pos):
|
||||||
|
# Customized SoC specific SetImagePos which skips the mkimage etype
|
||||||
|
# implementation and removes the 0x48 offset introduced there. That
|
||||||
|
# offset is only used for uImage/fitImage, which is not the case in
|
||||||
|
# here.
|
||||||
|
upto = 0x00
|
||||||
|
for entry in super().GetEntries().values():
|
||||||
|
entry.SetOffsetSize(upto, None)
|
||||||
|
upto += entry.size
|
||||||
|
|
||||||
|
Entry_section.SetImagePos(self, image_pos)
|
||||||
|
|
||||||
|
We should check the updated code on a real build, to make sure it really
|
||||||
|
isn't needed, of course.
|
||||||
|
|
||||||
|
Now, the test coverage is complete!
|
||||||
|
|
||||||
|
If we later discover a case where those lines are needed, we can add the
|
||||||
|
lines back, along with a test for this case.
|
||||||
|
|
||||||
|
Getting help
|
||||||
|
------------
|
||||||
|
|
||||||
|
If you are stuck and cannot work out how to add test coverage for your entry
|
||||||
|
type, ask on the U-Boot mailing list, cc ``Simon Glass <sjg@chromium.org>`` or
|
||||||
|
on irc ``sjg1``
|
|
@ -94,7 +94,7 @@ them. Expo supports doing this with an enum, where every ID is listed in the
|
||||||
enum::
|
enum::
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ZERO,
|
ID_PROMPT = EXPOID_BASE_ID,
|
||||||
|
|
||||||
ID_PROMPT,
|
ID_PROMPT,
|
||||||
|
|
||||||
|
@ -130,6 +130,11 @@ that means that something is wrong with your syntax, or perhaps you have an ID
|
||||||
in the `.dts` file that is not mentioned in your enum. Check both files and try
|
in the `.dts` file that is not mentioned in your enum. Check both files and try
|
||||||
again.
|
again.
|
||||||
|
|
||||||
|
Note that the first ID in your file must be no less that `EXPOID_BASE_ID` since
|
||||||
|
IDs before that are reserved. The `expo.py` tool automatically obtains this
|
||||||
|
value from the `expo.h` header file, but you must set the first ID to this
|
||||||
|
enum value.
|
||||||
|
|
||||||
|
|
||||||
Use the command interface
|
Use the command interface
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
|
@ -88,8 +88,13 @@ or even the IDs of objects. Programmatic creation of many items in a loop can be
|
||||||
handled by allocating space in the enum for a maximum number of items, then
|
handled by allocating space in the enum for a maximum number of items, then
|
||||||
adding the loop count to the enum values to obtain unique IDs.
|
adding the loop count to the enum values to obtain unique IDs.
|
||||||
|
|
||||||
Where dynamic IDs are need, use expo_set_dynamic_start() to set the start value,
|
Some standard IDs are reserved for certain purposes. These are defined by
|
||||||
so that they are allocated above the starting (enum) IDs.
|
`enum expo_id_t` and start at 1. `EXPOID_BASE_ID` defines the first ID which
|
||||||
|
can be used for an expo.
|
||||||
|
|
||||||
|
An ID of 0 is invalid. If this is specified in an expo call then a valid
|
||||||
|
'dynamic IDs is allocated. Use expo_set_dynamic_start() to set the start
|
||||||
|
value, so that they are allocated above the starting (enum) IDs.
|
||||||
|
|
||||||
All text strings are stored in a structure attached to the expo, referenced by
|
All text strings are stored in a structure attached to the expo, referenced by
|
||||||
a text ID. This makes it easier at some point to implement multiple languages or
|
a text ID. This makes it easier at some point to implement multiple languages or
|
||||||
|
@ -176,6 +181,10 @@ menu-inset
|
||||||
menuitem-gap-y
|
menuitem-gap-y
|
||||||
Number of pixels between menu items
|
Number of pixels between menu items
|
||||||
|
|
||||||
|
menu-title-margin-x
|
||||||
|
Number of pixels between right side of menu title to the left size of the
|
||||||
|
menu labels
|
||||||
|
|
||||||
Pop-up mode
|
Pop-up mode
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@ -352,6 +361,13 @@ item-id
|
||||||
Specifies the ID for each menu item. These are used for checking which item
|
Specifies the ID for each menu item. These are used for checking which item
|
||||||
has been selected.
|
has been selected.
|
||||||
|
|
||||||
|
item-value
|
||||||
|
type: u32 list, optional
|
||||||
|
|
||||||
|
Specifies the value for each menu item. These are used for saving and
|
||||||
|
loading. If this is omitted the value is its position in the menu (0..n-1).
|
||||||
|
Valid values are positive and negative integers INT_MIN...(INT_MAX - 1).
|
||||||
|
|
||||||
item-label / item-label-id
|
item-label / item-label-id
|
||||||
type: string list / u32 list, required
|
type: string list / u32 list, required
|
||||||
|
|
||||||
|
@ -413,8 +429,7 @@ strings are provided inline in the nodes where they are used.
|
||||||
/* this comment is parsed by the expo.py tool to insert the values below
|
/* this comment is parsed by the expo.py tool to insert the values below
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ZERO,
|
ID_PROMPT = EXPOID_BASE_ID,
|
||||||
ID_PROMPT,
|
|
||||||
ID_SCENE1,
|
ID_SCENE1,
|
||||||
ID_SCENE1_TITLE,
|
ID_SCENE1_TITLE,
|
||||||
|
|
||||||
|
@ -466,6 +481,9 @@ strings are provided inline in the nodes where they are used.
|
||||||
/* IDs for the menu items */
|
/* IDs for the menu items */
|
||||||
item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2
|
item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2
|
||||||
ID_CPU_SPEED_3>;
|
ID_CPU_SPEED_3>;
|
||||||
|
|
||||||
|
/* values for the menu items */
|
||||||
|
item-value = <(-1) 3 6>;
|
||||||
};
|
};
|
||||||
|
|
||||||
power-loss {
|
power-loss {
|
||||||
|
|
|
@ -83,6 +83,7 @@ Testing
|
||||||
py_testing
|
py_testing
|
||||||
tests_writing
|
tests_writing
|
||||||
tests_sandbox
|
tests_sandbox
|
||||||
|
binman_tests
|
||||||
|
|
||||||
Refactoring
|
Refactoring
|
||||||
-----------
|
-----------
|
||||||
|
|
|
@ -107,8 +107,10 @@ That results in::
|
||||||
/ {
|
/ {
|
||||||
cedit-values {
|
cedit-values {
|
||||||
cpu-speed = <0x00000006>;
|
cpu-speed = <0x00000006>;
|
||||||
|
cpu-speed-value = <0x00000003>;
|
||||||
cpu-speed-str = "2 GHz";
|
cpu-speed-str = "2 GHz";
|
||||||
power-loss = <0x0000000a>;
|
power-loss = <0x0000000a>;
|
||||||
|
power-loss-value = <0x00000000>;
|
||||||
power-loss-str = "Always Off";
|
power-loss-str = "Always Off";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -118,16 +120,23 @@ That results in::
|
||||||
This shows settings being stored in the environment::
|
This shows settings being stored in the environment::
|
||||||
|
|
||||||
=> cedit write_env -v
|
=> cedit write_env -v
|
||||||
c.cpu-speed=7
|
c.cpu-speed=11
|
||||||
c.cpu-speed-str=2.5 GHz
|
c.cpu-speed-str=2.5 GHz
|
||||||
c.power-loss=12
|
c.cpu-speed-value=3
|
||||||
c.power-loss-str=Memory
|
c.power-loss=14
|
||||||
|
c.power-loss-str=Always Off
|
||||||
|
c.power-loss-value=0
|
||||||
|
c.machine-name=my-machine
|
||||||
|
c.cpu-speed=11
|
||||||
|
c.power-loss=14
|
||||||
|
c.machine-name=my-machine
|
||||||
=> print
|
=> print
|
||||||
...
|
...
|
||||||
c.cpu-speed=6
|
c.cpu-speed=6
|
||||||
c.cpu-speed-str=2 GHz
|
c.cpu-speed-str=2 GHz
|
||||||
c.power-loss=10
|
c.power-loss=10
|
||||||
c.power-loss-str=Always Off
|
c.power-loss-str=Always Off
|
||||||
|
c.machine-name=my-machine
|
||||||
...
|
...
|
||||||
|
|
||||||
=> cedit read_env -v
|
=> cedit read_env -v
|
||||||
|
|
68
doc/usage/cmd/cpuid.rst
Normal file
68
doc/usage/cmd/cpuid.rst
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
.. SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
.. index::
|
||||||
|
single: cpuid (command)
|
||||||
|
|
||||||
|
cpuid command
|
||||||
|
=============
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
--------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
cpuid <op>
|
||||||
|
|
||||||
|
Description
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The cpuid command requests CPU-identification information on x86 CPUs. The
|
||||||
|
operation <op> selects what information is returned. Up to four 32-bit registers
|
||||||
|
can be update (eax-edx) depending on the operation.
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The cpuid command is only available on x86.
|
||||||
|
|
||||||
|
Return value
|
||||||
|
------------
|
||||||
|
|
||||||
|
The return value $? is 0 (true).
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
=> cpuid 1
|
||||||
|
eax 00060fb1
|
||||||
|
ebx 00040800
|
||||||
|
ecx 80002001
|
||||||
|
edx 178bfbfd
|
||||||
|
|
||||||
|
This shows checking for 64-bit 'long' mode::
|
||||||
|
|
||||||
|
=> cpuid 80000000
|
||||||
|
eax 8000000a
|
||||||
|
ebx 68747541
|
||||||
|
ecx 444d4163
|
||||||
|
edx 69746e65
|
||||||
|
=> cpuid 80000001
|
||||||
|
eax 00060fb1
|
||||||
|
ebx 00000000
|
||||||
|
ecx 00000007
|
||||||
|
edx 2193fbfd # Bit 29 is set in edx, so long mode is available
|
||||||
|
|
||||||
|
On a 32-bit-only CPU::
|
||||||
|
|
||||||
|
=> cpuid 80000000
|
||||||
|
eax 80000004
|
||||||
|
ebx 756e6547
|
||||||
|
ecx 6c65746e
|
||||||
|
edx 49656e69
|
||||||
|
=> cpuid 80000001
|
||||||
|
eax 00000663
|
||||||
|
ebx 00000000
|
||||||
|
ecx 00000000
|
||||||
|
edx 00000000 # Bit 29 is not set in edx, so long mode is not available
|
|
@ -13,7 +13,7 @@ Synopsis
|
||||||
|
|
||||||
font list
|
font list
|
||||||
font select <name> [<size>]
|
font select <name> [<size>]
|
||||||
font size <size>
|
font size [<size>]
|
||||||
|
|
||||||
Description
|
Description
|
||||||
-----------
|
-----------
|
||||||
|
@ -34,7 +34,7 @@ This selects a new font and optionally changes the size.
|
||||||
font size
|
font size
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
||||||
This changes the font size only.
|
This changes the font size only. With no argument it shows the current size.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
@ -44,6 +44,8 @@ Examples
|
||||||
=> font list
|
=> font list
|
||||||
nimbus_sans_l_regular
|
nimbus_sans_l_regular
|
||||||
cantoraone_regular
|
cantoraone_regular
|
||||||
|
=> font size
|
||||||
|
30
|
||||||
=> font size 40
|
=> font size 40
|
||||||
=> font select cantoraone_regular 20
|
=> font select cantoraone_regular 20
|
||||||
=>
|
=>
|
||||||
|
|
61
doc/usage/cmd/msr.rst
Normal file
61
doc/usage/cmd/msr.rst
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
.. SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
.. index::
|
||||||
|
single: msr (command)
|
||||||
|
|
||||||
|
msr command
|
||||||
|
===========
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
--------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
msr read <op>
|
||||||
|
msr write <op> <hi> <lo>
|
||||||
|
|
||||||
|
Description
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The msr command reads and writes machine-status registers (MSRs) on x86 CPUs.
|
||||||
|
The information is a 64-bit value split into two parts, <hi> for the top 32
|
||||||
|
bits and <lo> for the bottom 32 bits.
|
||||||
|
|
||||||
|
The operation <op> selects what information is read or written.
|
||||||
|
|
||||||
|
msr read
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
This reads an MSR and displays the value obtained.
|
||||||
|
|
||||||
|
msr write
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
This writes a value to an MSR.
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The msr command is only available on x86.
|
||||||
|
|
||||||
|
Return value
|
||||||
|
------------
|
||||||
|
|
||||||
|
The return value $? is 0 (true).
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
This shows reading msr 0x194 which is MSR_FLEX_RATIO on Intel CPUs::
|
||||||
|
|
||||||
|
=> msr read 194
|
||||||
|
00000000 00011200 # Bits 16 (flex ratio enable) and 20 (lock) are set
|
||||||
|
|
||||||
|
This shows adjusting the energy-performance bias on an Intel CPU::
|
||||||
|
|
||||||
|
=> msr read 1b0
|
||||||
|
00000000 00000006 # 6 means 'normal'
|
||||||
|
|
||||||
|
=> msr write 1b0 0 f # change to power-save
|
||||||
|
=> msr read 1b0
|
||||||
|
00000000 0000000f
|
|
@ -52,6 +52,7 @@ Shell commands
|
||||||
cmd/conitrace
|
cmd/conitrace
|
||||||
cmd/cp
|
cmd/cp
|
||||||
cmd/cpu
|
cmd/cpu
|
||||||
|
cmd/cpuid
|
||||||
cmd/cyclic
|
cmd/cyclic
|
||||||
cmd/dm
|
cmd/dm
|
||||||
cmd/ebtupdate
|
cmd/ebtupdate
|
||||||
|
@ -86,6 +87,7 @@ Shell commands
|
||||||
cmd/mbr
|
cmd/mbr
|
||||||
cmd/md
|
cmd/md
|
||||||
cmd/mmc
|
cmd/mmc
|
||||||
|
cmd/msr
|
||||||
cmd/mtest
|
cmd/mtest
|
||||||
cmd/mtrr
|
cmd/mtrr
|
||||||
cmd/panic
|
cmd/panic
|
||||||
|
|
|
@ -83,7 +83,7 @@ static unsigned long cpu_mhz_from_cpuid(void)
|
||||||
if (cpuid_eax(0) < 0x16)
|
if (cpuid_eax(0) < 0x16)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return cpuid_eax(0x16);
|
return cpuid_eax(0x15);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -299,10 +299,19 @@ static unsigned long __maybe_unused quick_pit_calibrate(void)
|
||||||
if (!pit_expect_msb(0xff-i, &delta, &d2))
|
if (!pit_expect_msb(0xff-i, &delta, &d2))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
delta -= tsc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extrapolate the error and fail fast if the error will
|
||||||
|
* never be below 500 ppm.
|
||||||
|
*/
|
||||||
|
if (i == 1 &&
|
||||||
|
d1 + d2 >= (delta * MAX_QUICK_PIT_ITERATIONS) >> 11)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate until the error is less than 500 ppm
|
* Iterate until the error is less than 500 ppm
|
||||||
*/
|
*/
|
||||||
delta -= tsc;
|
|
||||||
if (d1+d2 >= delta >> 11)
|
if (d1+d2 >= delta >> 11)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -403,6 +412,10 @@ static void tsc_timer_ensure_setup(bool early)
|
||||||
if (!gd->arch.clock_rate) {
|
if (!gd->arch.clock_rate) {
|
||||||
unsigned long fast_calibrate;
|
unsigned long fast_calibrate;
|
||||||
|
|
||||||
|
/* deal with this being called before x86_cpu_init_f() */
|
||||||
|
if (!gd->arch.x86_vendor)
|
||||||
|
x86_get_identity_for_timer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There is no obvious way to obtain this information from EFI
|
* There is no obvious way to obtain this information from EFI
|
||||||
* boot services. This value was measured on a Framework Laptop
|
* boot services. This value was measured on a Framework Laptop
|
||||||
|
@ -438,6 +451,7 @@ static void tsc_timer_ensure_setup(bool early)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
fast_calibrate = min(fast_calibrate, 4000UL);
|
||||||
if (!gd->arch.clock_rate)
|
if (!gd->arch.clock_rate)
|
||||||
gd->arch.clock_rate = fast_calibrate * 1000000;
|
gd->arch.clock_rate = fast_calibrate * 1000000;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,9 @@ static void vidconsole_newline(struct udevice *dev)
|
||||||
priv->ycur += priv->y_charsize;
|
priv->ycur += priv->y_charsize;
|
||||||
|
|
||||||
/* Check if we need to scroll the terminal */
|
/* Check if we need to scroll the terminal */
|
||||||
if ((priv->ycur + priv->y_charsize) / priv->y_charsize > priv->rows) {
|
if (vid_priv->rot % 2 ?
|
||||||
|
priv->ycur + priv->x_charsize > vid_priv->xsize :
|
||||||
|
priv->ycur + priv->y_charsize > vid_priv->ysize) {
|
||||||
vidconsole_move_rows(dev, 0, rows, priv->rows - rows);
|
vidconsole_move_rows(dev, 0, rows, priv->rows - rows);
|
||||||
for (i = 0; i < rows; i++)
|
for (i = 0; i < rows; i++)
|
||||||
vidconsole_set_row(dev, priv->rows - i - 1,
|
vidconsole_set_row(dev, priv->rows - i - 1,
|
||||||
|
|
|
@ -294,6 +294,9 @@ static const struct vid_rgb colours[VID_COLOUR_COUNT] = {
|
||||||
{ 0xff, 0x00, 0xff }, /* bright magenta */
|
{ 0xff, 0x00, 0xff }, /* bright magenta */
|
||||||
{ 0x00, 0xff, 0xff }, /* bright cyan */
|
{ 0x00, 0xff, 0xff }, /* bright cyan */
|
||||||
{ 0xff, 0xff, 0xff }, /* white */
|
{ 0xff, 0xff, 0xff }, /* white */
|
||||||
|
|
||||||
|
/* an extra one for menus */
|
||||||
|
{ 0x40, 0x40, 0x40 }, /* dark gray */
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 video_index_to_colour(struct video_priv *priv, enum colour_idx idx)
|
u32 video_index_to_colour(struct video_priv *priv, enum colour_idx idx)
|
||||||
|
|
|
@ -18,30 +18,82 @@ struct virtio_blk_priv {
|
||||||
struct virtqueue *vq;
|
struct virtqueue *vq;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const u32 feature[] = {
|
||||||
|
VIRTIO_BLK_F_WRITE_ZEROES
|
||||||
|
};
|
||||||
|
|
||||||
|
static void virtio_blk_init_header_sg(struct udevice *dev, u64 sector, u32 type,
|
||||||
|
struct virtio_blk_outhdr *out_hdr, struct virtio_sg *sg)
|
||||||
|
{
|
||||||
|
const bool sector_is_needed = type == VIRTIO_BLK_T_IN ||
|
||||||
|
type == VIRTIO_BLK_T_OUT;
|
||||||
|
|
||||||
|
out_hdr->type = cpu_to_virtio32(dev, type);
|
||||||
|
out_hdr->sector = cpu_to_virtio64(dev, sector_is_needed ? sector : 0);
|
||||||
|
|
||||||
|
sg->addr = out_hdr;
|
||||||
|
sg->length = sizeof(*out_hdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_blk_init_write_zeroes_sg(struct udevice *dev, u64 sector, lbaint_t blkcnt,
|
||||||
|
struct virtio_blk_discard_write_zeroes *wz,
|
||||||
|
struct virtio_sg *sg)
|
||||||
|
{
|
||||||
|
wz->sector = cpu_to_virtio64(dev, sector);
|
||||||
|
wz->num_sectors = cpu_to_virtio32(dev, blkcnt);
|
||||||
|
wz->flags = cpu_to_virtio32(dev, 0);
|
||||||
|
|
||||||
|
sg->addr = wz;
|
||||||
|
sg->length = sizeof(*wz);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_blk_init_status_sg(u8 *status, struct virtio_sg *sg)
|
||||||
|
{
|
||||||
|
sg->addr = status;
|
||||||
|
sg->length = sizeof(*status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_blk_init_data_sg(void *buffer, lbaint_t blkcnt, struct virtio_sg *sg)
|
||||||
|
{
|
||||||
|
sg->addr = buffer;
|
||||||
|
sg->length = blkcnt * 512;
|
||||||
|
}
|
||||||
|
|
||||||
static ulong virtio_blk_do_req(struct udevice *dev, u64 sector,
|
static ulong virtio_blk_do_req(struct udevice *dev, u64 sector,
|
||||||
lbaint_t blkcnt, void *buffer, u32 type)
|
lbaint_t blkcnt, void *buffer, u32 type)
|
||||||
{
|
{
|
||||||
struct virtio_blk_priv *priv = dev_get_priv(dev);
|
struct virtio_blk_priv *priv = dev_get_priv(dev);
|
||||||
|
struct virtio_blk_outhdr out_hdr;
|
||||||
|
struct virtio_blk_discard_write_zeroes wz_hdr;
|
||||||
unsigned int num_out = 0, num_in = 0;
|
unsigned int num_out = 0, num_in = 0;
|
||||||
|
struct virtio_sg hdr_sg, wz_sg, data_sg, status_sg;
|
||||||
struct virtio_sg *sgs[3];
|
struct virtio_sg *sgs[3];
|
||||||
u8 status;
|
u8 status;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
struct virtio_blk_outhdr out_hdr = {
|
virtio_blk_init_header_sg(dev, sector, type, &out_hdr, &hdr_sg);
|
||||||
.type = cpu_to_virtio32(dev, type),
|
|
||||||
.sector = cpu_to_virtio64(dev, sector),
|
|
||||||
};
|
|
||||||
struct virtio_sg hdr_sg = { &out_hdr, sizeof(out_hdr) };
|
|
||||||
struct virtio_sg data_sg = { buffer, blkcnt * 512 };
|
|
||||||
struct virtio_sg status_sg = { &status, sizeof(status) };
|
|
||||||
|
|
||||||
sgs[num_out++] = &hdr_sg;
|
sgs[num_out++] = &hdr_sg;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case VIRTIO_BLK_T_IN:
|
||||||
|
case VIRTIO_BLK_T_OUT:
|
||||||
|
virtio_blk_init_data_sg(buffer, blkcnt, &data_sg);
|
||||||
if (type & VIRTIO_BLK_T_OUT)
|
if (type & VIRTIO_BLK_T_OUT)
|
||||||
sgs[num_out++] = &data_sg;
|
sgs[num_out++] = &data_sg;
|
||||||
else
|
else
|
||||||
sgs[num_out + num_in++] = &data_sg;
|
sgs[num_out + num_in++] = &data_sg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIRTIO_BLK_T_WRITE_ZEROES:
|
||||||
|
virtio_blk_init_write_zeroes_sg(dev, sector, blkcnt, &wz_hdr, &wz_sg);
|
||||||
|
sgs[num_out++] = &wz_sg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtio_blk_init_status_sg(&status, &status_sg);
|
||||||
sgs[num_out + num_in++] = &status_sg;
|
sgs[num_out + num_in++] = &status_sg;
|
||||||
log_debug("dev=%s, active=%d, priv=%p, priv->vq=%p\n", dev->name,
|
log_debug("dev=%s, active=%d, priv=%p, priv->vq=%p\n", dev->name,
|
||||||
device_active(dev), priv, priv->vq);
|
device_active(dev), priv, priv->vq);
|
||||||
|
@ -75,6 +127,15 @@ static ulong virtio_blk_write(struct udevice *dev, lbaint_t start,
|
||||||
VIRTIO_BLK_T_OUT);
|
VIRTIO_BLK_T_OUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ulong virtio_blk_erase(struct udevice *dev, lbaint_t start,
|
||||||
|
lbaint_t blkcnt)
|
||||||
|
{
|
||||||
|
if (!virtio_has_feature(dev, VIRTIO_BLK_F_WRITE_ZEROES))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
return virtio_blk_do_req(dev, start, blkcnt, NULL, VIRTIO_BLK_T_WRITE_ZEROES);
|
||||||
|
}
|
||||||
|
|
||||||
static int virtio_blk_bind(struct udevice *dev)
|
static int virtio_blk_bind(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev->parent);
|
struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev->parent);
|
||||||
|
@ -104,7 +165,8 @@ static int virtio_blk_bind(struct udevice *dev)
|
||||||
desc->bdev = dev;
|
desc->bdev = dev;
|
||||||
|
|
||||||
/* Indicate what driver features we support */
|
/* Indicate what driver features we support */
|
||||||
virtio_driver_features_init(uc_priv, NULL, 0, NULL, 0);
|
virtio_driver_features_init(uc_priv, feature, ARRAY_SIZE(feature),
|
||||||
|
NULL, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -131,6 +193,7 @@ static int virtio_blk_probe(struct udevice *dev)
|
||||||
static const struct blk_ops virtio_blk_ops = {
|
static const struct blk_ops virtio_blk_ops = {
|
||||||
.read = virtio_blk_read,
|
.read = virtio_blk_read,
|
||||||
.write = virtio_blk_write,
|
.write = virtio_blk_write,
|
||||||
|
.erase = virtio_blk_erase,
|
||||||
};
|
};
|
||||||
|
|
||||||
U_BOOT_DRIVER(virtio_blk) = {
|
U_BOOT_DRIVER(virtio_blk) = {
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available */
|
#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available */
|
||||||
#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */
|
#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */
|
||||||
#define VIRTIO_BLK_F_MQ 12 /* Support more than one vq */
|
#define VIRTIO_BLK_F_MQ 12 /* Support more than one vq */
|
||||||
|
#define VIRTIO_BLK_F_DISCARD 13 /* Discard is supported */
|
||||||
|
#define VIRTIO_BLK_F_WRITE_ZEROES 14 /* Write zeroes is supported */
|
||||||
|
|
||||||
/* Legacy feature bits */
|
/* Legacy feature bits */
|
||||||
#ifndef VIRTIO_BLK_NO_LEGACY
|
#ifndef VIRTIO_BLK_NO_LEGACY
|
||||||
|
@ -65,6 +67,39 @@ struct __packed virtio_blk_config {
|
||||||
|
|
||||||
/* number of vqs, only available when VIRTIO_BLK_F_MQ is set */
|
/* number of vqs, only available when VIRTIO_BLK_F_MQ is set */
|
||||||
__u16 num_queues;
|
__u16 num_queues;
|
||||||
|
|
||||||
|
/* the next 3 entries are guarded by VIRTIO_BLK_F_DISCARD */
|
||||||
|
/*
|
||||||
|
* The maximum discard sectors (in 512-byte sectors) for
|
||||||
|
* one segment.
|
||||||
|
*/
|
||||||
|
__u32 max_discard_sectors;
|
||||||
|
/*
|
||||||
|
* The maximum number of discard segments in a
|
||||||
|
* discard command.
|
||||||
|
*/
|
||||||
|
__u32 max_discard_seg;
|
||||||
|
/* Discard commands must be aligned to this number of sectors. */
|
||||||
|
__u32 discard_sector_alignment;
|
||||||
|
|
||||||
|
/* the next 3 entries are guarded by VIRTIO_BLK_F_WRITE_ZEROES */
|
||||||
|
/*
|
||||||
|
* The maximum number of write zeroes sectors (in 512-byte sectors) in
|
||||||
|
* one segment.
|
||||||
|
*/
|
||||||
|
__u32 max_write_zeroes_sectors;
|
||||||
|
/*
|
||||||
|
* The maximum number of segments in a write zeroes
|
||||||
|
* command.
|
||||||
|
*/
|
||||||
|
__u32 max_write_zeroes_seg;
|
||||||
|
/*
|
||||||
|
* Set if a VIRTIO_BLK_T_WRITE_ZEROES request may result in the
|
||||||
|
* deallocation of one or more of the sectors.
|
||||||
|
*/
|
||||||
|
__u8 write_zeroes_may_unmap;
|
||||||
|
|
||||||
|
__u8 unused1[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -93,6 +128,9 @@ struct __packed virtio_blk_config {
|
||||||
/* Get device ID command */
|
/* Get device ID command */
|
||||||
#define VIRTIO_BLK_T_GET_ID 8
|
#define VIRTIO_BLK_T_GET_ID 8
|
||||||
|
|
||||||
|
/* Write zeroes command */
|
||||||
|
#define VIRTIO_BLK_T_WRITE_ZEROES 13
|
||||||
|
|
||||||
#ifndef VIRTIO_BLK_NO_LEGACY
|
#ifndef VIRTIO_BLK_NO_LEGACY
|
||||||
/* Barrier before this op */
|
/* Barrier before this op */
|
||||||
#define VIRTIO_BLK_T_BARRIER 0x80000000
|
#define VIRTIO_BLK_T_BARRIER 0x80000000
|
||||||
|
@ -112,6 +150,15 @@ struct virtio_blk_outhdr {
|
||||||
__virtio64 sector;
|
__virtio64 sector;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct virtio_blk_discard_write_zeroes {
|
||||||
|
/* discard/write zeroes start sector */
|
||||||
|
__virtio64 sector;
|
||||||
|
/* number of discard/write zeroes sectors */
|
||||||
|
__virtio32 num_sectors;
|
||||||
|
/* flags for this range */
|
||||||
|
__virtio32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
#ifndef VIRTIO_BLK_NO_LEGACY
|
#ifndef VIRTIO_BLK_NO_LEGACY
|
||||||
struct virtio_scsi_inhdr {
|
struct virtio_scsi_inhdr {
|
||||||
__virtio32 errors;
|
__virtio32 errors;
|
||||||
|
|
|
@ -197,7 +197,6 @@ static inline void blkcache_free(void) {}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(BLK)
|
|
||||||
struct udevice;
|
struct udevice;
|
||||||
|
|
||||||
/* Operations on block devices */
|
/* Operations on block devices */
|
||||||
|
@ -278,6 +277,8 @@ struct blk_ops {
|
||||||
#endif /* CONFIG_BOUNCE_BUFFER */
|
#endif /* CONFIG_BOUNCE_BUFFER */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(BLK)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions should take struct udevice instead of struct blk_desc,
|
* These functions should take struct udevice instead of struct blk_desc,
|
||||||
* but this is convenient for migration to driver model. Add a 'd' prefix
|
* but this is convenient for migration to driver model. Add a 'd' prefix
|
||||||
|
@ -291,6 +292,8 @@ unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start,
|
||||||
unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start,
|
unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start,
|
||||||
lbaint_t blkcnt);
|
lbaint_t blkcnt);
|
||||||
|
|
||||||
|
#endif /* BLK */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* blk_read() - Read from a block device
|
* blk_read() - Read from a block device
|
||||||
*
|
*
|
||||||
|
@ -528,8 +531,10 @@ struct blk_desc *blk_get_by_device(struct udevice *dev);
|
||||||
*/
|
*/
|
||||||
int blk_get_desc(enum uclass_id uclass_id, int devnum, struct blk_desc **descp);
|
int blk_get_desc(enum uclass_id uclass_id, int devnum, struct blk_desc **descp);
|
||||||
|
|
||||||
#else
|
#if !CONFIG_IS_ENABLED(BLK)
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions should take struct udevice instead of struct blk_desc,
|
* These functions should take struct udevice instead of struct blk_desc,
|
||||||
* but this is convenient for migration to driver model. Add a 'd' prefix
|
* but this is convenient for migration to driver model. Add a 'd' prefix
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
struct abuf;
|
struct abuf;
|
||||||
struct expo;
|
struct expo;
|
||||||
struct scene;
|
struct scene;
|
||||||
|
struct udevice;
|
||||||
struct video_priv;
|
struct video_priv;
|
||||||
struct udevice;
|
struct udevice;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,26 @@ struct udevice;
|
||||||
|
|
||||||
#include <cli.h>
|
#include <cli.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum expo_id_t - standard expo IDs
|
||||||
|
*
|
||||||
|
* These are assumed to be in use at all times. Expos should use IDs starting
|
||||||
|
* from EXPOID_BASE_ID,
|
||||||
|
*
|
||||||
|
* @EXPOID_NONE: Not used, invalid ID 0
|
||||||
|
* @EXPOID_SAVE: User has requested that the expo data be saved
|
||||||
|
* @EXPOID_DISCARD: User has requested that the expo data be discarded
|
||||||
|
* @EXPOID_BASE_ID: First ID which can be used for expo objects
|
||||||
|
*/
|
||||||
|
enum expo_id_t {
|
||||||
|
EXPOID_NONE,
|
||||||
|
|
||||||
|
EXPOID_SAVE,
|
||||||
|
EXPOID_DISCARD,
|
||||||
|
|
||||||
|
EXPOID_BASE_ID = 5,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum expoact_type - types of actions reported by the expo
|
* enum expoact_type - types of actions reported by the expo
|
||||||
*
|
*
|
||||||
|
@ -59,11 +79,14 @@ struct expo_action {
|
||||||
* @font_size: Default font size for all text
|
* @font_size: Default font size for all text
|
||||||
* @menu_inset: Inset width (on each side and top/bottom) for menu items
|
* @menu_inset: Inset width (on each side and top/bottom) for menu items
|
||||||
* @menuitem_gap_y: Gap between menu items in pixels
|
* @menuitem_gap_y: Gap between menu items in pixels
|
||||||
|
* @menu_title_margin_x: Gap between right side of menu title and left size of
|
||||||
|
* menu label
|
||||||
*/
|
*/
|
||||||
struct expo_theme {
|
struct expo_theme {
|
||||||
u32 font_size;
|
u32 font_size;
|
||||||
u32 menu_inset;
|
u32 menu_inset;
|
||||||
u32 menuitem_gap_y;
|
u32 menuitem_gap_y;
|
||||||
|
u32 menu_title_margin_x;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -307,6 +330,7 @@ enum scene_menuitem_flags_t {
|
||||||
* @desc_id: ID of text object to use as the description text
|
* @desc_id: ID of text object to use as the description text
|
||||||
* @preview_id: ID of the preview object, or 0 if none
|
* @preview_id: ID of the preview object, or 0 if none
|
||||||
* @flags: Flags for this item
|
* @flags: Flags for this item
|
||||||
|
* @value: Value for this item, or INT_MAX to use sequence
|
||||||
* @sibling: Node to link this item to its siblings
|
* @sibling: Node to link this item to its siblings
|
||||||
*/
|
*/
|
||||||
struct scene_menitem {
|
struct scene_menitem {
|
||||||
|
@ -317,6 +341,7 @@ struct scene_menitem {
|
||||||
uint desc_id;
|
uint desc_id;
|
||||||
uint preview_id;
|
uint preview_id;
|
||||||
uint flags;
|
uint flags;
|
||||||
|
int value;
|
||||||
struct list_head sibling;
|
struct list_head sibling;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -341,6 +366,15 @@ struct scene_obj_textline {
|
||||||
uint pos;
|
uint pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct expo_arrange_info - Information used when arranging a scene
|
||||||
|
*
|
||||||
|
* @label_width: Maximum width of labels in scene
|
||||||
|
*/
|
||||||
|
struct expo_arrange_info {
|
||||||
|
int label_width;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* expo_new() - create a new expo
|
* expo_new() - create a new expo
|
||||||
*
|
*
|
||||||
|
@ -506,15 +540,6 @@ void scene_set_highlight_id(struct scene *scn, uint id);
|
||||||
*/
|
*/
|
||||||
int scene_set_open(struct scene *scn, uint id, bool open);
|
int scene_set_open(struct scene *scn, uint id, bool open);
|
||||||
|
|
||||||
/**
|
|
||||||
* scene_title_set() - set the scene title
|
|
||||||
*
|
|
||||||
* @scn: Scene to update
|
|
||||||
* @title_id: Title ID to set
|
|
||||||
* Returns: 0 if OK
|
|
||||||
*/
|
|
||||||
int scene_title_set(struct scene *scn, uint title_id);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* scene_obj_count() - Count the number of objects in a scene
|
* scene_obj_count() - Count the number of objects in a scene
|
||||||
*
|
*
|
||||||
|
|
|
@ -9,24 +9,24 @@
|
||||||
#ifndef __cedit_test_h
|
#ifndef __cedit_test_h
|
||||||
#define __cedit_test_h
|
#define __cedit_test_h
|
||||||
|
|
||||||
#define ID_PROMPT 1
|
#define ID_PROMPT 5
|
||||||
#define ID_SCENE1 2
|
#define ID_SCENE1 6
|
||||||
#define ID_SCENE1_TITLE 3
|
#define ID_SCENE1_TITLE 7
|
||||||
|
|
||||||
#define ID_CPU_SPEED 4
|
#define ID_CPU_SPEED 8
|
||||||
#define ID_CPU_SPEED_TITLE 5
|
#define ID_CPU_SPEED_TITLE 9
|
||||||
#define ID_CPU_SPEED_1 6
|
#define ID_CPU_SPEED_1 10
|
||||||
#define ID_CPU_SPEED_2 7
|
#define ID_CPU_SPEED_2 11
|
||||||
#define ID_CPU_SPEED_3 8
|
#define ID_CPU_SPEED_3 12
|
||||||
|
|
||||||
#define ID_POWER_LOSS 9
|
#define ID_POWER_LOSS 13
|
||||||
#define ID_AC_OFF 10
|
#define ID_AC_OFF 14
|
||||||
#define ID_AC_ON 11
|
#define ID_AC_ON 15
|
||||||
#define ID_AC_MEMORY 12
|
#define ID_AC_MEMORY 16
|
||||||
|
|
||||||
#define ID_MACHINE_NAME 13
|
#define ID_MACHINE_NAME 17
|
||||||
#define ID_MACHINE_NAME_EDIT 14
|
#define ID_MACHINE_NAME_EDIT 18
|
||||||
|
|
||||||
#define ID_DYNAMIC_START 15
|
#define ID_DYNAMIC_START 19
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -78,7 +78,8 @@ enum video_format {
|
||||||
*
|
*
|
||||||
* @xsize: Number of pixel columns (e.g. 1366)
|
* @xsize: Number of pixel columns (e.g. 1366)
|
||||||
* @ysize: Number of pixels rows (e.g.. 768)
|
* @ysize: Number of pixels rows (e.g.. 768)
|
||||||
* @rot: Display rotation (0=none, 1=90 degrees clockwise, etc.)
|
* @rot: Display rotation (0=none, 1=90 degrees clockwise, etc.). THis
|
||||||
|
* does not affect @xsize and @ysize
|
||||||
* @bpix: Encoded bits per pixel (enum video_log2_bpp)
|
* @bpix: Encoded bits per pixel (enum video_log2_bpp)
|
||||||
* @format: Pixel format (enum video_format)
|
* @format: Pixel format (enum video_format)
|
||||||
* @vidconsole_drv_name: Driver to use for the text console, NULL to
|
* @vidconsole_drv_name: Driver to use for the text console, NULL to
|
||||||
|
@ -181,6 +182,7 @@ enum colour_idx {
|
||||||
VID_LIGHT_MAGENTA,
|
VID_LIGHT_MAGENTA,
|
||||||
VID_LIGHT_CYAN,
|
VID_LIGHT_CYAN,
|
||||||
VID_WHITE,
|
VID_WHITE,
|
||||||
|
VID_DARK_GREY,
|
||||||
|
|
||||||
VID_COLOUR_COUNT
|
VID_COLOUR_COUNT
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,14 @@ enum {
|
||||||
* Drivers must set up @rows, @cols, @x_charsize, @y_charsize in their probe()
|
* Drivers must set up @rows, @cols, @x_charsize, @y_charsize in their probe()
|
||||||
* method. Drivers may set up @xstart_frac if desired.
|
* method. Drivers may set up @xstart_frac if desired.
|
||||||
*
|
*
|
||||||
|
* Note that these values relate to the rotated console, so that an 80x25
|
||||||
|
* console which is rotated 90 degrees will have rows=80 and cols=25
|
||||||
|
*
|
||||||
|
* The xcur_frac and ycur values refer to the unrotated coordinates, that is
|
||||||
|
* xcur_frac always advances with each character, even if its limit might be
|
||||||
|
* vid_priv->ysize instead of vid_priv->xsize if the console is rotated 90 or
|
||||||
|
* 270 degrees.
|
||||||
|
*
|
||||||
* @sdev: stdio device, acting as an output sink
|
* @sdev: stdio device, acting as an output sink
|
||||||
* @xcur_frac: Current X position, in fractional units (VID_TO_POS(x))
|
* @xcur_frac: Current X position, in fractional units (VID_TO_POS(x))
|
||||||
* @ycur: Current Y position in pixels (0=top)
|
* @ycur: Current Y position in pixels (0=top)
|
||||||
|
|
|
@ -31,9 +31,11 @@ static int cedit_base(struct unit_test_state *uts)
|
||||||
* ^N Move down to second item
|
* ^N Move down to second item
|
||||||
* ^M Select item
|
* ^M Select item
|
||||||
* \e Quit
|
* \e Quit
|
||||||
|
*
|
||||||
|
* cedit_run() returns -EACCESS so this command returns CMD_RET_FAILURE
|
||||||
*/
|
*/
|
||||||
console_in_puts("\x0e\x0d\x0e\x0d\e");
|
console_in_puts("\x0e\x0d\x0e\x0d\e");
|
||||||
ut_assertok(run_command("cedit run", 0));
|
ut_asserteq(1, run_command("cedit run", 0));
|
||||||
|
|
||||||
exp = cur_exp;
|
exp = cur_exp;
|
||||||
scn = expo_lookup_scene_id(exp, exp->scene_id);
|
scn = expo_lookup_scene_id(exp, exp->scene_id);
|
||||||
|
@ -94,14 +96,16 @@ static int cedit_fdt(struct unit_test_state *uts)
|
||||||
|
|
||||||
ut_asserteq(ID_CPU_SPEED_2,
|
ut_asserteq(ID_CPU_SPEED_2,
|
||||||
ofnode_read_u32_default(node, "cpu-speed", 0));
|
ofnode_read_u32_default(node, "cpu-speed", 0));
|
||||||
|
ut_asserteq(3,
|
||||||
|
ofnode_read_u32_default(node, "cpu-speed-value", 0));
|
||||||
ut_asserteq_str("2.5 GHz", ofnode_read_string(node, "cpu-speed-str"));
|
ut_asserteq_str("2.5 GHz", ofnode_read_string(node, "cpu-speed-str"));
|
||||||
ut_asserteq_str("my-machine", ofnode_read_string(node, "machine-name"));
|
ut_asserteq_str("my-machine", ofnode_read_string(node, "machine-name"));
|
||||||
|
|
||||||
/* There should only be 5 properties */
|
/* There should only be 7 properties */
|
||||||
for (i = 0, ofnode_first_property(node, &prop); ofprop_valid(&prop);
|
for (i = 0, ofnode_first_property(node, &prop); ofprop_valid(&prop);
|
||||||
i++, ofnode_next_property(&prop))
|
i++, ofnode_next_property(&prop))
|
||||||
;
|
;
|
||||||
ut_asserteq(5, i);
|
ut_asserteq(7, i);
|
||||||
|
|
||||||
ut_assert_console_end();
|
ut_assert_console_end();
|
||||||
|
|
||||||
|
@ -147,14 +151,16 @@ static int cedit_env(struct unit_test_state *uts)
|
||||||
strcpy(str, "my-machine");
|
strcpy(str, "my-machine");
|
||||||
|
|
||||||
ut_assertok(run_command("cedit write_env -v", 0));
|
ut_assertok(run_command("cedit write_env -v", 0));
|
||||||
ut_assert_nextlinen("c.cpu-speed=7");
|
ut_assert_nextlinen("c.cpu-speed=11");
|
||||||
ut_assert_nextlinen("c.cpu-speed-str=2.5 GHz");
|
ut_assert_nextlinen("c.cpu-speed-str=2.5 GHz");
|
||||||
ut_assert_nextlinen("c.power-loss=10");
|
ut_assert_nextlinen("c.cpu-speed-value=3");
|
||||||
|
ut_assert_nextlinen("c.power-loss=14");
|
||||||
ut_assert_nextlinen("c.power-loss-str=Always Off");
|
ut_assert_nextlinen("c.power-loss-str=Always Off");
|
||||||
|
ut_assert_nextlinen("c.power-loss-value=0");
|
||||||
ut_assert_nextlinen("c.machine-name=my-machine");
|
ut_assert_nextlinen("c.machine-name=my-machine");
|
||||||
ut_assert_console_end();
|
ut_assert_console_end();
|
||||||
|
|
||||||
ut_asserteq(7, env_get_ulong("c.cpu-speed", 10, 0));
|
ut_asserteq(11, env_get_ulong("c.cpu-speed", 10, 0));
|
||||||
ut_asserteq_str("2.5 GHz", env_get("c.cpu-speed-str"));
|
ut_asserteq_str("2.5 GHz", env_get("c.cpu-speed-str"));
|
||||||
ut_asserteq_str("my-machine", env_get("c.machine-name"));
|
ut_asserteq_str("my-machine", env_get("c.machine-name"));
|
||||||
|
|
||||||
|
@ -163,8 +169,8 @@ static int cedit_env(struct unit_test_state *uts)
|
||||||
*str = '\0';
|
*str = '\0';
|
||||||
|
|
||||||
ut_assertok(run_command("cedit read_env -v", 0));
|
ut_assertok(run_command("cedit read_env -v", 0));
|
||||||
ut_assert_nextlinen("c.cpu-speed=7");
|
ut_assert_nextlinen("c.cpu-speed=11");
|
||||||
ut_assert_nextlinen("c.power-loss=10");
|
ut_assert_nextlinen("c.power-loss=14");
|
||||||
ut_assert_nextlinen("c.machine-name=my-machine");
|
ut_assert_nextlinen("c.machine-name=my-machine");
|
||||||
ut_assert_console_end();
|
ut_assert_console_end();
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ static int expo_base(struct unit_test_state *uts)
|
||||||
*name = '\0';
|
*name = '\0';
|
||||||
ut_assertnonnull(exp);
|
ut_assertnonnull(exp);
|
||||||
ut_asserteq(0, exp->scene_id);
|
ut_asserteq(0, exp->scene_id);
|
||||||
ut_asserteq(0, exp->next_id);
|
ut_asserteq(EXPOID_BASE_ID, exp->next_id);
|
||||||
|
|
||||||
/* Make sure the name was allocated */
|
/* Make sure the name was allocated */
|
||||||
ut_assertnonnull(exp->name);
|
ut_assertnonnull(exp->name);
|
||||||
|
@ -130,7 +130,7 @@ static int expo_scene(struct unit_test_state *uts)
|
||||||
ut_assertok(expo_new(EXPO_NAME, NULL, &exp));
|
ut_assertok(expo_new(EXPO_NAME, NULL, &exp));
|
||||||
|
|
||||||
scn = NULL;
|
scn = NULL;
|
||||||
ut_asserteq(0, exp->next_id);
|
ut_asserteq(EXPOID_BASE_ID, exp->next_id);
|
||||||
strcpy(name, SCENE_NAME1);
|
strcpy(name, SCENE_NAME1);
|
||||||
id = scene_new(exp, name, SCENE1, &scn);
|
id = scene_new(exp, name, SCENE1, &scn);
|
||||||
*name = '\0';
|
*name = '\0';
|
||||||
|
@ -151,7 +151,7 @@ static int expo_scene(struct unit_test_state *uts)
|
||||||
scn = NULL;
|
scn = NULL;
|
||||||
id = scene_new(exp, SCENE_NAME2, 0, &scn);
|
id = scene_new(exp, SCENE_NAME2, 0, &scn);
|
||||||
ut_assertnonnull(scn);
|
ut_assertnonnull(scn);
|
||||||
ut_assertok(scene_title_set(scn, title_id));
|
scn->title_id = title_id;
|
||||||
ut_asserteq(STR_SCENE_TITLE + 1, id);
|
ut_asserteq(STR_SCENE_TITLE + 1, id);
|
||||||
ut_asserteq(STR_SCENE_TITLE + 2, exp->next_id);
|
ut_asserteq(STR_SCENE_TITLE + 2, exp->next_id);
|
||||||
ut_asserteq_ptr(exp, scn->expo);
|
ut_asserteq_ptr(exp, scn->expo);
|
||||||
|
@ -167,6 +167,25 @@ static int expo_scene(struct unit_test_state *uts)
|
||||||
}
|
}
|
||||||
BOOTSTD_TEST(expo_scene, UTF_DM | UTF_SCAN_FDT);
|
BOOTSTD_TEST(expo_scene, UTF_DM | UTF_SCAN_FDT);
|
||||||
|
|
||||||
|
/* Check creating a scene with no ID */
|
||||||
|
static int expo_scene_no_id(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct scene *scn;
|
||||||
|
struct expo *exp;
|
||||||
|
char name[100];
|
||||||
|
int id;
|
||||||
|
|
||||||
|
ut_assertok(expo_new(EXPO_NAME, NULL, &exp));
|
||||||
|
ut_asserteq(EXPOID_BASE_ID, exp->next_id);
|
||||||
|
|
||||||
|
strcpy(name, SCENE_NAME1);
|
||||||
|
id = scene_new(exp, SCENE_NAME1, 0, &scn);
|
||||||
|
ut_asserteq(EXPOID_BASE_ID, scn->id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
BOOTSTD_TEST(expo_scene_no_id, UTF_DM | UTF_SCAN_FDT);
|
||||||
|
|
||||||
/* Check creating a scene with objects */
|
/* Check creating a scene with objects */
|
||||||
static int expo_object(struct unit_test_state *uts)
|
static int expo_object(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
|
@ -698,6 +717,7 @@ static int expo_test_build(struct unit_test_state *uts)
|
||||||
ut_asserteq(0, item->desc_id);
|
ut_asserteq(0, item->desc_id);
|
||||||
ut_asserteq(0, item->preview_id);
|
ut_asserteq(0, item->preview_id);
|
||||||
ut_asserteq(0, item->flags);
|
ut_asserteq(0, item->flags);
|
||||||
|
ut_asserteq(0, item->value);
|
||||||
|
|
||||||
txt = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE);
|
txt = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE);
|
||||||
ut_asserteq_str("2 GHz", expo_get_str(exp, txt->str_id));
|
ut_asserteq_str("2 GHz", expo_get_str(exp, txt->str_id));
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ZERO,
|
ID_PROMPT = EXPOID_BASE_ID,
|
||||||
ID_PROMPT,
|
|
||||||
|
|
||||||
ID_SCENE1,
|
ID_SCENE1,
|
||||||
ID_SCENE1_TITLE,
|
ID_SCENE1_TITLE,
|
||||||
|
|
|
@ -39,8 +39,11 @@
|
||||||
item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2
|
item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2
|
||||||
ID_CPU_SPEED_3>;
|
ID_CPU_SPEED_3>;
|
||||||
|
|
||||||
|
/* values for the menu items */
|
||||||
|
item-value = <0 3 6>;
|
||||||
|
|
||||||
start-bit = <0x400>;
|
start-bit = <0x400>;
|
||||||
bit-length = <2>;
|
bit-length = <3>;
|
||||||
};
|
};
|
||||||
|
|
||||||
power-loss {
|
power-loss {
|
||||||
|
|
|
@ -12,6 +12,7 @@ ifdef CONFIG_CONSOLE_RECORD
|
||||||
obj-$(CONFIG_CMD_PAUSE) += test_pause.o
|
obj-$(CONFIG_CMD_PAUSE) += test_pause.o
|
||||||
endif
|
endif
|
||||||
obj-y += exit.o mem.o
|
obj-y += exit.o mem.o
|
||||||
|
obj-$(CONFIG_X86) += cpuid.o msr.o
|
||||||
obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
|
obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
|
||||||
obj-$(CONFIG_CMD_BDI) += bdinfo.o
|
obj-$(CONFIG_CMD_BDI) += bdinfo.o
|
||||||
obj-$(CONFIG_CMD_FDT) += fdt.o
|
obj-$(CONFIG_CMD_FDT) += fdt.o
|
||||||
|
|
22
test/cmd/cpuid.c
Normal file
22
test/cmd/cpuid.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Tests for cpuid command
|
||||||
|
*
|
||||||
|
* Copyright 2024 Google LLC
|
||||||
|
* Written by Simon Glass <sjg@chromium.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <test/cmd.h>
|
||||||
|
#include <test/ut.h>
|
||||||
|
|
||||||
|
static int cmd_test_cpuid(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
ut_assertok(run_commandf("cpuid 1"));
|
||||||
|
ut_assert_nextline("eax 00060fb1");
|
||||||
|
ut_assert_nextline("ebx 00000800");
|
||||||
|
ut_assert_nextline("ecx 80002001");
|
||||||
|
ut_assert_nextline("edx 078bfbfd");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
CMD_TEST(cmd_test_cpuid, UTF_CONSOLE);
|
|
@ -27,14 +27,20 @@ static int font_test_base(struct unit_test_state *uts)
|
||||||
ut_assertok(uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev));
|
ut_assertok(uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev));
|
||||||
|
|
||||||
ut_assertok(run_command("font list", 0));
|
ut_assertok(run_command("font list", 0));
|
||||||
|
if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_NIMBUS))
|
||||||
ut_assert_nextline("nimbus_sans_l_regular");
|
ut_assert_nextline("nimbus_sans_l_regular");
|
||||||
|
if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_ANKACODER))
|
||||||
|
ut_assert_nextline("ankacoder_c75_r");
|
||||||
if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_CANTORAONE))
|
if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_CANTORAONE))
|
||||||
ut_assert_nextline("cantoraone_regular");
|
ut_assert_nextline("cantoraone_regular");
|
||||||
ut_assert_console_end();
|
ut_assert_console_end();
|
||||||
|
|
||||||
ut_assertok(vidconsole_get_font_size(dev, &name, &size));
|
ut_assertok(vidconsole_get_font_size(dev, &name, &size));
|
||||||
|
if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_ANKACODER))
|
||||||
|
ut_asserteq_str("ankacoder_c75_r", name);
|
||||||
|
else
|
||||||
ut_asserteq_str("nimbus_sans_l_regular", name);
|
ut_asserteq_str("nimbus_sans_l_regular", name);
|
||||||
ut_asserteq(18, size);
|
ut_asserteq(CONFIG_CONSOLE_TRUETYPE_SIZE, size);
|
||||||
|
|
||||||
if (!IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_CANTORAONE))
|
if (!IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_CANTORAONE))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -58,10 +64,19 @@ static int font_test_base(struct unit_test_state *uts)
|
||||||
ut_assertok(vidconsole_get_font_size(dev, &name, &size));
|
ut_assertok(vidconsole_get_font_size(dev, &name, &size));
|
||||||
ut_asserteq_str("cantoraone_regular", name);
|
ut_asserteq_str("cantoraone_regular", name);
|
||||||
ut_asserteq(40, size);
|
ut_asserteq(40, size);
|
||||||
|
ut_assertok(ut_check_console_end(uts));
|
||||||
|
|
||||||
|
ut_assertok(run_command("font size", 0));
|
||||||
|
ut_assert_nextline("40");
|
||||||
|
ut_assertok(ut_check_console_end(uts));
|
||||||
|
|
||||||
ut_assertok(run_command("font size 30", 0));
|
ut_assertok(run_command("font size 30", 0));
|
||||||
ut_assert_console_end();
|
ut_assert_console_end();
|
||||||
|
|
||||||
|
ut_assertok(run_command("font size", 0));
|
||||||
|
ut_assert_nextline("30");
|
||||||
|
ut_assertok(ut_check_console_end(uts));
|
||||||
|
|
||||||
ut_assertok(vidconsole_get_font_size(dev, &name, &size));
|
ut_assertok(vidconsole_get_font_size(dev, &name, &size));
|
||||||
ut_asserteq_str("cantoraone_regular", name);
|
ut_asserteq_str("cantoraone_regular", name);
|
||||||
ut_asserteq(30, size);
|
ut_asserteq(30, size);
|
||||||
|
|
38
test/cmd/msr.c
Normal file
38
test/cmd/msr.c
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Tests for msr command
|
||||||
|
*
|
||||||
|
* Copyright 2024 Google LLC
|
||||||
|
* Written by Simon Glass <sjg@chromium.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <test/cmd.h>
|
||||||
|
#include <test/ut.h>
|
||||||
|
|
||||||
|
static int cmd_test_msr(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
ut_assertok(run_commandf("msr read 200"));
|
||||||
|
ut_assert_nextline("00000000 ffe00006");
|
||||||
|
ut_assert_console_end();
|
||||||
|
|
||||||
|
/* change the first variable msr and see it reflected in the mtrr cmd */
|
||||||
|
ut_assertok(run_commandf("mtrr"));
|
||||||
|
ut_assert_nextline("CPU 65537:");
|
||||||
|
ut_assert_nextlinen("Reg");
|
||||||
|
ut_assert_nextlinen("0 Y Back 00000000ffe00000");
|
||||||
|
ut_assertok(console_record_reset_enable());
|
||||||
|
|
||||||
|
/* change the type from 6 to 5 */
|
||||||
|
ut_assertok(run_commandf("msr write 200 0 ffe00005"));
|
||||||
|
ut_assert_console_end();
|
||||||
|
|
||||||
|
/* Now it shows 'Protect' */
|
||||||
|
ut_assertok(run_commandf("mtrr"));
|
||||||
|
ut_assert_nextline("CPU 65537:");
|
||||||
|
ut_assert_nextlinen("Reg");
|
||||||
|
ut_assert_nextlinen("0 Y Protect 00000000ffe00000");
|
||||||
|
ut_assertok(console_record_reset_enable());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
CMD_TEST(cmd_test_msr, UTF_CONSOLE);
|
|
@ -2099,12 +2099,15 @@ Code coverage
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Binman is a critical tool and is designed to be very testable. Entry
|
Binman is a critical tool and is designed to be very testable. Entry
|
||||||
implementations target 100% test coverage. Run 'binman test -T' to check this.
|
implementations target 100% test coverage. Run ``binman test -T`` to check this.
|
||||||
|
|
||||||
To enable Python test coverage on Debian-type distributions (e.g. Ubuntu)::
|
To enable Python test coverage on Debian-type distributions (e.g. Ubuntu)::
|
||||||
|
|
||||||
$ sudo apt-get install python-coverage python3-coverage python-pytest
|
$ sudo apt-get install python-coverage python3-coverage python-pytest
|
||||||
|
|
||||||
|
You can also check the coverage provided by a single test, e.g.::
|
||||||
|
|
||||||
|
binman test -T testSimple
|
||||||
|
|
||||||
Exit status
|
Exit status
|
||||||
-----------
|
-----------
|
||||||
|
@ -2191,6 +2194,11 @@ Use '-P 1' to disable this. It is automatically disabled when code coverage is
|
||||||
being used (-T) since they are incompatible.
|
being used (-T) since they are incompatible.
|
||||||
|
|
||||||
|
|
||||||
|
Writing tests
|
||||||
|
-------------
|
||||||
|
|
||||||
|
See :doc:`../binman_tests`.
|
||||||
|
|
||||||
Debugging tests
|
Debugging tests
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ class Bintoolmkimage(bintool.Bintool):
|
||||||
|
|
||||||
# pylint: disable=R0913
|
# pylint: disable=R0913
|
||||||
def run(self, reset_timestamp=False, output_fname=None, external=False,
|
def run(self, reset_timestamp=False, output_fname=None, external=False,
|
||||||
pad=None, align=None):
|
pad=None, align=None, priv_keys_dir=None):
|
||||||
"""Run mkimage
|
"""Run mkimage
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -34,6 +34,7 @@ class Bintoolmkimage(bintool.Bintool):
|
||||||
other things to be easily added later, if required, such as
|
other things to be easily added later, if required, such as
|
||||||
signatures
|
signatures
|
||||||
align: Bytes to use for alignment of the FIT and its external data
|
align: Bytes to use for alignment of the FIT and its external data
|
||||||
|
priv_keys_dir: Path to directory containing private keys
|
||||||
version: True to get the mkimage version
|
version: True to get the mkimage version
|
||||||
"""
|
"""
|
||||||
args = []
|
args = []
|
||||||
|
@ -45,6 +46,8 @@ class Bintoolmkimage(bintool.Bintool):
|
||||||
args += ['-B', f'{align:x}']
|
args += ['-B', f'{align:x}']
|
||||||
if reset_timestamp:
|
if reset_timestamp:
|
||||||
args.append('-t')
|
args.append('-t')
|
||||||
|
if priv_keys_dir:
|
||||||
|
args += ['-k', f'{priv_keys_dir}']
|
||||||
if output_fname:
|
if output_fname:
|
||||||
args += ['-F', output_fname]
|
args += ['-F', output_fname]
|
||||||
return self.run_cmd(*args)
|
return self.run_cmd(*args)
|
||||||
|
|
|
@ -864,6 +864,13 @@ The top-level 'fit' node supports the following special properties:
|
||||||
|
|
||||||
fit,fdt-list-dir = "arch/arm/dts
|
fit,fdt-list-dir = "arch/arm/dts
|
||||||
|
|
||||||
|
fit,sign
|
||||||
|
Enable signing FIT images via mkimage as described in
|
||||||
|
verified-boot.rst. If the property is found, the private keys path is
|
||||||
|
detected among binman include directories and passed to mkimage via
|
||||||
|
-k flag. All the keys required for signing FIT must be available at
|
||||||
|
time of signing and must be located in single include directory.
|
||||||
|
|
||||||
Substitutions
|
Substitutions
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import glob
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import libfdt
|
import libfdt
|
||||||
|
import os
|
||||||
|
|
||||||
from binman.entry import Entry, EntryArg
|
from binman.entry import Entry, EntryArg
|
||||||
from binman.etype.section import Entry_section
|
from binman.etype.section import Entry_section
|
||||||
|
@ -101,6 +102,14 @@ class Entry_fit(Entry_section):
|
||||||
In this case the input directories are ignored and all devicetree
|
In this case the input directories are ignored and all devicetree
|
||||||
files must be in that directory.
|
files must be in that directory.
|
||||||
|
|
||||||
|
fit,sign
|
||||||
|
Enable signing FIT images via mkimage as described in
|
||||||
|
verified-boot.rst. If the property is found, the private keys path
|
||||||
|
is detected among binman include directories and passed to mkimage
|
||||||
|
via -k flag. All the keys required for signing FIT must be
|
||||||
|
available at time of signing and must be located in single include
|
||||||
|
directory.
|
||||||
|
|
||||||
Substitutions
|
Substitutions
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -426,6 +435,7 @@ class Entry_fit(Entry_section):
|
||||||
self._remove_props = props.split()
|
self._remove_props = props.split()
|
||||||
self.mkimage = None
|
self.mkimage = None
|
||||||
self.fdtgrep = None
|
self.fdtgrep = None
|
||||||
|
self._fit_sign = None
|
||||||
|
|
||||||
def ReadNode(self):
|
def ReadNode(self):
|
||||||
super().ReadNode()
|
super().ReadNode()
|
||||||
|
@ -508,6 +518,45 @@ class Entry_fit(Entry_section):
|
||||||
# are removed from self._entries later.
|
# are removed from self._entries later.
|
||||||
self._priv_entries = dict(self._entries)
|
self._priv_entries = dict(self._entries)
|
||||||
|
|
||||||
|
def _get_priv_keys_dir(self, data):
|
||||||
|
"""Detect private keys path among binman include directories
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data: FIT image in binary format
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Single path containing all private keys found or None
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: Filename 'rsa2048.key' not found in input path
|
||||||
|
ValueError: Multiple key paths found
|
||||||
|
"""
|
||||||
|
def _find_keys_dir(node):
|
||||||
|
for subnode in node.subnodes:
|
||||||
|
if subnode.name.startswith('signature'):
|
||||||
|
if subnode.props.get('key-name-hint') is None:
|
||||||
|
continue
|
||||||
|
hint = subnode.props['key-name-hint'].value
|
||||||
|
name = tools.get_input_filename(f"{hint}.key")
|
||||||
|
path = os.path.dirname(name)
|
||||||
|
if path not in paths:
|
||||||
|
paths.append(path)
|
||||||
|
else:
|
||||||
|
_find_keys_dir(subnode)
|
||||||
|
return None
|
||||||
|
|
||||||
|
fdt = Fdt.FromData(data)
|
||||||
|
fdt.Scan()
|
||||||
|
|
||||||
|
paths = []
|
||||||
|
|
||||||
|
_find_keys_dir(fdt.GetRoot())
|
||||||
|
|
||||||
|
if len(paths) > 1:
|
||||||
|
self.Raise("multiple key paths found (%s)" % ",".join(paths))
|
||||||
|
|
||||||
|
return paths[0] if len(paths) else None
|
||||||
|
|
||||||
def BuildSectionData(self, required):
|
def BuildSectionData(self, required):
|
||||||
"""Build FIT entry contents
|
"""Build FIT entry contents
|
||||||
|
|
||||||
|
@ -538,6 +587,8 @@ class Entry_fit(Entry_section):
|
||||||
align = self._fit_props.get('fit,align')
|
align = self._fit_props.get('fit,align')
|
||||||
if align is not None:
|
if align is not None:
|
||||||
args.update({'align': fdt_util.fdt32_to_cpu(align.value)})
|
args.update({'align': fdt_util.fdt32_to_cpu(align.value)})
|
||||||
|
if self._fit_props.get('fit,sign') is not None:
|
||||||
|
args.update({'priv_keys_dir': self._get_priv_keys_dir(data)})
|
||||||
if self.mkimage.run(reset_timestamp=True, output_fname=output_fname,
|
if self.mkimage.run(reset_timestamp=True, output_fname=output_fname,
|
||||||
**args) is None:
|
**args) is None:
|
||||||
if not self.GetAllowMissing():
|
if not self.GetAllowMissing():
|
||||||
|
@ -637,8 +688,8 @@ class Entry_fit(Entry_section):
|
||||||
"""
|
"""
|
||||||
val = fdt_util.GetStringList(node, 'fit,firmware')
|
val = fdt_util.GetStringList(node, 'fit,firmware')
|
||||||
if val is None:
|
if val is None:
|
||||||
return None, self._loadables
|
return None, loadables
|
||||||
valid_entries = list(self._loadables)
|
valid_entries = list(loadables)
|
||||||
for name, entry in self.GetEntries().items():
|
for name, entry in self.GetEntries().items():
|
||||||
missing = []
|
missing = []
|
||||||
entry.CheckMissing(missing)
|
entry.CheckMissing(missing)
|
||||||
|
@ -653,7 +704,7 @@ class Entry_fit(Entry_section):
|
||||||
firmware = name
|
firmware = name
|
||||||
elif name not in result:
|
elif name not in result:
|
||||||
result.append(name)
|
result.append(name)
|
||||||
for name in self._loadables:
|
for name in loadables:
|
||||||
if name != firmware and name not in result:
|
if name != firmware and name not in result:
|
||||||
result.append(name)
|
result.append(name)
|
||||||
return firmware, result
|
return firmware, result
|
||||||
|
|
|
@ -7804,6 +7804,101 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
|
||||||
"""Test that binman can produce an iMX8 image"""
|
"""Test that binman can produce an iMX8 image"""
|
||||||
self._DoTestFile('339_nxp_imx8.dts')
|
self._DoTestFile('339_nxp_imx8.dts')
|
||||||
|
|
||||||
|
def testFitSignSimple(self):
|
||||||
|
"""Test that image with FIT and signature nodes can be signed"""
|
||||||
|
if not elf.ELF_TOOLS:
|
||||||
|
self.skipTest('Python elftools not available')
|
||||||
|
entry_args = {
|
||||||
|
'of-list': 'test-fdt1',
|
||||||
|
'default-dt': 'test-fdt1',
|
||||||
|
'atf-bl31-path': 'bl31.elf',
|
||||||
|
}
|
||||||
|
data = tools.read_file(self.TestFile("340_rsa2048.key"))
|
||||||
|
self._MakeInputFile("keys/rsa2048.key", data)
|
||||||
|
|
||||||
|
test_subdir = os.path.join(self._indir, TEST_FDT_SUBDIR)
|
||||||
|
keys_subdir = os.path.join(self._indir, "keys")
|
||||||
|
data = self._DoReadFileDtb(
|
||||||
|
'340_fit_signature.dts',
|
||||||
|
entry_args=entry_args,
|
||||||
|
extra_indirs=[test_subdir, keys_subdir])[0]
|
||||||
|
|
||||||
|
dtb = fdt.Fdt.FromData(data)
|
||||||
|
dtb.Scan()
|
||||||
|
|
||||||
|
conf = dtb.GetNode('/configurations/conf-uboot-1')
|
||||||
|
self.assertIsNotNone(conf)
|
||||||
|
signature = conf.FindNode('signature')
|
||||||
|
self.assertIsNotNone(signature)
|
||||||
|
self.assertIsNotNone(signature.props.get('value'))
|
||||||
|
|
||||||
|
images = dtb.GetNode('/images')
|
||||||
|
self.assertIsNotNone(images)
|
||||||
|
for subnode in images.subnodes:
|
||||||
|
signature = subnode.FindNode('signature')
|
||||||
|
self.assertIsNotNone(signature)
|
||||||
|
self.assertIsNotNone(signature.props.get('value'))
|
||||||
|
|
||||||
|
def testFitSignKeyNotFound(self):
|
||||||
|
"""Test that missing keys raise an error"""
|
||||||
|
if not elf.ELF_TOOLS:
|
||||||
|
self.skipTest('Python elftools not available')
|
||||||
|
entry_args = {
|
||||||
|
'of-list': 'test-fdt1',
|
||||||
|
'default-dt': 'test-fdt1',
|
||||||
|
'atf-bl31-path': 'bl31.elf',
|
||||||
|
}
|
||||||
|
test_subdir = os.path.join(self._indir, TEST_FDT_SUBDIR)
|
||||||
|
with self.assertRaises(ValueError) as e:
|
||||||
|
self._DoReadFileDtb(
|
||||||
|
'340_fit_signature.dts',
|
||||||
|
entry_args=entry_args,
|
||||||
|
extra_indirs=[test_subdir])[0]
|
||||||
|
self.assertIn(
|
||||||
|
'Filename \'rsa2048.key\' not found in input path',
|
||||||
|
str(e.exception))
|
||||||
|
|
||||||
|
def testFitSignMultipleKeyPaths(self):
|
||||||
|
"""Test that keys found in multiple paths raise an error"""
|
||||||
|
if not elf.ELF_TOOLS:
|
||||||
|
self.skipTest('Python elftools not available')
|
||||||
|
entry_args = {
|
||||||
|
'of-list': 'test-fdt1',
|
||||||
|
'default-dt': 'test-fdt1',
|
||||||
|
'atf-bl31-path': 'bl31.elf',
|
||||||
|
}
|
||||||
|
data = tools.read_file(self.TestFile("340_rsa2048.key"))
|
||||||
|
self._MakeInputFile("keys1/rsa2048.key", data)
|
||||||
|
data = tools.read_file(self.TestFile("340_rsa2048.key"))
|
||||||
|
self._MakeInputFile("keys2/conf-rsa2048.key", data)
|
||||||
|
|
||||||
|
test_subdir = os.path.join(self._indir, TEST_FDT_SUBDIR)
|
||||||
|
keys_subdir1 = os.path.join(self._indir, "keys1")
|
||||||
|
keys_subdir2 = os.path.join(self._indir, "keys2")
|
||||||
|
with self.assertRaises(ValueError) as e:
|
||||||
|
self._DoReadFileDtb(
|
||||||
|
'341_fit_signature.dts',
|
||||||
|
entry_args=entry_args,
|
||||||
|
extra_indirs=[test_subdir, keys_subdir1, keys_subdir2])[0]
|
||||||
|
self.assertIn(
|
||||||
|
'Node \'/binman/fit\': multiple key paths found',
|
||||||
|
str(e.exception))
|
||||||
|
|
||||||
|
def testFitSignNoSingatureNodes(self):
|
||||||
|
"""Test that fit,sign doens't raise error if no signature nodes found"""
|
||||||
|
if not elf.ELF_TOOLS:
|
||||||
|
self.skipTest('Python elftools not available')
|
||||||
|
entry_args = {
|
||||||
|
'of-list': 'test-fdt1',
|
||||||
|
'default-dt': 'test-fdt1',
|
||||||
|
'atf-bl31-path': 'bl31.elf',
|
||||||
|
}
|
||||||
|
test_subdir = os.path.join(self._indir, TEST_FDT_SUBDIR)
|
||||||
|
self._DoReadFileDtb(
|
||||||
|
'342_fit_signature.dts',
|
||||||
|
entry_args=entry_args,
|
||||||
|
extra_indirs=[test_subdir])[0]
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -85,7 +85,7 @@ def RunTests(debug, verbosity, processes, test_preserve_dirs, args, toolpath):
|
||||||
|
|
||||||
return (0 if result.wasSuccessful() else 1)
|
return (0 if result.wasSuccessful() else 1)
|
||||||
|
|
||||||
def RunTestCoverage(toolpath, build_dir):
|
def RunTestCoverage(toolpath, build_dir, args):
|
||||||
"""Run the tests and check that we get 100% coverage"""
|
"""Run the tests and check that we get 100% coverage"""
|
||||||
glob_list = control.GetEntryModules(False)
|
glob_list = control.GetEntryModules(False)
|
||||||
all_set = set([os.path.splitext(os.path.basename(item))[0]
|
all_set = set([os.path.splitext(os.path.basename(item))[0]
|
||||||
|
@ -97,7 +97,7 @@ def RunTestCoverage(toolpath, build_dir):
|
||||||
test_util.run_test_coverage('tools/binman/binman', None,
|
test_util.run_test_coverage('tools/binman/binman', None,
|
||||||
['*test*', '*main.py', 'tools/patman/*', 'tools/dtoc/*',
|
['*test*', '*main.py', 'tools/patman/*', 'tools/dtoc/*',
|
||||||
'tools/u_boot_pylib/*'],
|
'tools/u_boot_pylib/*'],
|
||||||
build_dir, all_set, extra_args or None)
|
build_dir, all_set, extra_args or None, args=args)
|
||||||
|
|
||||||
def RunBinman(args):
|
def RunBinman(args):
|
||||||
"""Main entry point to binman once arguments are parsed
|
"""Main entry point to binman once arguments are parsed
|
||||||
|
@ -117,7 +117,7 @@ def RunBinman(args):
|
||||||
|
|
||||||
if args.cmd == 'test':
|
if args.cmd == 'test':
|
||||||
if args.test_coverage:
|
if args.test_coverage:
|
||||||
RunTestCoverage(args.toolpath, args.build_dir)
|
RunTestCoverage(args.toolpath, args.build_dir, args.tests)
|
||||||
else:
|
else:
|
||||||
ret_code = RunTests(args.debug, args.verbosity, args.processes,
|
ret_code = RunTests(args.debug, args.verbosity, args.processes,
|
||||||
args.test_preserve_dirs, args.tests,
|
args.test_preserve_dirs, args.tests,
|
||||||
|
|
98
tools/binman/test/340_fit_signature.dts
Normal file
98
tools/binman/test/340_fit_signature.dts
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
fit {
|
||||||
|
description = "test desc";
|
||||||
|
#address-cells = <1>;
|
||||||
|
fit,fdt-list = "of-list";
|
||||||
|
fit,sign;
|
||||||
|
|
||||||
|
images {
|
||||||
|
u-boot {
|
||||||
|
description = "test u-boot";
|
||||||
|
type = "standalone";
|
||||||
|
arch = "arm64";
|
||||||
|
os = "u-boot";
|
||||||
|
compression = "none";
|
||||||
|
load = <0x00000000>;
|
||||||
|
entry = <0x00000000>;
|
||||||
|
|
||||||
|
u-boot-nodtb {
|
||||||
|
};
|
||||||
|
|
||||||
|
hash {
|
||||||
|
algo = "sha256";
|
||||||
|
};
|
||||||
|
|
||||||
|
signature {
|
||||||
|
algo = "sha256,rsa2048";
|
||||||
|
key-name-hint = "rsa2048";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@atf-SEQ {
|
||||||
|
fit,operation = "split-elf";
|
||||||
|
description = "test tf-a";
|
||||||
|
type = "firmware";
|
||||||
|
arch = "arm64";
|
||||||
|
os = "arm-trusted-firmware";
|
||||||
|
compression = "none";
|
||||||
|
fit,load;
|
||||||
|
fit,entry;
|
||||||
|
fit,data;
|
||||||
|
|
||||||
|
atf-bl31 {
|
||||||
|
};
|
||||||
|
|
||||||
|
hash {
|
||||||
|
algo = "sha256";
|
||||||
|
};
|
||||||
|
|
||||||
|
signature {
|
||||||
|
algo = "sha256,rsa2048";
|
||||||
|
key-name-hint = "rsa2048";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@fdt-SEQ {
|
||||||
|
description = "test fdt";
|
||||||
|
type = "flat_dt";
|
||||||
|
compression = "none";
|
||||||
|
|
||||||
|
hash {
|
||||||
|
algo = "sha256";
|
||||||
|
};
|
||||||
|
|
||||||
|
signature {
|
||||||
|
algo = "sha256,rsa2048";
|
||||||
|
key-name-hint = "rsa2048";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
default = "@conf-uboot-DEFAULT-SEQ";
|
||||||
|
@conf-uboot-SEQ {
|
||||||
|
description = "uboot config";
|
||||||
|
fdt = "fdt-SEQ";
|
||||||
|
fit,firmware = "u-boot";
|
||||||
|
fit,loadables;
|
||||||
|
|
||||||
|
hash {
|
||||||
|
algo = "sha256";
|
||||||
|
};
|
||||||
|
|
||||||
|
signature {
|
||||||
|
algo = "sha256,rsa2048";
|
||||||
|
key-name-hint = "rsa2048";
|
||||||
|
sign-images = "firmware", "loadables", "fdt";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
28
tools/binman/test/340_rsa2048.key
Normal file
28
tools/binman/test/340_rsa2048.key
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDVUiT2JAF8Ajcx
|
||||||
|
3XTB5qdGxuPMVFcXKJH+4L66oSt4YUBGi1bClo80U2azu08BTzk2Jzv6hez/mvzL
|
||||||
|
hBvL3WnPwMl5vdOxb1kvUQyKLSw2bkM8VB0X1jGsKsKjzArg/aI8RknfiaSc5jua
|
||||||
|
2lqwUFwv2RMF8jvIMN/1GnTLdECeMFVgVFSFkzIocISAHGPoGUOxTf8xK7o0x4RX
|
||||||
|
NzB+95RtIqTQ5Az/KPVCOcQR5ETrUBXHF1I0rYjJjHHO4dUxxfDqFabt60EzQ/R2
|
||||||
|
oZu58C4y0TrRI98g4hVPBYapildWjaNQm1Exa4ZaSDVl01OXsFW9Dm80PqfW4tTH
|
||||||
|
Cm4nuCq5AgMBAAECggEBAIoG5b2SHJfFwzrzpQmVmeTU6i6a3+MvMBAwEZkmkb8J
|
||||||
|
hhJfNFsiGjTsRgbDiuI5BbbBejCmmWvmN+3jZCzr7fwsLPEl36TufFF+atO5WOM7
|
||||||
|
Qyv07QIwaOGSpXBgpSVhV6kSfdgy8p1G54hSAt4UkSGwnnt5ei8VWMP6Q1oltW3k
|
||||||
|
f9DQ/ar4UEVa4jlJU3xqchcUTiKBKSH6pMC/Fqlq8x5JTLmk1Yb6C2UNcgJYez1u
|
||||||
|
sHkdCA0FG3rFPrpFoQ1LUjMj1uEYNAxM3jOxE7Uvmk4yo9WpQDY7cRb2+Th9YY8a
|
||||||
|
IKQ2s81Yg2TmkGzr8f5nrZz3WbAmQhQgsKbwlo6snjUCgYEA7kBOt0JlU7bJTfOr
|
||||||
|
9s51g2VUfIH9lDS2Eh8MY+Bt6Y0Kdw/UK4HR8ZlN/nn0bHuHkc12K8lXEsQpgIEW
|
||||||
|
DaqHytZJHqFs2egzKu/IvQYZ2WXEMj47LZQxEDHO9gtjE+5qCW9yJGqxW9BJKPVD
|
||||||
|
F4spus4NqC+yD5OHM+6ESUtL/wMCgYEA5TZj6OHmECeh3efrwHqjDcjrqQbOTozU
|
||||||
|
KPCNCY3Pv4Cg4xas/L93TE2CY6HJTr6mwEMUM+M4Ujjj15VCmSDQ/YYcGau1jo+f
|
||||||
|
XdphOEENrPwoe9ATWIyBpT/wDrEz3L6JbE9dWMYY8vKYESt3qhVqDlbpmnYl8Jm+
|
||||||
|
O3r5Cy2NlJMCgYEAyqzsCZuy5QcesnByvm8dqpxdxdkzJYu9wyakfKZj+gUgfO57
|
||||||
|
OFOkjFk07yFB27MuPctCFredmfpDr+ygHRoPkG7AHw2Fss2EEaeP5bU18ilPQMqN
|
||||||
|
vxVMs5EblVVUgJUVoVcsC2yz2f4S7oPOAk5BPoehOIzydauznWrvIAas7I8CgYBr
|
||||||
|
CFHxLoNq6cbZQ3JACERZrIf2/vmZjoOHtoR1gKYRK7R1NmKDB7lihRMtCSBix/4/
|
||||||
|
61Lkw+bJ5kzmn4lgzgUpTdWTWy5FquVlQxOA3EfRjlItNsXB5KKpksi7Y53vJ34u
|
||||||
|
eIUDbkW6NPQzmFOhtaw3k/gzq5Yd2v0M82iWAqiJRwKBgQCl2+e2cjISK31QhKTC
|
||||||
|
puhwQ0/YuC3zlwMXQgB3nPw8b9RlaDTMrRBCIUFIrrX11tHswGWpyVsxW2AvZ3Zm
|
||||||
|
jsWpwGkUdpRdXJBhSaisV/PA+x3kYhpibzEI8FrzhU69zNROCb8CTkN4WcdBdq6J
|
||||||
|
PUh/jRtKoE79qrlnIlNvFoz2gQ==
|
||||||
|
-----END PRIVATE KEY-----
|
98
tools/binman/test/341_fit_signature.dts
Normal file
98
tools/binman/test/341_fit_signature.dts
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
fit {
|
||||||
|
description = "test desc";
|
||||||
|
#address-cells = <1>;
|
||||||
|
fit,fdt-list = "of-list";
|
||||||
|
fit,sign;
|
||||||
|
|
||||||
|
images {
|
||||||
|
u-boot {
|
||||||
|
description = "test u-boot";
|
||||||
|
type = "standalone";
|
||||||
|
arch = "arm64";
|
||||||
|
os = "u-boot";
|
||||||
|
compression = "none";
|
||||||
|
load = <0x00000000>;
|
||||||
|
entry = <0x00000000>;
|
||||||
|
|
||||||
|
u-boot-nodtb {
|
||||||
|
};
|
||||||
|
|
||||||
|
hash {
|
||||||
|
algo = "sha256";
|
||||||
|
};
|
||||||
|
|
||||||
|
signature {
|
||||||
|
algo = "sha256,rsa2048";
|
||||||
|
key-name-hint = "rsa2048";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@atf-SEQ {
|
||||||
|
fit,operation = "split-elf";
|
||||||
|
description = "test tf-a";
|
||||||
|
type = "firmware";
|
||||||
|
arch = "arm64";
|
||||||
|
os = "arm-trusted-firmware";
|
||||||
|
compression = "none";
|
||||||
|
fit,load;
|
||||||
|
fit,entry;
|
||||||
|
fit,data;
|
||||||
|
|
||||||
|
atf-bl31 {
|
||||||
|
};
|
||||||
|
|
||||||
|
hash {
|
||||||
|
algo = "sha256";
|
||||||
|
};
|
||||||
|
|
||||||
|
signature {
|
||||||
|
algo = "sha256,rsa2048";
|
||||||
|
key-name-hint = "rsa2048";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@fdt-SEQ {
|
||||||
|
description = "test fdt";
|
||||||
|
type = "flat_dt";
|
||||||
|
compression = "none";
|
||||||
|
|
||||||
|
hash {
|
||||||
|
algo = "sha256";
|
||||||
|
};
|
||||||
|
|
||||||
|
signature {
|
||||||
|
algo = "sha256,rsa2048";
|
||||||
|
key-name-hint = "rsa2048";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
default = "@conf-uboot-DEFAULT-SEQ";
|
||||||
|
@conf-uboot-SEQ {
|
||||||
|
description = "uboot config";
|
||||||
|
fdt = "fdt-SEQ";
|
||||||
|
fit,firmware = "u-boot";
|
||||||
|
fit,loadables;
|
||||||
|
|
||||||
|
hash {
|
||||||
|
algo = "sha256";
|
||||||
|
};
|
||||||
|
|
||||||
|
signature {
|
||||||
|
algo = "sha256,rsa2048";
|
||||||
|
key-name-hint = "conf-rsa2048";
|
||||||
|
sign-images = "firmware", "loadables", "fdt";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
61
tools/binman/test/342_fit_signature.dts
Normal file
61
tools/binman/test/342_fit_signature.dts
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
fit {
|
||||||
|
description = "test desc";
|
||||||
|
#address-cells = <1>;
|
||||||
|
fit,fdt-list = "of-list";
|
||||||
|
fit,sign;
|
||||||
|
|
||||||
|
images {
|
||||||
|
u-boot {
|
||||||
|
description = "test u-boot";
|
||||||
|
type = "standalone";
|
||||||
|
arch = "arm64";
|
||||||
|
os = "u-boot";
|
||||||
|
compression = "none";
|
||||||
|
load = <0x00000000>;
|
||||||
|
entry = <0x00000000>;
|
||||||
|
|
||||||
|
u-boot-nodtb {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@atf-SEQ {
|
||||||
|
fit,operation = "split-elf";
|
||||||
|
description = "test tf-a";
|
||||||
|
type = "firmware";
|
||||||
|
arch = "arm64";
|
||||||
|
os = "arm-trusted-firmware";
|
||||||
|
compression = "none";
|
||||||
|
fit,load;
|
||||||
|
fit,entry;
|
||||||
|
fit,data;
|
||||||
|
|
||||||
|
atf-bl31 {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@fdt-SEQ {
|
||||||
|
description = "test fdt";
|
||||||
|
type = "flat_dt";
|
||||||
|
compression = "none";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
default = "@conf-uboot-DEFAULT-SEQ";
|
||||||
|
@conf-uboot-SEQ {
|
||||||
|
description = "uboot config";
|
||||||
|
fdt = "fdt-SEQ";
|
||||||
|
fit,firmware = "u-boot";
|
||||||
|
fit,loadables;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -34,7 +34,7 @@ from u_boot_pylib.terminal import tprint
|
||||||
# Error in reading or end of file.
|
# Error in reading or end of file.
|
||||||
# <<
|
# <<
|
||||||
# which indicates that BREAK_ME has an empty default
|
# which indicates that BREAK_ME has an empty default
|
||||||
RE_NO_DEFAULT = re.compile(b'\((\w+)\) \[] \(NEW\)')
|
RE_NO_DEFAULT = re.compile(br'\((\w+)\) \[] \(NEW\)')
|
||||||
|
|
||||||
# Symbol types which appear in the bloat feature (-B). Others are silently
|
# Symbol types which appear in the bloat feature (-B). Others are silently
|
||||||
# dropped when reading in the 'nm' output
|
# dropped when reading in the 'nm' output
|
||||||
|
@ -374,9 +374,9 @@ class Builder:
|
||||||
|
|
||||||
self._re_function = re.compile('(.*): In function.*')
|
self._re_function = re.compile('(.*): In function.*')
|
||||||
self._re_files = re.compile('In file included from.*')
|
self._re_files = re.compile('In file included from.*')
|
||||||
self._re_warning = re.compile('(.*):(\d*):(\d*): warning: .*')
|
self._re_warning = re.compile(r'(.*):(\d*):(\d*): warning: .*')
|
||||||
self._re_dtb_warning = re.compile('(.*): Warning .*')
|
self._re_dtb_warning = re.compile('(.*): Warning .*')
|
||||||
self._re_note = re.compile('(.*):(\d*):(\d*): note: this is the location of the previous.*')
|
self._re_note = re.compile(r'(.*):(\d*):(\d*): note: this is the location of the previous.*')
|
||||||
self._re_migration_warning = re.compile(r'^={21} WARNING ={22}\n.*\n=+\n',
|
self._re_migration_warning = re.compile(r'^={21} WARNING ={22}\n.*\n=+\n',
|
||||||
re.MULTILINE | re.DOTALL)
|
re.MULTILINE | re.DOTALL)
|
||||||
|
|
||||||
|
|
|
@ -440,12 +440,12 @@ class Toolchains:
|
||||||
This converts ${blah} within the string to the value of blah.
|
This converts ${blah} within the string to the value of blah.
|
||||||
This function works recursively.
|
This function works recursively.
|
||||||
|
|
||||||
|
Resolved string
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
var_dict: Dictionary containing variables and their values
|
var_dict: Dictionary containing variables and their values
|
||||||
args: String containing make arguments
|
args: String containing make arguments
|
||||||
Returns:
|
Returns:
|
||||||
Resolved string
|
|
||||||
|
|
||||||
>>> bsettings.setup(None)
|
>>> bsettings.setup(None)
|
||||||
>>> tcs = Toolchains()
|
>>> tcs = Toolchains()
|
||||||
>>> tcs.Add('fred', False)
|
>>> tcs.Add('fred', False)
|
||||||
|
@ -456,7 +456,7 @@ class Toolchains:
|
||||||
>>> tcs.ResolveReferences(var_dict, 'this=${oblique}_set${first}nd')
|
>>> tcs.ResolveReferences(var_dict, 'this=${oblique}_set${first}nd')
|
||||||
'this=OBLIQUE_setfi2ndrstnd'
|
'this=OBLIQUE_setfi2ndrstnd'
|
||||||
"""
|
"""
|
||||||
re_var = re.compile('(\$\{[-_a-z0-9A-Z]{1,}\})')
|
re_var = re.compile(r'(\$\{[-_a-z0-9A-Z]{1,}\})')
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
m = re_var.search(args)
|
m = re_var.search(args)
|
||||||
|
@ -495,7 +495,7 @@ class Toolchains:
|
||||||
self._make_flags['target'] = brd.target
|
self._make_flags['target'] = brd.target
|
||||||
arg_str = self.ResolveReferences(self._make_flags,
|
arg_str = self.ResolveReferences(self._make_flags,
|
||||||
self._make_flags.get(brd.target, ''))
|
self._make_flags.get(brd.target, ''))
|
||||||
args = re.findall("(?:\".*?\"|\S)+", arg_str)
|
args = re.findall(r"(?:\".*?\"|\S)+", arg_str)
|
||||||
i = 0
|
i = 0
|
||||||
while i < len(args):
|
while i < len(args):
|
||||||
args[i] = args[i].replace('"', '')
|
args[i] = args[i].replace('"', '')
|
||||||
|
|
|
@ -244,12 +244,15 @@ RUN mkdir /tmp/trace && \
|
||||||
rm -rf /tmp/trace
|
rm -rf /tmp/trace
|
||||||
|
|
||||||
# Build coreboot
|
# Build coreboot
|
||||||
RUN wget -O - https://coreboot.org/releases/coreboot-4.22.01.tar.xz | tar -C /tmp -xJ && \
|
RUN wget -O - https://coreboot.org/releases/coreboot-24.08.tar.xz | tar -C /tmp -xJ && \
|
||||||
cd /tmp/coreboot-4.22.01 && \
|
cd /tmp/coreboot-24.08 && \
|
||||||
make crossgcc-i386 CPUS=$(nproc) && \
|
make crossgcc-i386 CPUS=$(nproc) && \
|
||||||
make -C payloads/coreinfo olddefconfig && \
|
make -C payloads/coreinfo olddefconfig && \
|
||||||
make -C payloads/coreinfo && \
|
make -C payloads/coreinfo && \
|
||||||
make olddefconfig && \
|
make olddefconfig && \
|
||||||
|
echo CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y | tee -a .config && \
|
||||||
|
echo CONFIG_USE_OPTION_TABLE=y | tee -a .config && \
|
||||||
|
make olddefconfig && \
|
||||||
make -j $(nproc) && \
|
make -j $(nproc) && \
|
||||||
sudo mkdir /opt/coreboot && \
|
sudo mkdir /opt/coreboot && \
|
||||||
sudo cp build/coreboot.rom build/cbfstool /opt/coreboot/
|
sudo cp build/coreboot.rom build/cbfstool /opt/coreboot/
|
||||||
|
|
|
@ -20,17 +20,22 @@ from u_boot_pylib import tools
|
||||||
|
|
||||||
# Parse:
|
# Parse:
|
||||||
# SCENE1 = 7,
|
# SCENE1 = 7,
|
||||||
|
# or SCENE1 = EXPOID_BASE_ID,
|
||||||
# or SCENE2,
|
# or SCENE2,
|
||||||
RE_ENUM = re.compile(r'(\S*)(\s*= (\d))?,')
|
RE_ENUM = re.compile(r'(\S*)(\s*= ([0-9A-Z_]+))?,')
|
||||||
|
|
||||||
# Parse #define <name> "string"
|
# Parse #define <name> "string"
|
||||||
RE_DEF = re.compile(r'#define (\S*)\s*"(.*)"')
|
RE_DEF = re.compile(r'#define (\S*)\s*"(.*)"')
|
||||||
|
|
||||||
def calc_ids(fname):
|
# Parse EXPOID_BASE_ID = 5,
|
||||||
|
RE_BASE_ID = re.compile(r'\s*EXPOID_BASE_ID\s*= (\d+),')
|
||||||
|
|
||||||
|
def calc_ids(fname, base_id):
|
||||||
"""Figure out the value of the enums in a C file
|
"""Figure out the value of the enums in a C file
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
fname (str): Filename to parse
|
fname (str): Filename to parse
|
||||||
|
base_id (int): Base ID (value of EXPOID_BASE_ID)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
OrderedDict():
|
OrderedDict():
|
||||||
|
@ -55,8 +60,12 @@ def calc_ids(fname):
|
||||||
if not line or line.startswith('/*'):
|
if not line or line.startswith('/*'):
|
||||||
continue
|
continue
|
||||||
m_enum = RE_ENUM.match(line)
|
m_enum = RE_ENUM.match(line)
|
||||||
if m_enum.group(3):
|
enum_name = m_enum.group(3)
|
||||||
cur_id = int(m_enum.group(3))
|
if enum_name:
|
||||||
|
if enum_name == 'EXPOID_BASE_ID':
|
||||||
|
cur_id = base_id
|
||||||
|
else:
|
||||||
|
cur_id = int(enum_name)
|
||||||
vals[m_enum.group(1)] = cur_id
|
vals[m_enum.group(1)] = cur_id
|
||||||
cur_id += 1
|
cur_id += 1
|
||||||
else:
|
else:
|
||||||
|
@ -67,10 +76,24 @@ def calc_ids(fname):
|
||||||
return vals
|
return vals
|
||||||
|
|
||||||
|
|
||||||
|
def find_base_id():
|
||||||
|
fname = 'include/expo.h'
|
||||||
|
base_id = None
|
||||||
|
with open(fname, 'r', encoding='utf-8') as inf:
|
||||||
|
for line in inf.readlines():
|
||||||
|
m_base_id = RE_BASE_ID.match(line)
|
||||||
|
if m_base_id:
|
||||||
|
base_id = int(m_base_id.group(1))
|
||||||
|
if base_id is None:
|
||||||
|
raise ValueError('EXPOID_BASE_ID not found in expo.h')
|
||||||
|
#print(f'EXPOID_BASE_ID={base_id}')
|
||||||
|
return base_id
|
||||||
|
|
||||||
def run_expo(args):
|
def run_expo(args):
|
||||||
"""Run the expo program"""
|
"""Run the expo program"""
|
||||||
|
base_id = find_base_id()
|
||||||
fname = args.enum_fname or args.layout
|
fname = args.enum_fname or args.layout
|
||||||
ids = calc_ids(fname)
|
ids = calc_ids(fname, base_id)
|
||||||
if not ids:
|
if not ids:
|
||||||
print(f"Warning: No enum ID values found in file '{fname}'")
|
print(f"Warning: No enum ID values found in file '{fname}'")
|
||||||
|
|
||||||
|
|
|
@ -1333,7 +1333,7 @@ int fit_add_verification_data(const char *keydir, const char *keyfile,
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "Can't add verification data for node '%s' (%s)\n",
|
fprintf(stderr, "Can't add verification data for node '%s' (%s)\n",
|
||||||
fdt_get_name(fit, noffset, NULL),
|
fdt_get_name(fit, noffset, NULL),
|
||||||
fdt_strerror(ret));
|
strerror(-ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,9 @@ except:
|
||||||
use_concurrent = False
|
use_concurrent = False
|
||||||
|
|
||||||
|
|
||||||
def run_test_coverage(prog, filter_fname, exclude_list, build_dir, required=None,
|
def run_test_coverage(prog, filter_fname, exclude_list, build_dir,
|
||||||
extra_args=None, single_thread='-P1'):
|
required=None, extra_args=None, single_thread='-P1',
|
||||||
|
args=None):
|
||||||
"""Run tests and check that we get 100% coverage
|
"""Run tests and check that we get 100% coverage
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -42,6 +43,7 @@ def run_test_coverage(prog, filter_fname, exclude_list, build_dir, required=None
|
||||||
single_thread (str): Argument string to make the tests run
|
single_thread (str): Argument string to make the tests run
|
||||||
single-threaded. This is necessary to get proper coverage results.
|
single-threaded. This is necessary to get proper coverage results.
|
||||||
The default is '-P0'
|
The default is '-P0'
|
||||||
|
args (list of str): List of tests to run, or None to run all
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ValueError if the code coverage is not 100%
|
ValueError if the code coverage is not 100%
|
||||||
|
@ -66,9 +68,10 @@ def run_test_coverage(prog, filter_fname, exclude_list, build_dir, required=None
|
||||||
'coverage')
|
'coverage')
|
||||||
|
|
||||||
cmd = ('%s%s run '
|
cmd = ('%s%s run '
|
||||||
'--omit "%s" %s %s %s %s' % (prefix, covtool, ','.join(glob_list),
|
'--omit "%s" %s %s %s %s %s' % (prefix, covtool, ','.join(glob_list),
|
||||||
prog, extra_args or '', test_cmd,
|
prog, extra_args or '', test_cmd,
|
||||||
single_thread or '-P1'))
|
single_thread or '-P1',
|
||||||
|
' '.join(args) if args else ''))
|
||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
stdout = command.output(covtool, 'report')
|
stdout = command.output(covtool, 'report')
|
||||||
lines = stdout.splitlines()
|
lines = stdout.splitlines()
|
||||||
|
|
Loading…
Add table
Reference in a new issue