Merge tag 'dm-pull-28mar21' of git://git.denx.de/u-boot-dm into next
binman support for expanding entries, connections
misc fixes and improvements to sandbox, etc.
x86 CBFS improvements
x86 coreboot improvements
diff --git a/arch/riscv/cpu/ax25/Kconfig b/arch/riscv/cpu/ax25/Kconfig
index 327b74e..941d963 100644
--- a/arch/riscv/cpu/ax25/Kconfig
+++ b/arch/riscv/cpu/ax25/Kconfig
@@ -6,7 +6,7 @@
imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
imply ANDES_PLIC if (RISCV_MMODE || SPL_RISCV_MMODE)
imply ANDES_PLMT_TIMER if (RISCV_MMODE || SPL_RISCV_MMODE)
- imply SPL_CPU_SUPPORT
+ imply SPL_CPU
imply SPL_OPENSBI
imply SPL_LOAD_FIT
help
diff --git a/arch/riscv/cpu/fu540/Kconfig b/arch/riscv/cpu/fu540/Kconfig
index 61bd5c4..616b256 100644
--- a/arch/riscv/cpu/fu540/Kconfig
+++ b/arch/riscv/cpu/fu540/Kconfig
@@ -13,7 +13,7 @@
imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
imply CMD_CPU
- imply SPL_CPU_SUPPORT
+ imply SPL_CPU
imply SPL_OPENSBI
imply SPL_LOAD_FIT
imply SMP
diff --git a/arch/riscv/cpu/generic/Kconfig b/arch/riscv/cpu/generic/Kconfig
index f4c2e26..198e36e 100644
--- a/arch/riscv/cpu/generic/Kconfig
+++ b/arch/riscv/cpu/generic/Kconfig
@@ -10,6 +10,6 @@
imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
imply CMD_CPU
- imply SPL_CPU_SUPPORT
+ imply SPL_CPU
imply SPL_OPENSBI
imply SPL_LOAD_FIT
diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index edd48e2..48636ab 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -6,7 +6,6 @@
#include <common.h>
#include <bootstage.h>
#include <cpu_func.h>
-#include <dm.h>
#include <errno.h>
#include <log.h>
#include <asm/global_data.h>
@@ -17,7 +16,6 @@
#include <asm/malloc.h>
#include <asm/setjmp.h>
#include <asm/state.h>
-#include <dm/root.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -34,10 +32,8 @@
{
/* Do this here while it still has an effect */
os_fd_restore();
- if (state_uninit())
- os_exit(2);
- if (dm_uninit())
+ if (state_uninit())
os_exit(2);
/* This is considered normal termination for now */
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 68825d2..b9ad341 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -711,7 +711,7 @@
* @fname: Filename to exec
* @return does not return on success, any return value is an error
*/
-static int os_jump_to_file(const char *fname)
+static int os_jump_to_file(const char *fname, bool delete_it)
{
struct sandbox_state *state = state_get_current();
char mem_fname[30];
@@ -734,11 +734,13 @@
os_fd_restore();
- extra_args[0] = "-j";
- extra_args[1] = (char *)fname;
- extra_args[2] = "-m";
- extra_args[3] = mem_fname;
- argc = 4;
+ argc = 0;
+ if (delete_it) {
+ extra_args[argc++] = "-j";
+ extra_args[argc++] = (char *)fname;
+ }
+ extra_args[argc++] = "-m";
+ extra_args[argc++] = mem_fname;
if (state->ram_buf_rm)
extra_args[argc++] = "--rm_memory";
err = add_args(&argv, extra_args, argc);
@@ -762,7 +764,10 @@
return err;
}
- return unlink(fname);
+ if (delete_it)
+ return unlink(fname);
+
+ return -EFAULT;
}
int os_jump_to_image(const void *dest, int size)
@@ -774,7 +779,7 @@
if (err)
return err;
- return os_jump_to_file(fname);
+ return os_jump_to_file(fname, true);
}
int os_find_u_boot(char *fname, int maxlen, bool use_img)
@@ -847,7 +852,8 @@
/* U-Boot will delete ram buffer after read: "--rm_memory"*/
state->ram_buf_rm = true;
- return os_jump_to_file(fname);
+
+ return os_jump_to_file(fname, false);
}
long os_get_time_offset(void)
diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds
index 936da5e..a1f509c 100644
--- a/arch/sandbox/cpu/u-boot.lds
+++ b/arch/sandbox/cpu/u-boot.lds
@@ -44,6 +44,13 @@
{
*(.__efi_runtime_rel_stop)
}
+
+ .dynsym :
+ {
+ __dyn_sym_start = .;
+ *(.dynsym)
+ __dyn_sym_end = .;
+ }
}
INSERT BEFORE .data;
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 69d7d30..31db50d 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -200,6 +200,10 @@
compatible = "sandbox,reset";
};
+ rng {
+ compatible = "sandbox,sandbox-rng";
+ };
+
sound {
compatible = "sandbox,sound";
cpu {
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5b089af..970bdff 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1047,4 +1047,25 @@
endif # INTEL_SOC
+config COREBOOT_SYSINFO
+ bool "Support reading coreboot sysinfo"
+ default y if SYS_COREBOOT
+ help
+ Select this option to read the coreboot sysinfo table on start-up,
+ if present. This is written by coreboot before it exits and provides
+ various pieces of information about the running system, including
+ display, memory and build information. It is stored in
+ struct sysinfo_t after parsing by get_coreboot_info().
+
+config SPL_COREBOOT_SYSINFO
+ bool "Support reading coreboot sysinfo"
+ depends on SPL
+ default y if COREBOOT_SYSINFO
+ help
+ Select this option to read the coreboot sysinfo table in SPL,
+ if present. This is written by coreboot before it exits and provides
+ various pieces of information about the running system, including
+ display, memory and build information. It is stored in
+ struct sysinfo_t after parsing by get_coreboot_info().
+
endmenu
diff --git a/arch/x86/cpu/apollolake/cpu.c b/arch/x86/cpu/apollolake/cpu.c
index fbc016d..647c9df 100644
--- a/arch/x86/cpu/apollolake/cpu.c
+++ b/arch/x86/cpu/apollolake/cpu.c
@@ -19,6 +19,7 @@
#include <asm/arch/iomap.h>
#include <dm/acpi.h>
+#ifdef CONFIG_ACPIGEN
#define CSTATE_RES(address_space, width, offset, address) \
{ \
.space_id = address_space, \
@@ -57,11 +58,6 @@
},
};
-static int apl_get_info(const struct udevice *dev, struct cpu_info *info)
-{
- return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
-}
-
static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
{
uint core_id = dev_seq(dev);
@@ -89,6 +85,12 @@
return 0;
}
+#endif /* CONFIG_ACPIGEN */
+
+static int apl_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+ return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
+}
static void update_fixed_mtrrs(void)
{
@@ -170,9 +172,11 @@
return 0;
}
+#ifdef CONFIG_ACPIGEN
struct acpi_ops apl_cpu_acpi_ops = {
.fill_ssdt = acpi_cpu_fill_ssdt,
};
+#endif
static const struct cpu_ops cpu_x86_apl_ops = {
.get_desc = cpu_x86_get_desc,
diff --git a/arch/x86/cpu/apollolake/cpu_common.c b/arch/x86/cpu/apollolake/cpu_common.c
index 63f6999..5d7d26b 100644
--- a/arch/x86/cpu/apollolake/cpu_common.c
+++ b/arch/x86/cpu/apollolake/cpu_common.c
@@ -7,11 +7,17 @@
#include <dm.h>
#include <log.h>
#include <asm/cpu_common.h>
+#include <asm/io.h>
#include <asm/msr.h>
+#include <asm/pci.h>
#include <asm/arch/cpu.h>
#include <asm/arch/iomap.h>
+#include <asm/arch/uart.h>
#include <power/acpi_pmc.h>
+/* Define this here to avoid referencing any drivers for the debug UART 1 */
+#define PCH_DEV_P2SB PCI_BDF(0, 0x0d, 0)
+
void cpu_flush_l1d_to_l2(void)
{
struct msr_t msr;
@@ -40,3 +46,57 @@
debug("PM timer %x %x\n", msr.hi, msr.lo);
msr_write(MSR_EMULATE_PM_TIMER, msr);
}
+
+static void pch_uart_init(void)
+{
+ /*
+ * Set up the pinmux so that the UART rx/tx signals are connected
+ * outside the SoC.
+ *
+ * There are about 500 lines of code required to program the GPIO
+ * configuration for the UARTs. But it boils down to four writes, and
+ * for the debug UART we want the minimum possible amount of code before
+ * the UART is running. So just add the magic writes here. See
+ * apl_hostbridge_early_init_pinctrl() for the full horror.
+ */
+ if (PCI_FUNC(PCH_DEV_UART) == 1) {
+ writel(0x40000402, 0xd0c50650);
+ writel(0x3c47, 0xd0c50654);
+ writel(0x40000400, 0xd0c50658);
+ writel(0x3c48, 0xd0c5065c);
+ } else { /* UART2 */
+ writel(0x40000402, 0xd0c50670);
+ writel(0x3c4b, 0xd0c50674);
+ writel(0x40000400, 0xd0c50678);
+ writel(0x3c4c, 0xd0c5067c);
+ }
+
+#ifdef CONFIG_DEBUG_UART
+ apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE);
+#endif
+}
+
+static void p2sb_enable_bar(ulong bar)
+{
+ /* Enable PCR Base address in PCH */
+ pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar,
+ PCI_SIZE_32);
+ pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
+
+ /* Enable P2SB MSE */
+ pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND,
+ PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY,
+ PCI_SIZE_8);
+}
+
+/*
+ * board_debug_uart_init() - Init the debug UART ready for use
+ *
+ * This is the minimum init needed to get the UART running. It avoids any
+ * drivers or complex code, so that the UART is running as soon as possible.
+ */
+void board_debug_uart_init(void)
+{
+ p2sb_enable_bar(IOMAP_P2SB_BAR);
+ pch_uart_init();
+}
diff --git a/arch/x86/cpu/apollolake/cpu_spl.c b/arch/x86/cpu/apollolake/cpu_spl.c
index 9a18476..8f48457 100644
--- a/arch/x86/cpu/apollolake/cpu_spl.c
+++ b/arch/x86/cpu/apollolake/cpu_spl.c
@@ -31,68 +31,10 @@
#include <asm/arch/lpc.h>
#include <asm/arch/pch.h>
#include <asm/arch/systemagent.h>
-#include <asm/arch/uart.h>
#include <asm/fsp2/fsp_api.h>
#include <linux/sizes.h>
#include <power/acpi_pmc.h>
-/* Define this here to avoid referencing any drivers for the debug UART 1 */
-#define PCH_DEV_P2SB PCI_BDF(0, 0x0d, 0)
-
-static void pch_uart_init(void)
-{
- /*
- * Set up the pinmux so that the UART rx/tx signals are connected
- * outside the SoC.
- *
- * There are about 500 lines of code required to program the GPIO
- * configuration for the UARTs. But it boils down to four writes, and
- * for the debug UART we want the minimum possible amount of code before
- * the UART is running. So just add the magic writes here. See
- * apl_hostbridge_early_init_pinctrl() for the full horror.
- */
- if (PCI_FUNC(PCH_DEV_UART) == 1) {
- writel(0x40000402, 0xd0c50650);
- writel(0x3c47, 0xd0c50654);
- writel(0x40000400, 0xd0c50658);
- writel(0x3c48, 0xd0c5065c);
- } else { /* UART2 */
- writel(0x40000402, 0xd0c50670);
- writel(0x3c4b, 0xd0c50674);
- writel(0x40000400, 0xd0c50678);
- writel(0x3c4c, 0xd0c5067c);
- }
-
-#ifdef CONFIG_DEBUG_UART
- apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE);
-#endif
-}
-
-static void p2sb_enable_bar(ulong bar)
-{
- /* Enable PCR Base address in PCH */
- pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar,
- PCI_SIZE_32);
- pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
-
- /* Enable P2SB MSE */
- pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND,
- PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY,
- PCI_SIZE_8);
-}
-
-/*
- * board_debug_uart_init() - Init the debug UART ready for use
- *
- * This is the minimum init needed to get the UART running. It avoids any
- * drivers or complex code, so that the UART is running as soon as possible.
- */
-void board_debug_uart_init(void)
-{
- p2sb_enable_bar(IOMAP_P2SB_BAR);
- pch_uart_init();
-}
-
static int fast_spi_cache_bios_region(void)
{
uint map_size, offset;
diff --git a/arch/x86/cpu/coreboot/Makefile b/arch/x86/cpu/coreboot/Makefile
index 605f903..a6cdb9a 100644
--- a/arch/x86/cpu/coreboot/Makefile
+++ b/arch/x86/cpu/coreboot/Makefile
@@ -20,5 +20,4 @@
obj-y += sdram.o
endif
obj-y += coreboot.o
-obj-y += tables.o
obj-y += timestamp.o
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c
index 15c3ad8..69cf8f4 100644
--- a/arch/x86/cpu/coreboot/coreboot.c
+++ b/arch/x86/cpu/coreboot/coreboot.c
@@ -14,7 +14,7 @@
#include <asm/io.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
#include <asm/arch/timestamp.h>
DECLARE_GLOBAL_DATA_PTR;
diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c
index a2e47d1..4a256ba 100644
--- a/arch/x86/cpu/coreboot/sdram.c
+++ b/arch/x86/cpu/coreboot/sdram.c
@@ -8,7 +8,7 @@
#include <common.h>
#include <init.h>
#include <asm/e820.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
#include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -16,32 +16,7 @@
unsigned int install_e820_map(unsigned int max_entries,
struct e820_entry *entries)
{
- unsigned int num_entries;
- int i;
-
- num_entries = min((unsigned int)lib_sysinfo.n_memranges, max_entries);
- if (num_entries < lib_sysinfo.n_memranges) {
- printf("Warning: Limiting e820 map to %d entries.\n",
- num_entries);
- }
- for (i = 0; i < num_entries; i++) {
- struct memrange *memrange = &lib_sysinfo.memrange[i];
-
- entries[i].addr = memrange->base;
- entries[i].size = memrange->size;
-
- /*
- * coreboot has some extensions (type 6 & 16) to the E820 types.
- * When we detect this, mark it as E820_RESERVED.
- */
- if (memrange->type == CB_MEM_VENDOR_RSVD ||
- memrange->type == CB_MEM_TABLE)
- entries[i].type = E820_RESERVED;
- else
- entries[i].type = memrange->type;
- }
-
- return num_entries;
+ return cb_install_e820_map(max_entries, entries);
}
/*
diff --git a/arch/x86/cpu/coreboot/tables.c b/arch/x86/cpu/coreboot/tables.c
deleted file mode 100644
index c52741a..0000000
--- a/arch/x86/cpu/coreboot/tables.c
+++ /dev/null
@@ -1,255 +0,0 @@
-// SPDX-License-Identifier: BSD-3-Clause
-/*
- * This file is part of the libpayload project.
- *
- * Copyright (C) 2008 Advanced Micro Devices, Inc.
- * Copyright (C) 2009 coresystems GmbH
- */
-
-#include <common.h>
-#include <net.h>
-#include <asm/arch/sysinfo.h>
-#include <asm/global_data.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/*
- * This needs to be in the .data section so that it's copied over during
- * relocation. By default it's put in the .bss section which is simply filled
- * with zeroes when transitioning from "ROM", which is really RAM, to other
- * RAM.
- */
-struct sysinfo_t lib_sysinfo __attribute__((section(".data")));
-
-/*
- * Some of this is x86 specific, and the rest of it is generic. Right now,
- * since we only support x86, we'll avoid trying to make lots of infrastructure
- * we don't need. If in the future, we want to use coreboot on some other
- * architecture, then take out the generic parsing code and move it elsewhere.
- */
-
-/* === Parsing code === */
-/* This is the generic parsing code. */
-
-static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info)
-{
- struct cb_memory *mem = (struct cb_memory *)ptr;
- int count = MEM_RANGE_COUNT(mem);
- int i;
-
- if (count > SYSINFO_MAX_MEM_RANGES)
- count = SYSINFO_MAX_MEM_RANGES;
-
- info->n_memranges = 0;
-
- for (i = 0; i < count; i++) {
- struct cb_memory_range *range =
- (struct cb_memory_range *)MEM_RANGE_PTR(mem, i);
-
- info->memrange[info->n_memranges].base =
- UNPACK_CB64(range->start);
-
- info->memrange[info->n_memranges].size =
- UNPACK_CB64(range->size);
-
- info->memrange[info->n_memranges].type = range->type;
-
- info->n_memranges++;
- }
-}
-
-static void cb_parse_serial(unsigned char *ptr, struct sysinfo_t *info)
-{
- struct cb_serial *ser = (struct cb_serial *)ptr;
- info->serial = ser;
-}
-
-static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info)
-{
- struct cb_vbnv *vbnv = (struct cb_vbnv *)ptr;
-
- info->vbnv_start = vbnv->vbnv_start;
- info->vbnv_size = vbnv->vbnv_size;
-}
-
-static void cb_parse_cbmem_entry(unsigned char *ptr, struct sysinfo_t *info)
-{
- struct cb_cbmem_entry *entry = (struct cb_cbmem_entry *)ptr;
-
- if (entry->id != CBMEM_ID_SMBIOS)
- return;
-
- info->smbios_start = entry->address;
- info->smbios_size = entry->entry_size;
-}
-
-static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info)
-{
- int i;
- struct cb_gpios *gpios = (struct cb_gpios *)ptr;
-
- info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ?
- (gpios->count) : SYSINFO_MAX_GPIOS;
-
- for (i = 0; i < info->num_gpios; i++)
- info->gpios[i] = gpios->gpios[i];
-}
-
-static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info)
-{
- struct cb_vdat *vdat = (struct cb_vdat *) ptr;
-
- info->vdat_addr = vdat->vdat_addr;
- info->vdat_size = vdat->vdat_size;
-}
-
-static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info)
-{
- info->tstamp_table = ((struct cb_cbmem_tab *)ptr)->cbmem_tab;
-}
-
-static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info)
-{
- info->cbmem_cons = ((struct cb_cbmem_tab *)ptr)->cbmem_tab;
-}
-
-static void cb_parse_framebuffer(unsigned char *ptr, struct sysinfo_t *info)
-{
- info->framebuffer = (struct cb_framebuffer *)ptr;
-}
-
-static void cb_parse_string(unsigned char *ptr, char **info)
-{
- *info = (char *)((struct cb_string *)ptr)->string;
-}
-
-__weak void cb_parse_unhandled(u32 tag, unsigned char *ptr)
-{
-}
-
-static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
-{
- unsigned char *ptr = addr;
- struct cb_header *header;
- int i;
-
- header = (struct cb_header *)ptr;
- if (!header->table_bytes)
- return 0;
-
- /* Make sure the checksums match. */
- if (!ip_checksum_ok(header, sizeof(*header)))
- return -1;
-
- if (compute_ip_checksum(ptr + sizeof(*header), header->table_bytes) !=
- header->table_checksum)
- return -1;
-
- /* Now, walk the tables. */
- ptr += header->header_bytes;
-
- /* Inintialize some fields to sentinel values. */
- info->vbnv_start = info->vbnv_size = (uint32_t)(-1);
-
- for (i = 0; i < header->table_entries; i++) {
- struct cb_record *rec = (struct cb_record *)ptr;
-
- /* We only care about a few tags here (maybe more later). */
- switch (rec->tag) {
- case CB_TAG_FORWARD:
- return cb_parse_header(
- (void *)(unsigned long)
- ((struct cb_forward *)rec)->forward,
- len, info);
- continue;
- case CB_TAG_MEMORY:
- cb_parse_memory(ptr, info);
- break;
- case CB_TAG_SERIAL:
- cb_parse_serial(ptr, info);
- break;
- case CB_TAG_VERSION:
- cb_parse_string(ptr, &info->version);
- break;
- case CB_TAG_EXTRA_VERSION:
- cb_parse_string(ptr, &info->extra_version);
- break;
- case CB_TAG_BUILD:
- cb_parse_string(ptr, &info->build);
- break;
- case CB_TAG_COMPILE_TIME:
- cb_parse_string(ptr, &info->compile_time);
- break;
- case CB_TAG_COMPILE_BY:
- cb_parse_string(ptr, &info->compile_by);
- break;
- case CB_TAG_COMPILE_HOST:
- cb_parse_string(ptr, &info->compile_host);
- break;
- case CB_TAG_COMPILE_DOMAIN:
- cb_parse_string(ptr, &info->compile_domain);
- break;
- case CB_TAG_COMPILER:
- cb_parse_string(ptr, &info->compiler);
- break;
- case CB_TAG_LINKER:
- cb_parse_string(ptr, &info->linker);
- break;
- case CB_TAG_ASSEMBLER:
- cb_parse_string(ptr, &info->assembler);
- break;
- /*
- * FIXME we should warn on serial if coreboot set up a
- * framebuffer buf the payload does not know about it.
- */
- case CB_TAG_FRAMEBUFFER:
- cb_parse_framebuffer(ptr, info);
- break;
- case CB_TAG_GPIO:
- cb_parse_gpios(ptr, info);
- break;
- case CB_TAG_VDAT:
- cb_parse_vdat(ptr, info);
- break;
- case CB_TAG_TIMESTAMPS:
- cb_parse_tstamp(ptr, info);
- break;
- case CB_TAG_CBMEM_CONSOLE:
- cb_parse_cbmem_cons(ptr, info);
- break;
- case CB_TAG_VBNV:
- cb_parse_vbnv(ptr, info);
- break;
- case CB_TAG_CBMEM_ENTRY:
- cb_parse_cbmem_entry(ptr, info);
- break;
- default:
- cb_parse_unhandled(rec->tag, ptr);
- break;
- }
-
- ptr += rec->size;
- }
-
- return 1;
-}
-
-/* == Architecture specific == */
-/* This is the x86 specific stuff. */
-
-int get_coreboot_info(struct sysinfo_t *info)
-{
- long addr;
- int ret;
-
- addr = locate_coreboot_table();
- if (addr < 0)
- return addr;
- ret = cb_parse_header((void *)addr, 0x1000, info);
- if (!ret)
- return -ENOENT;
- gd->arch.coreboot_table = addr;
- gd->flags |= GD_FLG_SKIP_LL_INIT;
-
- return 0;
-}
diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c
index 0162597..7f133ce 100644
--- a/arch/x86/cpu/coreboot/timestamp.c
+++ b/arch/x86/cpu/coreboot/timestamp.c
@@ -8,21 +8,9 @@
#include <common.h>
#include <bootstage.h>
#include <asm/arch/timestamp.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
#include <linux/compiler.h>
-struct timestamp_entry {
- uint32_t entry_id;
- uint64_t entry_stamp;
-} __packed;
-
-struct timestamp_table {
- uint64_t base_time;
- uint32_t max_entries;
- uint32_t num_entries;
- struct timestamp_entry entries[0]; /* Variable number of entries */
-} __packed;
-
static struct timestamp_table *ts_table __attribute__((section(".data")));
void timestamp_init(void)
diff --git a/arch/x86/cpu/start_from_spl.S b/arch/x86/cpu/start_from_spl.S
index 905c825..abfd4ab 100644
--- a/arch/x86/cpu/start_from_spl.S
+++ b/arch/x86/cpu/start_from_spl.S
@@ -43,6 +43,10 @@
call board_init_f_init_reserve
+#ifdef CONFIG_DEBUG_UART
+ call debug_uart_init
+#endif
+
call x86_cpu_reinit_f
xorl %eax, %eax
call board_init_f
diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts
index d109a38..c8cb4e2 100644
--- a/arch/x86/dts/chromebook_coral.dts
+++ b/arch/x86/dts/chromebook_coral.dts
@@ -47,6 +47,7 @@
i2c5 = &i2c_5;
i2c6 = &i2c_6;
i2c7 = &i2c_7;
+ mmc0 = &emmc;
mmc1 = &sdmmc;
};
@@ -55,6 +56,17 @@
recovery-gpios = <&gpio_nw (-1) GPIO_ACTIVE_LOW>;
write-protect-gpios = <&gpio_nw GPIO_75 GPIO_ACTIVE_HIGH>;
phase-enforce-gpios = <&gpio_n GPIO_10 GPIO_ACTIVE_HIGH>;
+ memconfig-gpios = <&gpio_nw GPIO_101 GPIO_ACTIVE_HIGH
+ &gpio_nw GPIO_102 GPIO_ACTIVE_HIGH
+ &gpio_n GPIO_38 GPIO_ACTIVE_HIGH
+ &gpio_n GPIO_45 GPIO_ACTIVE_HIGH>;
+
+ /*
+ * This is used for reef only:
+ *
+ * skuconfig-gpios = <&gpio_nw GPIO_16 GPIO_ACTIVE_HIGH
+ * &gpio_nw GPIO_17 GPIO_ACTIVE_HIGH>;
+ */
smbios {
/* Type 1 table */
system {
@@ -148,6 +160,11 @@
#interrupt-cells = <2>;
};
+ coreboot-video {
+ /* This will only activate when booted from coreboot */
+ compatible = "coreboot-fb";
+ };
+
keyboard {
intel,duplicate-por;
};
@@ -571,7 +588,7 @@
sdmmc: sdmmc@1b,0 {
reg = <0x0000d800 0 0 0 0>;
compatible = "intel,apl-sd";
- cd-gpios = <&gpio_n GPIO_177 GPIO_ACTIVE_LOW>;
+ cd-gpios = <&gpio_sw GPIO_177 GPIO_ACTIVE_LOW>;
acpi,name = "SDCD";
};
diff --git a/arch/x86/include/asm/arch-apollolake/uart.h b/arch/x86/include/asm/arch-apollolake/uart.h
index 38335b0..c3ca171 100644
--- a/arch/x86/include/asm/arch-apollolake/uart.h
+++ b/arch/x86/include/asm/arch-apollolake/uart.h
@@ -6,6 +6,7 @@
#ifndef _ASM_ARCH_UART_H
#define _ASM_ARCH_UART_H
+#include <dt-structs.h>
#include <ns16550.h>
/**
diff --git a/arch/x86/include/asm/arch-coreboot/sysinfo.h b/arch/x86/include/asm/arch-coreboot/sysinfo.h
deleted file mode 100644
index 419ec52..0000000
--- a/arch/x86/include/asm/arch-coreboot/sysinfo.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause */
-/*
- * This file is part of the libpayload project.
- *
- * Copyright (C) 2008 Advanced Micro Devices, Inc.
- */
-
-#ifndef _COREBOOT_SYSINFO_H
-#define _COREBOOT_SYSINFO_H
-
-#include <asm/coreboot_tables.h>
-
-/* Maximum number of memory range definitions */
-#define SYSINFO_MAX_MEM_RANGES 32
-/* Allow a maximum of 8 GPIOs */
-#define SYSINFO_MAX_GPIOS 8
-
-struct sysinfo_t {
- int n_memranges;
- struct memrange {
- unsigned long long base;
- unsigned long long size;
- unsigned int type;
- } memrange[SYSINFO_MAX_MEM_RANGES];
-
- u32 cmos_range_start;
- u32 cmos_range_end;
- u32 cmos_checksum_location;
- u32 vbnv_start;
- u32 vbnv_size;
-
- char *version;
- char *extra_version;
- char *build;
- char *compile_time;
- char *compile_by;
- char *compile_host;
- char *compile_domain;
- char *compiler;
- char *linker;
- char *assembler;
-
- struct cb_framebuffer *framebuffer;
-
- int num_gpios;
- struct cb_gpio gpios[SYSINFO_MAX_GPIOS];
-
- void *vdat_addr;
- u32 vdat_size;
- void *tstamp_table;
- void *cbmem_cons;
- u64 smbios_start;
- u32 smbios_size;
-
- struct cb_serial *serial;
-};
-
-extern struct sysinfo_t lib_sysinfo;
-
-int get_coreboot_info(struct sysinfo_t *info);
-
-#endif
diff --git a/arch/x86/include/asm/arch-coreboot/timestamp.h b/arch/x86/include/asm/arch-coreboot/timestamp.h
index 85d42c0..531526b 100644
--- a/arch/x86/include/asm/arch-coreboot/timestamp.h
+++ b/arch/x86/include/asm/arch-coreboot/timestamp.h
@@ -8,30 +8,7 @@
#ifndef __COREBOOT_TIMESTAMP_H__
#define __COREBOOT_TIMESTAMP_H__
-enum timestamp_id {
- /* coreboot specific timestamp IDs */
- TS_START_ROMSTAGE = 1,
- TS_BEFORE_INITRAM = 2,
- TS_AFTER_INITRAM = 3,
- TS_END_ROMSTAGE = 4,
- TS_START_COPYRAM = 8,
- TS_END_COPYRAM = 9,
- TS_START_RAMSTAGE = 10,
- TS_DEVICE_ENUMERATE = 30,
- TS_DEVICE_CONFIGURE = 40,
- TS_DEVICE_ENABLE = 50,
- TS_DEVICE_INITIALIZE = 60,
- TS_DEVICE_DONE = 70,
- TS_CBMEM_POST = 75,
- TS_WRITE_TABLES = 80,
- TS_LOAD_PAYLOAD = 90,
- TS_ACPI_WAKE_JUMP = 98,
- TS_SELFBOOT_JUMP = 99,
-
- /* U-Boot entry IDs start at 1000 */
- TS_U_BOOT_INITTED = 1000, /* This is where u-boot starts */
- TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel. */
-};
+#include <asm/cb_sysinfo.h>
void timestamp_init(void);
void timestamp_add(enum timestamp_id id, uint64_t ts_time);
diff --git a/arch/x86/include/asm/cb_sysinfo.h b/arch/x86/include/asm/cb_sysinfo.h
new file mode 100644
index 0000000..675eef6
--- /dev/null
+++ b/arch/x86/include/asm/cb_sysinfo.h
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _COREBOOT_SYSINFO_H
+#define _COREBOOT_SYSINFO_H
+
+#include <asm/coreboot_tables.h>
+
+/* Maximum number of memory range definitions */
+#define SYSINFO_MAX_MEM_RANGES 32
+/* Allow a maximum of 8 GPIOs */
+#define SYSINFO_MAX_GPIOS 8
+/* Up to 10 MAC addresses */
+#define SYSINFO_MAX_MACS 10
+
+/**
+ * struct sysinfo_t - Information passed to U-Boot from coreboot
+ *
+ * Coreboot passes on a lot of information using a list of individual data
+ * structures identified by a numeric tag. These are parsed in U-Boot to produce
+ * this struct. Some of the pointers here point back to the tagged data
+ * structure, since it is assumed to remain around while U-Boot is running.
+ *
+ * The 'cbsysinfo' command can display this information.
+ *
+ * @cpu_khz: CPU frequence in KHz (e.g. 1100000)
+ * @serial: Pointer to the serial information, NULL if none
+ * @ser_ioport: Not actually provided by a tag and not used on modern hardware,
+ * which typicaally uses a memory-mapped port
+ * @ser_base: Not used at all, but present to match up with the coreboot data
+ * structure
+ * @n_memranges: Number of memory ranges
+ * @memrange: List of memory ranges:
+ * @base: Base address of range
+ * @size: Size of range in bytes
+ * @type: Type of range (CB_MEM_RAM, etc.)
+ * @option_table: Provides a pointer to the CMOS RAM options table, which
+ * indicates which options are available. The header is followed by a list
+ * of struct cb_cmos_entries records, so that an option can be found from
+ * its name. This is not used in U-Boot. NULL if not present
+ * @cmos_range_start: Start bit of the CMOS checksum range (in fact this must
+ * be a multiple of 8)
+ * @cmos_range_end: End bit of the CMOS checksum range (multiple of 8). This is
+ * the inclusive end.
+ * @cmos_checksum_location: Location of checksum, multiplied by 8. This is the
+ * byte offset into the CMOS RAM of the first checksum byte. The second one
+ * follows immediately. The checksum is a simple 16-bit sum of all the
+ * bytes from offset cmos_range_start / 8 to cmos_range_end / 8, inclusive,
+ * in big-endian format (so sum >> 8 is stored in the first byte).
+ * @vbnv_start: Start offset of CMOS RAM used for Chromium OS verified boot
+ * (typically 0x34)
+ * @vbnv_size: Number of bytes used by Chromium OS verified boot (typically
+ * 0x10)
+ * @extra_version: Extra version information, typically ""
+ * @build: Build date, e.g. "Wed Nov 18 02:51:58 UTC 2020"
+ * @compile_time: Compilation time, e.g. "02:51:58"
+ * @compile_by: Who compiled coreboot (never set?)
+ * @compile_host: Name of the machine that compiled coreboot (never set?)
+ * @compile_domain: Domain name of the machine that compiled coreboot (never
+ * set?)
+ * @compiler: Name of the compiler used to build coreboot (never set?)
+ * @linker: Name of the linker used to build coreboot (never set?)
+ * @assembler: Name of the assembler used to build coreboot (never set?)
+ * @cb_version: Coreboot version string, e.g. v1.9308_26_0.0.22-2599-g232f22c75d
+ * @framebuffer: Address of framebuffer tag, or NULL if none. See
+ * struct cb_framebuffer for the definition
+ * @num_gpios: Number of verified-boot GPIOs
+ * @gpios: List of GPIOs:
+ * @port: GPIO number, or 0xffffffff if not a GPIO
+ * @polarity: CB_GPIO_ACTIVE_LOW or CB_GPIO_ACTIVE_HIGH
+ * @value: Value of GPIO (0 or 1)
+ * @name: Name of GPIO
+ *
+ * A typical list is:
+ * id: port polarity val name
+ * 0: - active-high 1 write protect
+ * 1: - active-high 0 recovery
+ * 2: - active-high 1 lid
+ * 3: - active-high 0 power
+ * 4: - active-high 0 oprom
+ * 5: 29 active-high 0 EC in RW
+ *
+ * @num_macs: Number of MAC addresses
+ * @macs: List of MAC addresses
+ * @serialno: Serial number, or NULL (never set?)
+ * @mbtable: Address of the multiboot table, or NULL. This is a
+ * struct multiboot_header, not used in U-Boot
+ * @header: Address of header, if there is a CB_TAG_FORWARD, else NULL
+ * @mainboard: Pointer to mainboard info or NULL. Typically the vendor is
+ * "Google" and the part number is ""
+ * @vboot_handoff: Pointer to Chromium OS verified boot hand-off information.
+ * This is struct vboot_handoff, providing access to internal information
+ * generated by coreboot when this is being used
+ * @vboot_handoff_size: Size of hand-off information (typically 0xc0c)
+ * @vdat_addr: Pointer to Chromium OS verified boot data, which uses
+ * struct chromeos_acpi. It sits in the Intel Global NVS struct, after the
+ * first 0x100 bytes
+ * @vdat_size: Size of this data, typically 0xf00
+ * @smbios_start: Address of SMBIOS tables
+ * @smbios_size: Size of SMBIOS tables (e.g. 0x800)
+ * @x86_rom_var_mtrr_index: MTRR number used for ROM caching. Not used in U-Boot
+ * @tstamp_table: Pointer to timestamp_table, struct timestamp_table
+ * @cbmem_cons: Pointer to the console dump, struct cbmem_console. This provides
+ * access to the console output generated by coreboot, typically about 64KB
+ * and mostly PCI enumeration info
+ * @mrc_cache: Pointer to memory-reference-code cache, typically NULL
+ * acpi_gnvs: @Pointer to Intel Global NVS struct, see struct acpi_global_nvs
+ * @board_id: Board ID indicating the board variant, typically 0xffffffff
+ * @ram_code: RAM code indicating the SDRAM type, typically 0xffffffff
+ * @wifi_calibration: WiFi calibration info, NULL if none
+ * @ramoops_buffer: Address of kernel Ramoops buffer
+ * @ramoops_buffer_size: Sizeof of Ramoops buffer, typically 1MB
+ * @spi_flash: Information about SPI flash:
+ * @size: Size in bytes, e.g. 16MB
+ * @sector_size; Sector size of flash device, e.g. 4KB
+ * @erase_cmd: Command used to erase flash, or 0 if not used
+ * @fmap_offset: SPI-flash offset of the flash map (FMAP) table. This has a
+ * __FMAP__ header. It provides information about the different top-level
+ * sections in the SPI flash, e.g. 0x204000
+ * @cbfs_offset: SPI-flash offset of the Coreboot Filesystem (CBFS) used for
+ * read-only data, e.g. 0x205000. This is typically called 'COREBOOT' in
+ * the flash map. It holds various coreboot binaries as well as
+ * video-configuration files and graphics data for the Chromium OS
+ * verified boot user interface.
+ * @cbfs_size: Size of CBFS, e.g. 0x17b000
+ * @boot_media_size; Size of boot media (i.e. SPI flash), e.g. 16MB
+ * @mtc_start; Start of MTC region (Nvidia private data), 0 if not used. See
+ * https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/chromeos-2013.04/src/soc/nvidia/tegra210/mtc.c
+ * @mtc_size: Size of MTC region
+ * @chromeos_vpd: Chromium OS Vital Product Data region, typically NULL, meaning
+ * not used
+ */
+struct sysinfo_t {
+ unsigned int cpu_khz;
+ struct cb_serial *serial;
+ unsigned short ser_ioport;
+ unsigned long ser_base; // for mmapped serial
+
+ int n_memranges;
+
+ struct memrange {
+ unsigned long long base;
+ unsigned long long size;
+ unsigned int type;
+ } memrange[SYSINFO_MAX_MEM_RANGES];
+
+ struct cb_cmos_option_table *option_table;
+ u32 cmos_range_start;
+ u32 cmos_range_end;
+ u32 cmos_checksum_location;
+ u32 vbnv_start;
+ u32 vbnv_size;
+
+ char *version;
+ char *extra_version;
+ char *build;
+ char *compile_time;
+ char *compile_by;
+ char *compile_host;
+ char *compile_domain;
+ char *compiler;
+ char *linker;
+ char *assembler;
+
+ char *cb_version;
+
+ struct cb_framebuffer *framebuffer;
+
+ int num_gpios;
+ struct cb_gpio gpios[SYSINFO_MAX_GPIOS];
+ int num_macs;
+ struct mac_address macs[SYSINFO_MAX_MACS];
+ char *serialno;
+
+ unsigned long *mbtable; /** Pointer to the multiboot table */
+
+ struct cb_header *header;
+ struct cb_mainboard *mainboard;
+
+ void *vboot_handoff;
+ u32 vboot_handoff_size;
+ void *vdat_addr;
+ u32 vdat_size;
+ u64 smbios_start;
+ u32 smbios_size;
+
+ int x86_rom_var_mtrr_index;
+
+ void *tstamp_table;
+ void *cbmem_cons;
+ void *mrc_cache;
+ void *acpi_gnvs;
+ u32 board_id;
+ u32 ram_code;
+ void *wifi_calibration;
+ u64 ramoops_buffer;
+ u32 ramoops_buffer_size;
+ struct {
+ u32 size;
+ u32 sector_size;
+ u32 erase_cmd;
+ } spi_flash;
+ u64 fmap_offset;
+ u64 cbfs_offset;
+ u64 cbfs_size;
+ u64 boot_media_size;
+ u64 mtc_start;
+ u32 mtc_size;
+ void *chromeos_vpd;
+};
+
+extern struct sysinfo_t lib_sysinfo;
+
+int get_coreboot_info(struct sysinfo_t *info);
+
+#endif
diff --git a/arch/x86/include/asm/coreboot_tables.h b/arch/x86/include/asm/coreboot_tables.h
index 7e15767..a74654b 100644
--- a/arch/x86/include/asm/coreboot_tables.h
+++ b/arch/x86/include/asm/coreboot_tables.h
@@ -8,6 +8,106 @@
#ifndef _COREBOOT_TABLES_H
#define _COREBOOT_TABLES_H
+struct timestamp_entry {
+ u32 entry_id;
+ u64 entry_stamp;
+} __packed;
+
+struct timestamp_table {
+ u64 base_time;
+ u16 max_entries;
+ u16 tick_freq_mhz;
+ u32 num_entries;
+ struct timestamp_entry entries[0]; /* Variable number of entries */
+} __packed;
+
+enum timestamp_id {
+ /* coreboot-specific timestamp IDs */
+ TS_START_ROMSTAGE = 1,
+ TS_BEFORE_INITRAM = 2,
+ TS_AFTER_INITRAM = 3,
+ TS_END_ROMSTAGE = 4,
+ TS_START_VBOOT = 5,
+ TS_END_VBOOT = 6,
+ TS_START_COPYRAM = 8,
+ TS_END_COPYRAM = 9,
+ TS_START_RAMSTAGE = 10,
+ TS_START_BOOTBLOCK = 11,
+ TS_END_BOOTBLOCK = 12,
+ TS_START_COPYROM = 13,
+ TS_END_COPYROM = 14,
+ TS_START_ULZMA = 15,
+ TS_END_ULZMA = 16,
+ TS_START_ULZ4F = 17,
+ TS_END_ULZ4F = 18,
+ TS_DEVICE_ENUMERATE = 30,
+ TS_DEVICE_CONFIGURE = 40,
+ TS_DEVICE_ENABLE = 50,
+ TS_DEVICE_INITIALIZE = 60,
+ TS_DEVICE_DONE = 70,
+ TS_CBMEM_POST = 75,
+ TS_WRITE_TABLES = 80,
+ TS_FINALIZE_CHIPS = 85,
+ TS_LOAD_PAYLOAD = 90,
+ TS_ACPI_WAKE_JUMP = 98,
+ TS_SELFBOOT_JUMP = 99,
+
+ /* 500+ reserved for vendorcode extensions (500-600: google/chromeos) */
+ TS_START_COPYVER = 501,
+ TS_END_COPYVER = 502,
+ TS_START_TPMINIT = 503,
+ TS_END_TPMINIT = 504,
+ TS_START_VERIFY_SLOT = 505,
+ TS_END_VERIFY_SLOT = 506,
+ TS_START_HASH_BODY = 507,
+ TS_DONE_LOADING = 508,
+ TS_DONE_HASHING = 509,
+ TS_END_HASH_BODY = 510,
+ TS_START_COPYVPD = 550,
+ TS_END_COPYVPD_RO = 551,
+ TS_END_COPYVPD_RW = 552,
+
+ /* 940-950 reserved for vendorcode extensions (940-950: Intel ME) */
+ TS_ME_INFORM_DRAM_WAIT = 940,
+ TS_ME_INFORM_DRAM_DONE = 941,
+
+ /* 950+ reserved for vendorcode extensions (950-999: intel/fsp) */
+ TS_FSP_MEMORY_INIT_START = 950,
+ TS_FSP_MEMORY_INIT_END = 951,
+ TS_FSP_TEMP_RAM_EXIT_START = 952,
+ TS_FSP_TEMP_RAM_EXIT_END = 953,
+ TS_FSP_SILICON_INIT_START = 954,
+ TS_FSP_SILICON_INIT_END = 955,
+ TS_FSP_BEFORE_ENUMERATE = 956,
+ TS_FSP_AFTER_ENUMERATE = 957,
+ TS_FSP_BEFORE_FINALIZE = 958,
+ TS_FSP_AFTER_FINALIZE = 959,
+ TS_FSP_BEFORE_END_OF_FIRMWARE = 960,
+ TS_FSP_AFTER_END_OF_FIRMWARE = 961,
+
+ /* 1000+ reserved for payloads (1000-1200: ChromeOS depthcharge) */
+
+ /* U-Boot entry IDs start at 1000 */
+ TS_U_BOOT_INITTED = 1000, /* This is where U-Boot starts */
+
+ TS_RO_PARAMS_INIT = 1001,
+ TS_RO_VB_INIT = 1002,
+ TS_RO_VB_SELECT_FIRMWARE = 1003,
+ TS_RO_VB_SELECT_AND_LOAD_KERNEL = 1004,
+
+ TS_RW_VB_SELECT_AND_LOAD_KERNEL = 1010,
+
+ TS_VB_SELECT_AND_LOAD_KERNEL = 1020,
+ TS_VB_EC_VBOOT_DONE = 1030,
+ TS_VB_STORAGE_INIT_DONE = 1040,
+ TS_VB_READ_KERNEL_DONE = 1050,
+ TS_VB_VBOOT_DONE = 1100,
+
+ TS_START_KERNEL = 1101,
+ TS_KERNEL_DECOMPRESSION = 1102,
+ TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel */
+};
+
struct memory_area;
struct cbuint64 {
@@ -162,13 +262,14 @@
};
#define CB_TAG_GPIO 0x0013
-#define GPIO_MAX_NAME_LENGTH 16
-
+#define CB_GPIO_ACTIVE_LOW 0
+#define CB_GPIO_ACTIVE_HIGH 1
+#define CB_GPIO_MAX_NAME_LENGTH 16
struct cb_gpio {
u32 port;
u32 polarity;
u32 value;
- u8 name[GPIO_MAX_NAME_LENGTH];
+ u8 name[CB_GPIO_MAX_NAME_LENGTH];
};
struct cb_gpios {
@@ -181,61 +282,158 @@
#define CB_TAG_FDT 0x0014
struct cb_fdt {
- uint32_t tag;
- uint32_t size; /* size of the entire entry */
+ u32 tag;
+ u32 size; /* size of the entire entry */
/* the actual FDT gets placed here */
};
#define CB_TAG_VDAT 0x0015
struct cb_vdat {
- uint32_t tag;
- uint32_t size; /* size of the entire entry */
+ u32 tag;
+ u32 size; /* size of the entire entry */
void *vdat_addr;
- uint32_t vdat_size;
+ u32 vdat_size;
};
#define CB_TAG_TIMESTAMPS 0x0016
#define CB_TAG_CBMEM_CONSOLE 0x0017
+
+struct cbmem_console {
+ u32 size;
+ u32 cursor;
+ char body[0];
+} __packed;
+
#define CB_TAG_MRC_CACHE 0x0018
struct cb_cbmem_tab {
- uint32_t tag;
- uint32_t size;
- void *cbmem_tab;
+ u32 tag;
+ u32 size;
+ u64 cbmem_tab;
};
#define CB_TAG_VBNV 0x0019
struct cb_vbnv {
- uint32_t tag;
- uint32_t size;
- uint32_t vbnv_start;
- uint32_t vbnv_size;
+ u32 tag;
+ u32 size;
+ u32 vbnv_start;
+ u32 vbnv_size;
+};
+
+#define CB_TAG_VBOOT_HANDOFF 0x0020
+
+#define CB_TAG_X86_ROM_MTRR 0x0021
+struct cb_x86_rom_mtrr {
+ u32 tag;
+ u32 size;
+ /*
+ * The variable range MTRR index covering the ROM. If one wants to
+ * enable caching the ROM, the variable MTRR needs to be set to
+ * write-protect. To disable the caching after enabling set the
+ * type to uncacheable
+ */
+ u32 index;
+};
+
+#define CB_TAG_DMA 0x0022
+#define CB_TAG_RAM_OOPS 0x0023
+#define CB_TAG_ACPI_GNVS 0x0024
+
+#define CB_TAG_BOARD_ID 0x0025
+struct cb_board_id {
+ u32 tag;
+ u32 size;
+ /* Board ID as retrieved from the board revision GPIOs. */
+ u32 board_id;
+};
+
+#define CB_TAG_MAC_ADDRS 0x0026
+struct mac_address {
+ u8 mac_addr[6];
+ u8 pad[2]; /* Pad it to 8 bytes to keep it simple. */
+};
+
+struct cb_macs {
+ u32 tag;
+ u32 size;
+ u32 count;
+ struct mac_address mac_addrs[0];
+};
+
+#define CB_TAG_WIFI_CALIBRATION 0x0027
+
+#define CB_TAG_RAM_CODE 0x0028
+struct cb_ram_code {
+ u32 tag;
+ u32 size;
+ u32 ram_code;
+};
+
+#define CB_TAG_SPI_FLASH 0x0029
+struct cb_spi_flash {
+ u32 tag;
+ u32 size;
+ u32 flash_size;
+ u32 sector_size;
+ u32 erase_cmd;
};
-#define CB_TAG_CBMEM_ENTRY 0x0031
-#define CBMEM_ID_SMBIOS 0x534d4254
+#define CB_TAG_MTC 0x002b
+#define CB_TAG_VPD 0x002c
+struct lb_range {
+ u32 tag;
+ u32 size;
+ u64 range_start;
+ u32 range_size;
+};
+
+#define CB_TAG_BOOT_MEDIA_PARAMS 0x0030
+struct cb_boot_media_params {
+ u32 tag;
+ u32 size;
+ /* offsets are relative to start of boot media */
+ u64 fmap_offset;
+ u64 cbfs_offset;
+ u64 cbfs_size;
+ u64 boot_media_size;
+};
+
+#define CB_TAG_CBMEM_ENTRY 0x0031
+#define CBMEM_ID_SMBIOS 0x534d4254
struct cb_cbmem_entry {
- uint32_t tag;
- uint32_t size;
- uint64_t address;
- uint32_t entry_size;
- uint32_t id;
+ u32 tag;
+ u32 size;
+ u64 address;
+ u32 entry_size;
+ u32 id;
+};
+
+#define CB_TAG_TSC_INFO 0x0032
+struct cb_tsc_info {
+ u32 tag;
+ u32 size;
+
+ u32 freq_khz;
};
+#define CB_TAG_SERIALNO 0x002a
+#define CB_MAX_SERIALNO_LENGTH 32
+
#define CB_TAG_CMOS_OPTION_TABLE 0x00c8
struct cb_cmos_option_table {
u32 tag;
u32 size;
u32 header_length;
+ /* entries follow after this header */
};
#define CB_TAG_OPTION 0x00c9
-#define CMOS_MAX_NAME_LENGTH 32
+#define CB_CMOS_MAX_NAME_LENGTH 32
struct cb_cmos_entries {
u32 tag;
@@ -244,34 +442,33 @@
u32 length;
u32 config;
u32 config_id;
- u8 name[CMOS_MAX_NAME_LENGTH];
+ u8 name[CB_CMOS_MAX_NAME_LENGTH];
};
#define CB_TAG_OPTION_ENUM 0x00ca
-#define CMOS_MAX_TEXT_LENGTH 32
-
+#define CB_CMOS_MAX_TEXT_LENGTH 32
struct cb_cmos_enums {
u32 tag;
u32 size;
u32 config_id;
u32 value;
- u8 text[CMOS_MAX_TEXT_LENGTH];
+ u8 text[CB_CMOS_MAX_TEXT_LENGTH];
};
#define CB_TAG_OPTION_DEFAULTS 0x00cb
-#define CMOS_IMAGE_BUFFER_SIZE 128
+#define CB_CMOS_IMAGE_BUFFER_SIZE 128
struct cb_cmos_defaults {
u32 tag;
u32 size;
u32 name_length;
- u8 name[CMOS_MAX_NAME_LENGTH];
- u8 default_set[CMOS_IMAGE_BUFFER_SIZE];
+ u8 name[CB_CMOS_MAX_NAME_LENGTH];
+ u8 default_set[CB_CMOS_IMAGE_BUFFER_SIZE];
};
#define CB_TAG_OPTION_CHECKSUM 0x00cc
-#define CHECKSUM_NONE 0
-#define CHECKSUM_PCBIOS 1
+#define CB_CHECKSUM_NONE 0
+#define CB_CHECKSUM_PCBIOS 1
struct cb_cmos_checksum {
u32 tag;
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index a66c0d2..850a0a7 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -22,9 +22,23 @@
#define ISA_START_ADDRESS 0xa0000
#define ISA_END_ADDRESS 0x100000
-/* Implementation defined function to install an e820 map */
+/* Implementation-defined function to install an e820 map */
unsigned int install_e820_map(unsigned int max_entries,
struct e820_entry *);
+
+/**
+ * cb_install_e820_map() - Install e820 map provided by coreboot sysinfo
+ *
+ * This should be used when booting from coreboot, since in that case the
+ * memory areas are provided by coreboot in its sysinfo.
+ *
+ * @max_entries: Maximum number of entries to write
+ * @entries: Place to put entires
+ * @return number of entries written
+ */
+unsigned int cb_install_e820_map(unsigned int max_entries,
+ struct e820_entry *entries);
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_X86_E820_H */
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 1bcbb49..65d9b3b 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -15,6 +15,7 @@
obj-$(CONFIG_CMD_BOOTM) += bootm.o
endif
obj-y += cmd_boot.o
+obj-$(CONFIG_$(SPL_)COREBOOT_SYSINFO) += coreboot/
obj-$(CONFIG_SEABIOS) += coreboot_table.o
obj-y += early_cmos.o
obj-y += e820.o
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c
index aa5f0bf..733dd71 100644
--- a/arch/x86/lib/bootm.c
+++ b/arch/x86/lib/bootm.c
@@ -36,7 +36,7 @@
printf("\nStarting kernel ...\n\n");
#ifdef CONFIG_SYS_COREBOOT
- timestamp_add_now(TS_U_BOOT_START_KERNEL);
+ timestamp_add_now(TS_START_KERNEL);
#endif
bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
#if CONFIG_IS_ENABLED(BOOTSTAGE_REPORT)
diff --git a/arch/x86/lib/coreboot/Makefile b/arch/x86/lib/coreboot/Makefile
new file mode 100644
index 0000000..cb0ae1d
--- /dev/null
+++ b/arch/x86/lib/coreboot/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2021 Google LLC
+#
+
+obj-y += cb_sysinfo.o
+obj-y += cb_support.o
diff --git a/arch/x86/lib/coreboot/cb_support.c b/arch/x86/lib/coreboot/cb_support.c
new file mode 100644
index 0000000..ebb45cd
--- /dev/null
+++ b/arch/x86/lib/coreboot/cb_support.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Support for booting from coreboot
+ *
+ * Copyright 2021 Google LLC
+ */
+
+#include <common.h>
+#include <asm/cb_sysinfo.h>
+#include <asm/e820.h>
+
+unsigned int cb_install_e820_map(unsigned int max_entries,
+ struct e820_entry *entries)
+{
+ unsigned int num_entries;
+ int i;
+
+ num_entries = min((unsigned int)lib_sysinfo.n_memranges, max_entries);
+ if (num_entries < lib_sysinfo.n_memranges) {
+ printf("Warning: Limiting e820 map to %d entries\n",
+ num_entries);
+ }
+ for (i = 0; i < num_entries; i++) {
+ struct memrange *memrange = &lib_sysinfo.memrange[i];
+
+ entries[i].addr = memrange->base;
+ entries[i].size = memrange->size;
+
+ /*
+ * coreboot has some extensions (type 6 & 16) to the E820 types.
+ * When we detect this, mark it as E820_RESERVED.
+ */
+ if (memrange->type == CB_MEM_VENDOR_RSVD ||
+ memrange->type == CB_MEM_TABLE)
+ entries[i].type = E820_RESERVED;
+ else
+ entries[i].type = memrange->type;
+ }
+
+ return num_entries;
+}
diff --git a/arch/x86/lib/coreboot/cb_sysinfo.c b/arch/x86/lib/coreboot/cb_sysinfo.c
new file mode 100644
index 0000000..e2c65bf
--- /dev/null
+++ b/arch/x86/lib/coreboot/cb_sysinfo.c
@@ -0,0 +1,468 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2009 coresystems GmbH
+ */
+
+#include <common.h>
+#include <asm/cb_sysinfo.h>
+#include <init.h>
+#include <mapmem.h>
+#include <net.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This needs to be in the .data section so that it's copied over during
+ * relocation. By default it's put in the .bss section which is simply filled
+ * with zeroes when transitioning from "ROM", which is really RAM, to other
+ * RAM.
+ */
+struct sysinfo_t lib_sysinfo __attribute__((section(".data")));
+
+/*
+ * Some of this is x86 specific, and the rest of it is generic. Right now,
+ * since we only support x86, we'll avoid trying to make lots of infrastructure
+ * we don't need. If in the future, we want to use coreboot on some other
+ * architecture, then take out the generic parsing code and move it elsewhere.
+ */
+
+/* === Parsing code === */
+/* This is the generic parsing code */
+
+static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info)
+{
+ struct cb_memory *mem = (struct cb_memory *)ptr;
+ int count = MEM_RANGE_COUNT(mem);
+ int i;
+
+ if (count > SYSINFO_MAX_MEM_RANGES)
+ count = SYSINFO_MAX_MEM_RANGES;
+
+ info->n_memranges = 0;
+
+ for (i = 0; i < count; i++) {
+ struct cb_memory_range *range =
+ (struct cb_memory_range *)MEM_RANGE_PTR(mem, i);
+
+ info->memrange[info->n_memranges].base =
+ UNPACK_CB64(range->start);
+
+ info->memrange[info->n_memranges].size =
+ UNPACK_CB64(range->size);
+
+ info->memrange[info->n_memranges].type = range->type;
+
+ info->n_memranges++;
+ }
+}
+
+static void cb_parse_serial(unsigned char *ptr, struct sysinfo_t *info)
+{
+ struct cb_serial *ser = (struct cb_serial *)ptr;
+
+ info->serial = ser;
+}
+
+static void cb_parse_vboot_handoff(unsigned char *ptr, struct sysinfo_t *info)
+{
+ struct lb_range *vbho = (struct lb_range *)ptr;
+
+ info->vboot_handoff = (void *)(uintptr_t)vbho->range_start;
+ info->vboot_handoff_size = vbho->range_size;
+}
+
+static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info)
+{
+ struct lb_range *vbnv = (struct lb_range *)ptr;
+
+ info->vbnv_start = vbnv->range_start;
+ info->vbnv_size = vbnv->range_size;
+}
+
+static void cb_parse_cbmem_entry(unsigned char *ptr, struct sysinfo_t *info)
+{
+ struct cb_cbmem_entry *entry = (struct cb_cbmem_entry *)ptr;
+
+ if (entry->id != CBMEM_ID_SMBIOS)
+ return;
+
+ info->smbios_start = entry->address;
+ info->smbios_size = entry->entry_size;
+}
+
+static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info)
+{
+ int i;
+ struct cb_gpios *gpios = (struct cb_gpios *)ptr;
+
+ info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ?
+ (gpios->count) : SYSINFO_MAX_GPIOS;
+
+ for (i = 0; i < info->num_gpios; i++)
+ info->gpios[i] = gpios->gpios[i];
+}
+
+static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info)
+{
+ struct lb_range *vdat = (struct lb_range *)ptr;
+
+ info->vdat_addr = map_sysmem(vdat->range_start, vdat->range_size);
+ info->vdat_size = vdat->range_size;
+}
+
+static void cb_parse_mac_addresses(unsigned char *ptr,
+ struct sysinfo_t *info)
+{
+ struct cb_macs *macs = (struct cb_macs *)ptr;
+ int i;
+
+ info->num_macs = (macs->count < ARRAY_SIZE(info->macs)) ?
+ macs->count : ARRAY_SIZE(info->macs);
+
+ for (i = 0; i < info->num_macs; i++)
+ info->macs[i] = macs->mac_addrs[i];
+}
+
+static void cb_parse_tstamp(void *ptr, struct sysinfo_t *info)
+{
+ struct cb_cbmem_tab *const cbmem = ptr;
+
+ info->tstamp_table = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_cbmem_cons(void *ptr, struct sysinfo_t *info)
+{
+ struct cb_cbmem_tab *const cbmem = ptr;
+
+ info->cbmem_cons = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_acpi_gnvs(unsigned char *ptr, struct sysinfo_t *info)
+{
+ struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
+
+ info->acpi_gnvs = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_board_id(unsigned char *ptr, struct sysinfo_t *info)
+{
+ struct cb_board_id *const cbbid = (struct cb_board_id *)ptr;
+
+ info->board_id = cbbid->board_id;
+}
+
+static void cb_parse_ram_code(unsigned char *ptr, struct sysinfo_t *info)
+{
+ struct cb_ram_code *const ram_code = (struct cb_ram_code *)ptr;
+
+ info->ram_code = ram_code->ram_code;
+}
+
+static void cb_parse_optiontable(void *ptr, struct sysinfo_t *info)
+{
+ /* ptr points to a coreboot table entry and is already virtual */
+ info->option_table = ptr;
+}
+
+static void cb_parse_checksum(void *ptr, struct sysinfo_t *info)
+{
+ struct cb_cmos_checksum *cmos_cksum = ptr;
+
+ info->cmos_range_start = cmos_cksum->range_start;
+ info->cmos_range_end = cmos_cksum->range_end;
+ info->cmos_checksum_location = cmos_cksum->location;
+}
+
+static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info)
+{
+ /* ptr points to a coreboot table entry and is already virtual */
+ info->framebuffer = ptr;
+}
+
+static void cb_parse_string(unsigned char *ptr, char **info)
+{
+ *info = (char *)((struct cb_string *)ptr)->string;
+}
+
+static void cb_parse_wifi_calibration(void *ptr, struct sysinfo_t *info)
+{
+ struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
+
+ info->wifi_calibration = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_ramoops(void *ptr, struct sysinfo_t *info)
+{
+ struct lb_range *ramoops = (struct lb_range *)ptr;
+
+ info->ramoops_buffer = ramoops->range_start;
+ info->ramoops_buffer_size = ramoops->range_size;
+}
+
+static void cb_parse_mtc(void *ptr, struct sysinfo_t *info)
+{
+ struct lb_range *mtc = (struct lb_range *)ptr;
+
+ info->mtc_start = mtc->range_start;
+ info->mtc_size = mtc->range_size;
+}
+
+static void cb_parse_spi_flash(void *ptr, struct sysinfo_t *info)
+{
+ struct cb_spi_flash *flash = (struct cb_spi_flash *)ptr;
+
+ info->spi_flash.size = flash->flash_size;
+ info->spi_flash.sector_size = flash->sector_size;
+ info->spi_flash.erase_cmd = flash->erase_cmd;
+}
+
+static void cb_parse_boot_media_params(unsigned char *ptr,
+ struct sysinfo_t *info)
+{
+ struct cb_boot_media_params *const bmp =
+ (struct cb_boot_media_params *)ptr;
+
+ info->fmap_offset = bmp->fmap_offset;
+ info->cbfs_offset = bmp->cbfs_offset;
+ info->cbfs_size = bmp->cbfs_size;
+ info->boot_media_size = bmp->boot_media_size;
+}
+
+static void cb_parse_vpd(void *ptr, struct sysinfo_t *info)
+{
+ struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
+
+ info->chromeos_vpd = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_tsc_info(void *ptr, struct sysinfo_t *info)
+{
+ const struct cb_tsc_info *tsc_info = ptr;
+
+ if (tsc_info->freq_khz == 0)
+ return;
+
+ /* Honor the TSC frequency passed to the payload */
+ info->cpu_khz = tsc_info->freq_khz;
+}
+
+static void cb_parse_x86_rom_var_mtrr(void *ptr, struct sysinfo_t *info)
+{
+ struct cb_x86_rom_mtrr *rom_mtrr = ptr;
+
+ info->x86_rom_var_mtrr_index = rom_mtrr->index;
+}
+
+static void cb_parse_mrc_cache(void *ptr, struct sysinfo_t *info)
+{
+ struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
+
+ info->mrc_cache = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+__weak void cb_parse_unhandled(u32 tag, unsigned char *ptr)
+{
+}
+
+static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
+{
+ unsigned char *ptr = addr;
+ struct cb_header *header;
+ int i;
+
+ header = (struct cb_header *)ptr;
+ if (!header->table_bytes)
+ return 0;
+
+ /* Make sure the checksums match */
+ if (!ip_checksum_ok(header, sizeof(*header)))
+ return -1;
+
+ if (compute_ip_checksum(ptr + sizeof(*header), header->table_bytes) !=
+ header->table_checksum)
+ return -1;
+
+ info->header = header;
+
+ /*
+ * Board straps represented by numerical values are small numbers.
+ * Preset them to an invalid value in case the firmware does not
+ * supply the info.
+ */
+ info->board_id = ~0;
+ info->ram_code = ~0;
+
+ /* Now, walk the tables */
+ ptr += header->header_bytes;
+
+ /* Inintialize some fields to sentinel values */
+ info->vbnv_start = info->vbnv_size = (uint32_t)(-1);
+
+ for (i = 0; i < header->table_entries; i++) {
+ struct cb_record *rec = (struct cb_record *)ptr;
+
+ /* We only care about a few tags here (maybe more later) */
+ switch (rec->tag) {
+ case CB_TAG_FORWARD:
+ return cb_parse_header(
+ (void *)(unsigned long)
+ ((struct cb_forward *)rec)->forward,
+ len, info);
+ continue;
+ case CB_TAG_MEMORY:
+ cb_parse_memory(ptr, info);
+ break;
+ case CB_TAG_SERIAL:
+ cb_parse_serial(ptr, info);
+ break;
+ case CB_TAG_VERSION:
+ cb_parse_string(ptr, &info->cb_version);
+ break;
+ case CB_TAG_EXTRA_VERSION:
+ cb_parse_string(ptr, &info->extra_version);
+ break;
+ case CB_TAG_BUILD:
+ cb_parse_string(ptr, &info->build);
+ break;
+ case CB_TAG_COMPILE_TIME:
+ cb_parse_string(ptr, &info->compile_time);
+ break;
+ case CB_TAG_COMPILE_BY:
+ cb_parse_string(ptr, &info->compile_by);
+ break;
+ case CB_TAG_COMPILE_HOST:
+ cb_parse_string(ptr, &info->compile_host);
+ break;
+ case CB_TAG_COMPILE_DOMAIN:
+ cb_parse_string(ptr, &info->compile_domain);
+ break;
+ case CB_TAG_COMPILER:
+ cb_parse_string(ptr, &info->compiler);
+ break;
+ case CB_TAG_LINKER:
+ cb_parse_string(ptr, &info->linker);
+ break;
+ case CB_TAG_ASSEMBLER:
+ cb_parse_string(ptr, &info->assembler);
+ break;
+ case CB_TAG_CMOS_OPTION_TABLE:
+ cb_parse_optiontable(ptr, info);
+ break;
+ case CB_TAG_OPTION_CHECKSUM:
+ cb_parse_checksum(ptr, info);
+ break;
+ /*
+ * FIXME we should warn on serial if coreboot set up a
+ * framebuffer buf the payload does not know about it.
+ */
+ case CB_TAG_FRAMEBUFFER:
+ cb_parse_framebuffer(ptr, info);
+ break;
+ case CB_TAG_MAINBOARD:
+ info->mainboard = (struct cb_mainboard *)ptr;
+ break;
+ case CB_TAG_GPIO:
+ cb_parse_gpios(ptr, info);
+ break;
+ case CB_TAG_VDAT:
+ cb_parse_vdat(ptr, info);
+ break;
+ case CB_TAG_VBNV:
+ cb_parse_vbnv(ptr, info);
+ break;
+ case CB_TAG_VBOOT_HANDOFF:
+ cb_parse_vboot_handoff(ptr, info);
+ break;
+ case CB_TAG_MAC_ADDRS:
+ cb_parse_mac_addresses(ptr, info);
+ break;
+ case CB_TAG_SERIALNO:
+ cb_parse_string(ptr, &info->serialno);
+ break;
+ case CB_TAG_TIMESTAMPS:
+ cb_parse_tstamp(ptr, info);
+ break;
+ case CB_TAG_CBMEM_CONSOLE:
+ cb_parse_cbmem_cons(ptr, info);
+ break;
+ case CB_TAG_ACPI_GNVS:
+ cb_parse_acpi_gnvs(ptr, info);
+ break;
+ case CB_TAG_CBMEM_ENTRY:
+ cb_parse_cbmem_entry(ptr, info);
+ break;
+ case CB_TAG_BOARD_ID:
+ cb_parse_board_id(ptr, info);
+ break;
+ case CB_TAG_RAM_CODE:
+ cb_parse_ram_code(ptr, info);
+ break;
+ case CB_TAG_WIFI_CALIBRATION:
+ cb_parse_wifi_calibration(ptr, info);
+ break;
+ case CB_TAG_RAM_OOPS:
+ cb_parse_ramoops(ptr, info);
+ break;
+ case CB_TAG_SPI_FLASH:
+ cb_parse_spi_flash(ptr, info);
+ break;
+ case CB_TAG_MTC:
+ cb_parse_mtc(ptr, info);
+ break;
+ case CB_TAG_BOOT_MEDIA_PARAMS:
+ cb_parse_boot_media_params(ptr, info);
+ break;
+ case CB_TAG_TSC_INFO:
+ cb_parse_tsc_info(ptr, info);
+ break;
+ case CB_TAG_VPD:
+ cb_parse_vpd(ptr, info);
+ break;
+ case CB_TAG_X86_ROM_MTRR:
+ cb_parse_x86_rom_var_mtrr(rec, info);
+ break;
+ case CB_TAG_MRC_CACHE:
+ cb_parse_mrc_cache(rec, info);
+ break;
+ default:
+ cb_parse_unhandled(rec->tag, ptr);
+ break;
+ }
+
+ ptr += rec->size;
+ }
+
+ return 1;
+}
+
+/* == Architecture specific == */
+/* This is the x86 specific stuff */
+
+int get_coreboot_info(struct sysinfo_t *info)
+{
+ long addr;
+ int ret;
+
+ addr = locate_coreboot_table();
+ if (addr < 0)
+ return addr;
+ ret = cb_parse_header((void *)addr, 0x1000, info);
+ if (!ret)
+ return -ENOENT;
+ gd->arch.coreboot_table = addr;
+ gd->flags |= GD_FLG_SKIP_LL_INIT;
+
+ return 0;
+}
+
+const struct sysinfo_t *cb_get_sysinfo(void)
+{
+ if (!ll_boot_init())
+ return &lib_sysinfo;
+
+ return NULL;
+}
diff --git a/arch/x86/lib/fsp/fsp_graphics.c b/arch/x86/lib/fsp/fsp_graphics.c
index cc909e0..02fd05c 100644
--- a/arch/x86/lib/fsp/fsp_graphics.c
+++ b/arch/x86/lib/fsp/fsp_graphics.c
@@ -87,7 +87,7 @@
int ret;
if (!ll_boot_init())
- return 0;
+ return -ENODEV;
printf("Video: ");
diff --git a/arch/x86/lib/fsp2/fsp_init.c b/arch/x86/lib/fsp2/fsp_init.c
index 85cae54..5afdce1 100644
--- a/arch/x86/lib/fsp2/fsp_init.c
+++ b/arch/x86/lib/fsp2/fsp_init.c
@@ -84,7 +84,8 @@
struct cbfs_priv *cbfs;
int ret;
- ret = cbfs_init_mem(map_base + cbfs_base, &cbfs);
+ ret = cbfs_init_mem(map_base + cbfs_base, CBFS_SIZE_UNKNOWN, true,
+ &cbfs);
if (ret)
return ret;
if (!ret) {
diff --git a/arch/x86/lib/fsp2/fsp_support.c b/arch/x86/lib/fsp2/fsp_support.c
index 503f97d..b2c7658 100644
--- a/arch/x86/lib/fsp2/fsp_support.c
+++ b/arch/x86/lib/fsp2/fsp_support.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <dm.h>
+#include <init.h>
#include <log.h>
#include <spi_flash.h>
#include <asm/fsp/fsp_support.h>
@@ -114,6 +115,9 @@
struct fsp_notify_params *params_ptr;
u32 status;
+ if (!ll_boot_init())
+ return 0;
+
if (!fsp_hdr)
fsp_hdr = gd->arch.fsp_s_hdr;
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index 066dc40..67401b9 100644
--- a/arch/x86/lib/init_helpers.c
+++ b/arch/x86/lib/init_helpers.c
@@ -18,6 +18,9 @@
IS_ENABLED(CONFIG_FSP_VERSION2);
int ret;
+ if (!ll_boot_init())
+ return 0;
+
do_mtrr &= !IS_ENABLED(CONFIG_FSP_VERSION1) &&
!IS_ENABLED(CONFIG_SYS_SLIMBOOTLOADER);
@@ -31,9 +34,6 @@
return ret;
}
- if (!ll_boot_init())
- return 0;
-
/* Initialise the CPU cache(s) */
return init_cache();
}
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c
index 1bae1f4..b18c1cd 100644
--- a/arch/x86/lib/spl.c
+++ b/arch/x86/lib/spl.c
@@ -96,7 +96,7 @@
}
#endif
preloader_console_init();
-#ifndef CONFIG_TPL
+#if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU)
ret = print_cpuinfo();
if (ret) {
debug("%s: print_cpuinfo() failed\n", __func__);
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
index 602788e..90fc8a4 100644
--- a/arch/x86/lib/zimage.c
+++ b/arch/x86/lib/zimage.c
@@ -18,6 +18,7 @@
#include <bootm.h>
#include <command.h>
#include <env.h>
+#include <init.h>
#include <irq_func.h>
#include <log.h>
#include <malloc.h>
@@ -28,6 +29,7 @@
#include <asm/byteorder.h>
#include <asm/bootm.h>
#include <asm/bootparam.h>
+#include <asm/global_data.h>
#ifdef CONFIG_SYS_COREBOOT
#include <asm/arch/timestamp.h>
#endif
@@ -35,6 +37,8 @@
#include <linux/ctype.h>
#include <linux/libfdt.h>
+DECLARE_GLOBAL_DATA_PTR;
+
/*
* Memory lay-out:
*
@@ -309,8 +313,13 @@
int bootproto = get_boot_protocol(hdr, false);
log_debug("Setup E820 entries\n");
- setup_base->e820_entries = install_e820_map(
- ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
+ if (ll_boot_init()) {
+ setup_base->e820_entries = install_e820_map(
+ ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
+ } else if (IS_ENABLED(CONFIG_COREBOOT_SYSINFO)) {
+ setup_base->e820_entries = cb_install_e820_map(
+ ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
+ }
if (bootproto == 0x0100) {
setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC;
diff --git a/board/coreboot/coreboot/coreboot.c b/board/coreboot/coreboot/coreboot.c
index 9aafb89..175d3ce 100644
--- a/board/coreboot/coreboot/coreboot.c
+++ b/board/coreboot/coreboot/coreboot.c
@@ -4,7 +4,7 @@
*/
#include <common.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
#include <asm/global_data.h>
#include <init.h>
#include <smbios.h>
diff --git a/board/google/chromebook_coral/coral.c b/board/google/chromebook_coral/coral.c
index f9fb3f1..3f9235c 100644
--- a/board/google/chromebook_coral/coral.c
+++ b/board/google/chromebook_coral/coral.c
@@ -3,9 +3,12 @@
* Copyright 2019 Google LLC
*/
+#define LOG_CATEGORY UCLASS_SYSINFO
+
#include <common.h>
#include <bloblist.h>
#include <command.h>
+#include <cros_ec.h>
#include <dm.h>
#include <log.h>
#include <sysinfo.h>
@@ -15,6 +18,7 @@
#include <asm/intel_gnvs.h>
#include <asm/intel_pinctrl.h>
#include <dm/acpi.h>
+#include <linux/delay.h>
#include "variant_gpio.h"
struct cros_gpio_info {
@@ -29,10 +33,125 @@
return 0;
}
+static int get_memconfig(struct udevice *dev)
+{
+ struct gpio_desc gpios[4];
+ int cfg;
+ int ret;
+
+ ret = gpio_request_list_by_name(dev, "memconfig-gpios", gpios,
+ ARRAY_SIZE(gpios),
+ GPIOD_IS_IN | GPIOD_PULL_UP);
+ if (ret < 0) {
+ log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret);
+ return ret;
+ }
+
+ /* Give the lines time to settle */
+ udelay(10);
+
+ ret = dm_gpio_get_values_as_int(gpios, ARRAY_SIZE(gpios));
+ if (ret < 0)
+ return log_msg_ret("get", ret);
+ cfg = ret;
+
+ ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios));
+ if (ret)
+ return log_msg_ret("free", ret);
+
+ return cfg;
+}
+
+/**
+ * get_skuconfig() - Get the SKU number either from pins or the EC
+ *
+ * Two options are supported:
+ * skuconfig-gpios - two pins in the device tree (tried first)
+ * EC - reading from the EC (backup)
+ *
+ * @dev: sysinfo device to use
+ * @return SKU ID, or -ve error if not found
+ */
+static int get_skuconfig(struct udevice *dev)
+{
+ struct gpio_desc gpios[2];
+ int cfg;
+ int ret;
+
+ ret = gpio_request_list_by_name(dev, "skuconfig-gpios", gpios,
+ ARRAY_SIZE(gpios),
+ GPIOD_IS_IN);
+ if (ret != ARRAY_SIZE(gpios)) {
+ struct udevice *cros_ec;
+
+ log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret);
+
+ /* Try the EC */
+ ret = uclass_first_device_err(UCLASS_CROS_EC, &cros_ec);
+ if (ret < 0) {
+ log_err("Cannot find EC for SKU details\n");
+ return log_msg_ret("sku", ret);
+ }
+ ret = cros_ec_get_sku_id(cros_ec);
+ if (ret < 0) {
+ log_err("Cannot read SKU details\n");
+ return log_msg_ret("sku", ret);
+ }
+
+ return ret;
+ }
+
+ ret = dm_gpio_get_values_as_int_base3(gpios, ARRAY_SIZE(gpios));
+ if (ret < 0)
+ return log_msg_ret("get", ret);
+ cfg = ret;
+
+ ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios));
+ if (ret)
+ return log_msg_ret("free", ret);
+
+ return cfg;
+}
+
-/* This function is needed if CONFIG_CMDLINE is not enabled */
-int board_run_command(const char *cmdline)
+static int coral_get_str(struct udevice *dev, int id, size_t size, char *val)
{
- printf("No command line\n");
+ int ret;
+
+ if (IS_ENABLED(CONFIG_SPL_BUILD))
+ return -ENOSYS;
+
+ switch (id) {
+ case SYSINFO_ID_SMBIOS_SYSTEM_VERSION:
+ case SYSINFO_ID_SMBIOS_BASEBOARD_VERSION: {
+ ret = get_skuconfig(dev);
+
+ if (ret < 0)
+ return ret;
+ if (size < 15)
+ return -ENOSPC;
+ sprintf(val, "rev%d", ret);
+ break;
+ }
+ case SYSINFO_ID_BOARD_MODEL: {
+ int mem_config, sku_config;
+ const char *model;
+
+ ret = get_memconfig(dev);
+ if (ret < 0)
+ log_warning("Unable to read memconfig (err=%d)\n", ret);
+ mem_config = ret;
+ ret = get_skuconfig(dev);
+ if (ret < 0)
+ log_warning("Unable to read skuconfig (err=%d)\n", ret);
+ sku_config = ret;
+ model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+ snprintf(val, size, "%s (memconfig %d, SKU %d)", model,
+ mem_config, sku_config);
+ break;
+ }
+ default:
+ return -ENOENT;
+ }
return 0;
}
@@ -45,12 +164,15 @@
int ret;
ret = gpio_request_by_name((struct udevice *)dev, prop, 0, &desc, 0);
- if (ret == -ENOTBLK)
+ if (ret == -ENOTBLK) {
info->gpio_num = CROS_GPIO_VIRTUAL;
- else if (ret)
+ log_debug("GPIO '%s' is virtual\n", prop);
+ } else if (ret) {
return log_msg_ret("gpio", ret);
- else
+ } else {
info->gpio_num = desc.offset;
+ dm_gpio_free((struct udevice *)dev, &desc);
+ }
info->linux_name = dev_read_string(desc.dev, "linux-name");
if (!info->linux_name)
return log_msg_ret("linux-name", -ENOENT);
@@ -63,6 +185,8 @@
}
info->flags = desc.flags & GPIOD_ACTIVE_LOW ? CROS_GPIO_ACTIVE_LOW :
CROS_GPIO_ACTIVE_HIGH;
+ if (!ret)
+ dm_gpio_free(desc.dev, &desc);
return 0;
}
@@ -81,11 +205,11 @@
ret = chromeos_get_gpio(dev, "write-protect-gpios", CROS_GPIO_WP,
&info[1]);
if (ret)
- return log_msg_ret("rec", ret);
+ return log_msg_ret("wp", ret);
ret = chromeos_get_gpio(dev, "phase-enforce-gpios", CROS_GPIO_PE,
&info[2]);
if (ret)
- return log_msg_ret("rec", ret);
+ return log_msg_ret("phase", ret);
acpigen_write_scope(ctx, "\\");
acpigen_write_name(ctx, "OIPG");
acpigen_write_package(ctx, count);
@@ -145,6 +269,7 @@
};
struct sysinfo_ops coral_sysinfo_ops = {
+ .get_str = coral_get_str,
};
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
diff --git a/board/google/chromebook_coral/variant_gpio.h b/board/google/chromebook_coral/variant_gpio.h
index f516d88..403e241 100644
--- a/board/google/chromebook_coral/variant_gpio.h
+++ b/board/google/chromebook_coral/variant_gpio.h
@@ -34,12 +34,6 @@
/* Determine if board is in final shipping mode. */
#define GPIO_SHIP_MODE GPIO_10
-/* Memory SKU GPIOs. */
-#define MEM_CONFIG3 GPIO_45
-#define MEM_CONFIG2 GPIO_38
-#define MEM_CONFIG1 GPIO_102
-#define MEM_CONFIG0 GPIO_101
-
/* DMIC_CONFIG_PIN: High for 1-DMIC and low for 4-DMIC's */
#define DMIC_CONFIG_PIN GPIO_17
diff --git a/cmd/Kconfig b/cmd/Kconfig
index e4bb1d4..8ab34f3 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2251,6 +2251,15 @@
for some PowerPC processors. For details please see the
documentation in doc/README.bedbug.
+config CMD_CBSYSINFO
+ bool "cbsysinfo"
+ depends on X86
+ default y if SYS_COREBOOT
+ help
+ This provides information about the coreboot sysinfo table stored in
+ memory by coreboot before jumping to U-Boot. It can be useful for
+ debugging the beaaviour of coreboot or U-Boot.
+
config CMD_DIAG
bool "diag - Board diagnostics"
help
diff --git a/cmd/acpi.c b/cmd/acpi.c
index 157261b..e5b9a17 100644
--- a/cmd/acpi.c
+++ b/cmd/acpi.c
@@ -187,10 +187,12 @@
return 0;
}
+#ifdef CONFIG_SYS_LONGHELP
static char acpi_help_text[] =
"list - list ACPI tables\n"
"acpi items [-d] - List/dump each piece of ACPI data from devices\n"
"acpi dump <name> - Dump ACPI table";
+#endif
U_BOOT_CMD_WITH_SUBCMDS(acpi, "ACPI tables", acpi_help_text,
U_BOOT_SUBCMD_MKENT(list, 1, 1, do_acpi_list),
diff --git a/cmd/bloblist.c b/cmd/bloblist.c
index 97b5734..21e7ff6 100644
--- a/cmd/bloblist.c
+++ b/cmd/bloblist.c
@@ -29,9 +29,11 @@
return 0;
}
+#ifdef CONFIG_SYS_LONGHELP
static char bloblist_help_text[] =
"info - show information about the bloblist\n"
"bloblist list - list blobs in the bloblist";
+#endif
U_BOOT_CMD_WITH_SUBCMDS(bloblist, "Bloblists", bloblist_help_text,
U_BOOT_SUBCMD_MKENT(info, 1, 1, do_bloblist_info),
diff --git a/cmd/host.c b/cmd/host.c
index 1d21f79..6aa3d91 100644
--- a/cmd/host.c
+++ b/cmd/host.c
@@ -41,17 +41,35 @@
static int do_host_bind(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
- if (argc < 2 || argc > 3)
- return CMD_RET_USAGE;
+ bool removable = false;
+ const char *dev_str;
+ char *file;
char *ep;
- char *dev_str = argv[1];
- char *file = argc >= 3 ? argv[2] : NULL;
- int dev = simple_strtoul(dev_str, &ep, 16);
+ int dev;
+
+ /* Skip 'bind' */
+ argc--;
+ argv++;
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (!strcmp(argv[0], "-r")) {
+ removable = true;
+ argc--;
+ argv++;
+ }
+
+ if (argc > 2)
+ return CMD_RET_USAGE;
+ dev_str = argv[0];
+ dev = simple_strtoul(dev_str, &ep, 16);
if (*ep) {
printf("** Bad device specification %s **\n", dev_str);
return CMD_RET_USAGE;
}
- return !!host_dev_bind(dev, file);
+ file = argc > 1 ? argv[1] : NULL;
+
+ return !!host_dev_bind(dev, file, removable);
}
static int do_host_info(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -146,7 +164,7 @@
U_BOOT_CMD_MKENT(ls, 3, 0, do_host_ls, "", ""),
U_BOOT_CMD_MKENT(save, 6, 0, do_host_save, "", ""),
U_BOOT_CMD_MKENT(size, 3, 0, do_host_size, "", ""),
- U_BOOT_CMD_MKENT(bind, 3, 0, do_host_bind, "", ""),
+ U_BOOT_CMD_MKENT(bind, 4, 0, do_host_bind, "", ""),
U_BOOT_CMD_MKENT(info, 3, 0, do_host_info, "", ""),
U_BOOT_CMD_MKENT(dev, 0, 1, do_host_dev, "", ""),
};
@@ -178,7 +196,8 @@
"host save hostfs - <addr> <filename> <bytes> [<offset>] - "
"save a file to host\n"
"host size hostfs - <filename> - determine size of file on host\n"
- "host bind <dev> [<filename>] - bind \"host\" device to file\n"
+ "host bind [-r] <dev> [<filename>] - bind \"host\" device to file\n"
+ " -r = mark as removable\n"
"host info [<dev>] - show device binding & info\n"
"host dev [<dev>] - Set or retrieve the current host device\n"
"host commands use the \"hostfs\" device. The \"host\" device is used\n"
diff --git a/cmd/version.c b/cmd/version.c
index 3686b87..685b458 100644
--- a/cmd/version.c
+++ b/cmd/version.c
@@ -9,7 +9,7 @@
#include <version.h>
#include <linux/compiler.h>
#ifdef CONFIG_SYS_COREBOOT
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
#endif
const char __weak version_string[] = U_BOOT_VERSION_STRING;
diff --git a/cmd/x86/Makefile b/cmd/x86/Makefile
index 144b1cf..5f82204 100644
--- a/cmd/x86/Makefile
+++ b/cmd/x86/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0+
+obj-$(CONFIG_CMD_CBSYSINFO) += cbsysinfo.o
obj-y += mtrr.o
obj-$(CONFIG_CMD_EXCEPTION) += exception.o
obj-$(CONFIG_USE_HOB) += hob.o
diff --git a/cmd/x86/cbsysinfo.c b/cmd/x86/cbsysinfo.c
new file mode 100644
index 0000000..a0db0ad
--- /dev/null
+++ b/cmd/x86/cbsysinfo.c
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <asm/cb_sysinfo.h>
+#include <command.h>
+#include <console.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void cbprompt(const char *name)
+{
+ for (; *name == '>'; name++)
+ puts(" ");
+ printf("%-12s: ", name);
+}
+
+static void print_dec(const char *name, int value)
+{
+ cbprompt(name);
+ printf(value > 9 ? "0d%d\n" : "%d\n", value);
+}
+
+static void print_hex(const char *name, int value)
+{
+ cbprompt(name);
+ printf("%x\n", value);
+}
+
+static void print_addr(const char *name, ulong value)
+{
+ cbprompt(name);
+ printf("%08lx\n", value);
+}
+
+static void print_addr64(const char *name, u64 value)
+{
+ cbprompt(name);
+ printf("%16llx\n", value);
+}
+
+static void print_ptr(const char *name, const void *value)
+{
+ cbprompt(name);
+ printf("%p\n", value);
+}
+
+static void print_str(const char *name, const char *value)
+{
+ if (value) {
+ cbprompt(name);
+ printf("%s\n", value);
+ }
+}
+
+static void print_idx(const char *name, uint idx, const u8 *strings)
+{
+ const char *ptr;
+
+ cbprompt(name);
+ ptr = (char *)strings + idx;
+ printf("%d: %s\n", idx, ptr ? ptr : "(unknown)");
+}
+
+static const char *const cb_mem_name[] = {
+ NULL,
+ "ram",
+ "reserved",
+ "acpi",
+ "nvs",
+ "unusable",
+ "vendor",
+};
+
+static const char *get_mem_name(int tag)
+{
+ if (tag >= CB_MEM_RAM && tag <= CB_MEM_VENDOR_RSVD)
+ return cb_mem_name[tag];
+
+ if (tag == CB_MEM_TABLE)
+ return "table";
+
+ return "(unknown)";
+}
+
+static const struct timestamp_id_to_name {
+ uint id;
+ const char *name;
+} timestamp_ids[] = {
+ /* Marker to report base_time */
+ { 0, "1st timestamp" },
+ { TS_START_ROMSTAGE, "start of romstage" },
+ { TS_BEFORE_INITRAM, "before ram initialization" },
+ { TS_AFTER_INITRAM, "after ram initialization" },
+ { TS_END_ROMSTAGE, "end of romstage" },
+ { TS_START_VBOOT, "start of verified boot" },
+ { TS_END_VBOOT, "end of verified boot" },
+ { TS_START_COPYRAM, "starting to load ramstage" },
+ { TS_END_COPYRAM, "finished loading ramstage" },
+ { TS_START_RAMSTAGE, "start of ramstage" },
+ { TS_START_BOOTBLOCK, "start of bootblock" },
+ { TS_END_BOOTBLOCK, "end of bootblock" },
+ { TS_START_COPYROM, "starting to load romstage" },
+ { TS_END_COPYROM, "finished loading romstage" },
+ { TS_START_ULZMA, "starting LZMA decompress (ignore for x86)" },
+ { TS_END_ULZMA, "finished LZMA decompress (ignore for x86)" },
+ { TS_START_ULZ4F, "starting LZ4 decompress (ignore for x86)" },
+ { TS_END_ULZ4F, "finished LZ4 decompress (ignore for x86)" },
+ { TS_DEVICE_ENUMERATE, "device enumeration" },
+ { TS_DEVICE_CONFIGURE, "device configuration" },
+ { TS_DEVICE_ENABLE, "device enable" },
+ { TS_DEVICE_INITIALIZE, "device initialization" },
+ { TS_DEVICE_DONE, "device setup done" },
+ { TS_CBMEM_POST, "cbmem post" },
+ { TS_WRITE_TABLES, "write tables" },
+ { TS_FINALIZE_CHIPS, "finalize chips" },
+ { TS_LOAD_PAYLOAD, "load payload" },
+ { TS_ACPI_WAKE_JUMP, "ACPI wake jump" },
+ { TS_SELFBOOT_JUMP, "selfboot jump" },
+
+ { TS_START_COPYVER, "starting to load verstage" },
+ { TS_END_COPYVER, "finished loading verstage" },
+ { TS_START_TPMINIT, "starting to initialize TPM" },
+ { TS_END_TPMINIT, "finished TPM initialization" },
+ { TS_START_VERIFY_SLOT, "starting to verify keyblock/preamble (RSA)" },
+ { TS_END_VERIFY_SLOT, "finished verifying keyblock/preamble (RSA)" },
+ { TS_START_HASH_BODY, "starting to verify body (load+SHA2+RSA) " },
+ { TS_DONE_LOADING, "finished loading body (ignore for x86)" },
+ { TS_DONE_HASHING, "finished calculating body hash (SHA2)" },
+ { TS_END_HASH_BODY, "finished verifying body signature (RSA)" },
+
+ { TS_START_COPYVPD, "starting to load Chrome OS VPD" },
+ { TS_END_COPYVPD_RO, "finished loading Chrome OS VPD (RO)" },
+ { TS_END_COPYVPD_RW, "finished loading Chrome OS VPD (RW)" },
+
+ { TS_U_BOOT_INITTED, "U-Boot start" },
+ { TS_RO_PARAMS_INIT, "RO parameter init" },
+ { TS_RO_VB_INIT, "RO vboot init" },
+ { TS_RO_VB_SELECT_FIRMWARE, "RO vboot select firmware" },
+ { TS_RO_VB_SELECT_AND_LOAD_KERNEL, "RO vboot select&load kernel" },
+ { TS_RW_VB_SELECT_AND_LOAD_KERNEL, "RW vboot select&load kernel" },
+ { TS_VB_SELECT_AND_LOAD_KERNEL, "vboot select&load kernel" },
+ { TS_VB_EC_VBOOT_DONE, "finished EC verification" },
+ { TS_VB_STORAGE_INIT_DONE, "finished storage device initialization" },
+ { TS_VB_READ_KERNEL_DONE, "finished reading kernel from disk" },
+ { TS_VB_VBOOT_DONE, "finished vboot kernel verification" },
+ { TS_KERNEL_DECOMPRESSION, "starting kernel decompression/relocation" },
+ { TS_START_KERNEL, "jumping to kernel" },
+ { TS_U_BOOT_START_KERNEL, "just before jump to kernel" },
+
+ /* Intel ME-related timestamps */
+ { TS_ME_INFORM_DRAM_WAIT, "waiting for ME acknowledgment of raminit"},
+ { TS_ME_INFORM_DRAM_DONE, "finished waiting for ME response"},
+
+ /* FSP-related timestamps */
+ { TS_FSP_MEMORY_INIT_START, "calling FspMemoryInit" },
+ { TS_FSP_MEMORY_INIT_END, "returning from FspMemoryInit" },
+ { TS_FSP_TEMP_RAM_EXIT_START, "calling FspTempRamExit" },
+ { TS_FSP_TEMP_RAM_EXIT_END, "returning from FspTempRamExit" },
+ { TS_FSP_SILICON_INIT_START, "calling FspSiliconInit" },
+ { TS_FSP_SILICON_INIT_END, "returning from FspSiliconInit" },
+ { TS_FSP_BEFORE_ENUMERATE, "calling FspNotify(AfterPciEnumeration)" },
+ { TS_FSP_AFTER_ENUMERATE,
+ "returning from FspNotify(AfterPciEnumeration)" },
+ { TS_FSP_BEFORE_FINALIZE, "calling FspNotify(ReadyToBoot)" },
+ { TS_FSP_AFTER_FINALIZE, "returning from FspNotify(ReadyToBoot)" },
+ { TS_FSP_BEFORE_END_OF_FIRMWARE, "calling FspNotify(EndOfFirmware)" },
+ { TS_FSP_AFTER_END_OF_FIRMWARE,
+ "returning from FspNotify(EndOfFirmware)" },
+};
+
+static const char *timestamp_name(uint32_t id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(timestamp_ids); i++) {
+ if (timestamp_ids[i].id == id)
+ return timestamp_ids[i].name;
+ }
+
+ return "<unknown>";
+}
+
+static void show_table(struct sysinfo_t *info, bool verbose)
+{
+ struct cb_serial *ser = info->serial;
+ int i;
+
+ printf("Coreboot table at %lx, decoded to %p",
+ gd->arch.coreboot_table, info);
+ if (info->header)
+ printf(", forwarded to %p\n", info->header);
+ printf("\n");
+
+ print_dec("CPU KHz", info->cpu_khz);
+
+ print_addr("Serial I/O port", info->ser_ioport);
+ print_addr(">base", info->ser_base);
+ print_ptr(">pointer", ser);
+ if (ser) {
+ print_hex(">type", ser->type);
+ print_addr(">base", ser->baseaddr);
+ print_dec(">baud", ser->baud);
+ print_hex(">baud", ser->regwidth);
+ print_dec(">input_hz", ser->input_hertz);
+ print_addr(">PCI addr", ser->uart_pci_addr);
+ }
+
+ print_dec("Mem ranges", info->n_memranges);
+ printf("%12s: %-11s || base || size\n", "id", "type");
+ for (i = 0; i < info->n_memranges; i++) {
+ const struct memrange *mr = &info->memrange[i];
+
+ printf("%12d: %02x:%-8s %016llx %016llx\n", i, mr->type,
+ get_mem_name(mr->type), mr->base, mr->size);
+ }
+ print_ptr("option_table", info->option_table);
+
+ print_hex("CMOS start", info->cmos_range_start);
+ if (info->cmos_range_start) {
+ print_hex(">CMOS end", info->cmos_range_end);
+ print_hex(">CMOS csum loc", info->cmos_checksum_location);
+ }
+
+ print_hex("VBNV start", info->vbnv_start);
+ print_hex("VBNV size", info->vbnv_size);
+
+ print_str("CB version", info->cb_version);
+ print_str(">Extra", info->extra_version);
+ print_str(">Build", info->build);
+ print_str(">Time", info->compile_time);
+ print_str(">By", info->compile_by);
+ print_str(">Host", info->compile_host);
+ print_str(">Domain", info->compile_domain);
+ print_str(">Compiler", info->compiler);
+ print_str(">Linker", info->linker);
+ print_str(">Assembler", info->assembler);
+
+ print_ptr("Framebuffer", info->framebuffer);
+ if (info->framebuffer) {
+ struct cb_framebuffer *fb = info->framebuffer;
+
+ print_addr64(">Phys addr", fb->physical_address);
+ print_dec(">X res", fb->x_resolution);
+ print_dec(">X res", fb->y_resolution);
+ print_hex(">Bytes / line", fb->bytes_per_line);
+ print_dec(">Bpp", fb->bits_per_pixel);
+ printf(" %-12s red %d/%d, green %d/%d, blue %d/%d, reserved %d/%d\n",
+ "pos/size", fb->red_mask_pos, fb->red_mask_size,
+ fb->green_mask_pos, fb->green_mask_size,
+ fb->blue_mask_pos, fb->blue_mask_size,
+ fb->reserved_mask_pos, fb->reserved_mask_size);
+ }
+
+ print_dec("GPIOs", info->num_gpios);
+ printf("%12s: %4s %12s %3s %s\n", "id", "port", "polarity", "val",
+ "name");
+ for (i = 0; i < info->num_gpios; i++) {
+ const struct cb_gpio *gpio = &info->gpios[i];
+ char portstr[4];
+
+ if (gpio->port == 0xffffffff)
+ strcpy(portstr, "-");
+ else
+ sprintf(portstr, "%x", gpio->port);
+ printf("%12d: %4s %12s %3d %s\n", i, portstr,
+ gpio->polarity == CB_GPIO_ACTIVE_LOW ? "active-low" :
+ "active-high", gpio->value, gpio->name);
+ }
+ print_dec("MACs", info->num_macs);
+ for (i = 0; i < info->num_macs; i++) {
+ const struct mac_address *mac = &info->macs[i];
+ int j;
+
+ printf("%12d: ", i);
+ for (j = 0; j < sizeof(mac->mac_addr); j++)
+ printf("%s%02x", j ? ":" : "", mac->mac_addr[j]);
+ printf("\n");
+ }
+ print_str(">Serial #", info->serialno);
+ print_ptr("Multiboot tab", info->mbtable);
+ print_ptr("CB header", info->header);
+ print_ptr("CB mainboard", info->mainboard);
+ if (info->mainboard) {
+ struct cb_mainboard *mb = info->mainboard;
+
+ print_idx(">vendor", mb->vendor_idx, mb->strings);
+ print_idx(">part_number", mb->part_number_idx, mb->strings);
+ }
+ print_ptr("vboot handoff", info->vboot_handoff);
+ print_hex(">size", info->vboot_handoff_size);
+ print_ptr(">vdat addr", info->vdat_addr);
+ print_hex(">size", info->vdat_size);
+
+ print_addr64("SMBIOS", info->smbios_start);
+ print_hex(">size", info->smbios_size);
+ print_hex("ROM MTRR", info->x86_rom_var_mtrr_index);
+
+ print_ptr("Tstamp table", info->tstamp_table);
+ if (verbose && info->tstamp_table) {
+ struct timestamp_table *ts = info->tstamp_table;
+
+ printf("%-12s", "Base_time");
+ print_grouped_ull(ts->base_time, 12);
+ printf("\n");
+ print_dec("Tick MHz", ts->tick_freq_mhz);
+ for (i = 0; i < ts->num_entries; i++) {
+ const struct timestamp_entry *tse;
+
+ tse = &ts->entries[i];
+ printf(" ");
+ print_grouped_ull(tse->entry_stamp, 12);
+ printf(" %s\n", timestamp_name(tse->entry_id));
+ }
+ }
+
+ print_ptr("CBmem cons", info->cbmem_cons);
+ if (info->cbmem_cons) {
+ struct cbmem_console *cons = info->cbmem_cons;
+ int i;
+
+ print_hex("Size", cons->size);
+ print_hex("Cursor", cons->cursor);
+ if (verbose) {
+ for (i = 0; i < cons->cursor; i++) {
+ int ch = cons->body[i];
+
+ putc(ch);
+
+ if (ch == '\n') {
+ /* check for ctrl-c to abort... */
+ if (ctrlc()) {
+ puts("Abort\n");
+ return;
+ }
+ printf(" ");
+ }
+ }
+ printf("\n");
+ }
+ }
+
+ print_ptr("MRC cache", info->mrc_cache);
+ print_ptr("ACPI GNVS", info->acpi_gnvs);
+ print_hex("Board ID", info->board_id);
+ print_hex("RAM code", info->ram_code);
+ print_ptr("WiFi calib", info->wifi_calibration);
+ print_addr64("Ramoops buff", info->ramoops_buffer);
+ print_hex(">size", info->ramoops_buffer_size);
+ print_hex("SF size", info->spi_flash.size);
+ print_hex("SF sector", info->spi_flash.sector_size);
+ print_hex("SF erase cmd", info->spi_flash.erase_cmd);
+
+ print_addr64("FMAP offset", info->fmap_offset);
+ print_addr64("CBFS offset", info->cbfs_offset);
+ print_addr64("CBFS size", info->cbfs_size);
+ print_addr64("Boot media size", info->boot_media_size);
+ print_addr64("MTC start", info->mtc_start);
+ print_hex("MTC size", info->mtc_size);
+
+ print_ptr("Chrome OS VPD", info->chromeos_vpd);
+}
+
+static int do_cbsysinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ bool verbose = false;
+
+ if (argc > 1) {
+ if (!strcmp("-v", argv[1]))
+ verbose = true;
+ else
+ return CMD_RET_USAGE;
+ }
+
+ if (!gd->arch.coreboot_table) {
+ printf("No coreboot sysinfo table found\n");
+ return CMD_RET_FAILURE;
+ }
+ show_table(&lib_sysinfo, verbose);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ cbsysinfo, 2, 1, do_cbsysinfo,
+ "Show coreboot sysinfo table",
+ "[-v] Dumps out the contents of the sysinfo table. This only\n"
+ "works if U-Boot is booted from coreboot"
+);
diff --git a/common/board_info.c b/common/board_info.c
index b54aa30..1cfe34f 100644
--- a/common/board_info.c
+++ b/common/board_info.c
@@ -1,31 +1,52 @@
// SPDX-License-Identifier: GPL-2.0+
#include <common.h>
+#include <dm.h>
#include <init.h>
+#include <sysinfo.h>
#include <asm/global_data.h>
#include <linux/libfdt.h>
#include <linux/compiler.h>
+DECLARE_GLOBAL_DATA_PTR;
+
int __weak checkboard(void)
{
return 0;
}
/*
- * If the root node of the DTB has a "model" property, show it.
+ * Check sysinfo for board information. Failing that if the root node of the DTB
+ * has a "model" property, show it.
+ *
* Then call checkboard().
*/
int __weak show_board_info(void)
{
-#ifdef CONFIG_OF_CONTROL
- DECLARE_GLOBAL_DATA_PTR;
- const char *model;
+ if (IS_ENABLED(CONFIG_OF_CONTROL)) {
+ struct udevice *dev;
+ const char *model;
+ char str[80];
+ int ret = -ENOSYS;
- model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+ if (IS_ENABLED(CONFIG_SYSINFO)) {
+ /* This might provide more detail */
+ ret = uclass_first_device_err(UCLASS_SYSINFO, &dev);
+ if (!ret)
+ ret = sysinfo_get_str(dev,
+ SYSINFO_ID_BOARD_MODEL,
+ sizeof(str), str);
+ }
+
+ /* Fail back to the main 'model' if available */
+ if (ret)
+ model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+ else
+ model = str;
- if (model)
- printf("Model: %s\n", model);
-#endif
+ if (model)
+ printf("Model: %s\n", model);
+ }
return checkboard();
}
diff --git a/common/bootm.c b/common/bootm.c
index dab7c36..ea71522 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -583,7 +583,8 @@
if (ret)
return log_msg_ret("silent", ret);
}
- if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && (flags & BOOTM_CL_SUBST)) {
+ if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && IS_ENABLED(CONFIG_CMDLINE) &&
+ (flags & BOOTM_CL_SUBST)) {
ret = process_subst(buf, maxlen);
if (ret)
return log_msg_ret("subst", ret);
diff --git a/common/bootstage.c b/common/bootstage.c
index 2c0110c..4621105 100644
--- a/common/bootstage.c
+++ b/common/bootstage.c
@@ -9,6 +9,8 @@
* permits accurate timestamping of each.
*/
+#define LOG_CATEGORY LOGC_BOOT
+
#include <common.h>
#include <bootstage.h>
#include <hang.h>
@@ -127,12 +129,16 @@
/* Only record the first event for each */
rec = find_id(data, id);
- if (!rec && data->rec_count < RECORD_COUNT) {
- rec = &data->record[data->rec_count++];
- rec->time_us = mark;
- rec->name = name;
- rec->flags = flags;
- rec->id = id;
+ if (!rec) {
+ if (data->rec_count < RECORD_COUNT) {
+ rec = &data->record[data->rec_count++];
+ rec->time_us = mark;
+ rec->name = name;
+ rec->flags = flags;
+ rec->id = id;
+ } else {
+ log_warning("Bootstage space exhasuted\n");
+ }
}
/* Tell the board about this progress */
diff --git a/common/image-fit.c b/common/image-fit.c
index 28b3d2b..2d0ece6 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1512,6 +1512,10 @@
uint8_t image_arch;
int aarch32_support = 0;
+ /* Let's assume that sandbox can load any architecture */
+ if (IS_ENABLED(CONFIG_SANDBOX))
+ return true;
+
if (IS_ENABLED(CONFIG_ARM64_SUPPORT_AARCH32))
aarch32_support = 1;
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 584f848..0711cbf 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -500,7 +500,7 @@
future requests for that data can be served faster. Enable this option
to build the drivers in drivers/cache as part of an SPL build.
-config SPL_CPU_SUPPORT
+config SPL_CPU
bool "Support CPU drivers"
help
Enable this to support CPU drivers in SPL. These drivers can set
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 5f51098..556a91a 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -387,6 +387,22 @@
#endif /* HANDOFF */
+/**
+ * get_bootstage_id() - Get the bootstage ID to emit
+ *
+ * @start: true if this is for starting SPL, false for ending it
+ * @return bootstage ID to use
+ */
+static enum bootstage_id get_bootstage_id(bool start)
+{
+ enum u_boot_phase phase = spl_phase();
+
+ if (IS_ENABLED(CONFIG_TPL_BUILD) && phase == PHASE_TPL)
+ return start ? BOOTSTAGE_ID_START_TPL : BOOTSTAGE_ID_END_TPL;
+ else
+ return start ? BOOTSTAGE_ID_START_SPL : BOOTSTAGE_ID_END_SPL;
+}
+
static int spl_common_init(bool setup_malloc)
{
int ret;
@@ -417,8 +433,8 @@
__func__, ret);
}
#endif /* CONFIG_BOOTSTAGE_STASH */
- bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_START_TPL :
- BOOTSTAGE_ID_START_SPL, SPL_TPL_NAME);
+ bootstage_mark_name(get_bootstage_id(true),
+ spl_phase_name(spl_phase()));
#if CONFIG_IS_ENABLED(LOG)
ret = log_init();
if (ret) {
@@ -733,8 +749,7 @@
debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr,
gd->malloc_ptr / 1024);
#endif
- bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_END_TPL :
- BOOTSTAGE_ID_END_SPL, "end " SPL_TPL_NAME);
+ bootstage_mark_name(get_bootstage_id(false), "end phase");
#ifdef CONFIG_BOOTSTAGE_STASH
ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR,
CONFIG_BOOTSTAGE_STASH_SIZE);
diff --git a/configs/chromebook_coral_defconfig b/configs/chromebook_coral_defconfig
index e3756cf..4823913 100644
--- a/configs/chromebook_coral_defconfig
+++ b/configs/chromebook_coral_defconfig
@@ -43,7 +43,7 @@
CONFIG_HANDOFF=y
CONFIG_TPL_SYS_MALLOC_SIMPLE=y
CONFIG_SPL_SEPARATE_BSS=y
-CONFIG_SPL_CPU_SUPPORT=y
+CONFIG_SPL_CPU=y
CONFIG_SPL_DM_SPI_FLASH=y
CONFIG_SPL_PCI=y
# CONFIG_SPL_SPI_FLASH_TINY is not set
diff --git a/configs/chromebook_link64_defconfig b/configs/chromebook_link64_defconfig
index 8f56ee3..872e33d 100644
--- a/configs/chromebook_link64_defconfig
+++ b/configs/chromebook_link64_defconfig
@@ -31,7 +31,7 @@
CONFIG_LAST_STAGE_INIT=y
CONFIG_MISC_INIT_R=y
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_CPU_SUPPORT=y
+CONFIG_SPL_CPU=y
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C_SUPPORT=y
CONFIG_SPL_DM_SPI_FLASH=y
diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig
index 99a489c..4815d8a 100644
--- a/configs/qemu-x86_64_defconfig
+++ b/configs/qemu-x86_64_defconfig
@@ -31,7 +31,7 @@
CONFIG_LAST_STAGE_INIT=y
CONFIG_PCI_INIT_R=y
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_CPU_SUPPORT=y
+CONFIG_SPL_CPU=y
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_DM_SPI_FLASH=y
CONFIG_SPL_NET_SUPPORT=y
diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst
index 8b18a22..e052b6b 100644
--- a/doc/arch/sandbox.rst
+++ b/doc/arch/sandbox.rst
@@ -389,6 +389,8 @@
=>host bind 0 ./disk.raw
=>ls host 0:2
+The device can be marked removeable with 'host bind -r'.
+
A disk image can be created using the following commands::
$> truncate -s 1200M ./disk.raw
diff --git a/doc/board/google/chromebook_coral.rst b/doc/board/google/chromebook_coral.rst
index c39f1e3..4b58567 100644
--- a/doc/board/google/chromebook_coral.rst
+++ b/doc/board/google/chromebook_coral.rst
@@ -16,6 +16,169 @@
Slim Bootloader. This documentation refers to a 'bare metal' port.
+Building
+--------
+
+First, you need the following binary blobs:
+
+ * descriptor.bin - Intel flash descriptor
+ * fitimage.bin - Base flash image structure
+ * fsp_m.bin - FSP-M, for setting up SDRAM
+ * fsp_s.bin - FSP-S, for setting up Silicon
+ * vbt.bin - for setting up display
+
+These binaries do not seem to be available publicly. If you have a ROM image,
+such as santa.bin then you can do this::
+
+ cbfstool santa.bin extract -n fspm.bin -f fsp-m.bin
+ cbfstool santa.bin extract -n fsps.bin -f fsp-s.bin
+ cbfstool santa.bin extract -n vbt-santa.bin -f vbt.bin
+ mkdir tmp
+ cd tmp
+ dump_fmap -x ../santa.bin
+ mv SI_DESC ../descriptor.bin
+ mv IFWI ../fitimage.bin
+
+Put all of these files in `board/google/chromebook_coral` so they can be found
+by the build.
+
+To build::
+
+ make O=/tmp/b/chromebook_coral chromebook_coral_defconfig
+ make O=/tmp/b/chromebook_coral -s -j30 all
+
+That should produce `/tmp/b/chrombook_coral/u-boot.rom` which you can use with
+a Dediprog em100::
+
+ em100 -s -c w25q128fw -d /tmp/b/chromebook_coral/u-boot.rom -r
+
+or you can use flashrom to write it to the board. If you do that, make sure you
+have a way to restore the old ROM without booting the board. Otherwise you may
+brick it. Having said that, you may find these instructions useful if you want
+to unbrick your device:
+
+ https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging.md
+
+You can buy Suzy-Q from Sparkfun:
+
+ https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/main/docs/ccd.md#suzyq-suzyqable
+
+Note that it will hang at the SPL prompt for 21 seconds. When booting into
+Chrome OS it will always select developer mode, so will wipe anything you have
+on the device if you let it proceed. You have two seconds in U-Boot to stop the
+auto-boot prompt and several seconds at the 'developer wipe' screen to stop it
+wiping the disk.
+
+Here is the console output::
+
+ U-Boot TPL 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700)
+ Trying to boot from Mapped SPI
+
+ U-Boot SPL 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700)
+ Trying to boot from Mapped SPI
+
+
+ U-Boot 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700)
+
+ CPU: Intel(R) Celeron(R) CPU N3450 @ 1.10GHz
+ DRAM: 3.9 GiB
+ MMC: sdmmc@1b,0: 1, emmc@1c,0: 2
+ Video: 1024x768x32 @ b0000000
+ Model: Google Coral
+ Net: No ethernet found.
+ SF: Detected w25q128fw with page size 256 Bytes, erase size 4 KiB, total 16 MiB
+ Hit any key to stop autoboot: 0
+ cmdline=console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=${uuid}/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=${uuid} add_efi_memmap boot=local noresume noswap i915.modeset=1 Kernel command line: "console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off "
+ Setup located at 00090000:
+
+ ACPI RSDP addr : 7991f000
+ E820: 14 entries
+ Addr Size Type
+ d0000000 1000000 <NULL>
+ 0 a0000 RAM
+ a0000 60000 Reserved
+ 7b000000 800000 Reserved
+ 7b800000 4800000 Reserved
+ 7ac00000 400000 Reserved
+ 100000 ff00000 RAM
+ 10000000 2151000 Reserved
+ 12151000 68aaf000 RAM
+ 100000000 80000000 RAM
+ e0000000 10000000 Reserved
+ 7991bfd0 12e4030 Reserved
+ d0000000 10000000 Reserved
+ fed10000 8000 Reserved
+ Setup sectors : 1e
+ Root flags : 1
+ Sys size : 63420
+ RAM size : 0
+ Video mode : ffff
+ Root dev : 0
+ Boot flag : 0
+ Jump : 66eb
+ Header : 53726448
+ Kernel V2
+ Version : 20d
+ Real mode switch : 0
+ Start sys : 1000
+ Kernel version : 38cc
+ @00003acc:
+ Type of loader : 80
+ U-Boot, version 0
+ Load flags : 81
+ : loaded-high can-use-heap
+ Setup move size : 8000
+ Code32 start : 100000
+ Ramdisk image : 0
+ Ramdisk size : 0
+ Bootsect kludge : 0
+ Heap end ptr : 8e00
+ Ext loader ver : 0
+ Ext loader type : 0
+ Command line ptr : 99000
+ console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off
+ Initrd addr max : 7fffffff
+ Kernel alignment : 200000
+ Relocatable kernel : 1
+ Min alignment : 15
+ : 200000
+ Xload flags : 3
+ : 64-bit-entry can-load-above-4gb
+ Cmdline size : 7ff
+ Hardware subarch : 0
+ HW subarch data : 0
+ Payload offset : 26e
+ Payload length : 612045
+ Setup data : 0
+ Pref address : 1000000
+ Init size : 1383000
+ Handover offset : 0
+
+ Starting kernel ...
+
+ Timer summary in microseconds (17 records):
+ Mark Elapsed Stage
+ 0 0 reset
+ 155,279 155,279 TPL
+ 237,088 81,809 end phase
+ 237,533 445 SPL
+ 816,456 578,923 end phase
+ 817,357 901 board_init_f
+ 1,061,751 244,394 board_init_r
+ 1,402,435 340,684 id=64
+ 1,430,071 27,636 main_loop
+ 5,532,057 4,101,986 start_kernel
+
+ Accumulated time:
+ 685 dm_r
+ 2,817 fast_spi
+ 33,095 dm_spl
+ 52,468 dm_f
+ 208,242 fsp-m
+ 242,221 fsp-s
+ 332,710 mmap_spi
+
+
Boot flow - TPL
---------------
@@ -181,7 +344,7 @@
ff000000 Bottom of ROM
fefc0000 Top of CAR region
fef96000 Stack for FSP-M
- fef40000 59000 FSP-M
+ fef40000 59000 FSP-M (also VPL loads here)
fef11000 SPL loaded here
fef10000 CONFIG_BLOBLIST_ADDR
fef10000 Stack top in TPL, SPL and U-Boot before relocation
@@ -194,36 +357,73 @@
200000 FSP-S (which is run after U-Boot is relocated)
1110000 CONFIG_SYS_TEXT_BASE
+
+Speeding up SPL for development
+-------------------------------
+
+The 21-second wait for memory training is annoying during development, since
+every new image incurs this cost when booting. There is no cache to fall back on
+since that area of the image is empty on start-up.
+
+You can add suitable cache contents to the image to fix this, for development
+purposes only, like this::
+
+ # Read the image back after booting through SPL
+ em100 -s -c w25q128fw -u image.bin
+
+ # Extract the two cache regions
+ binman extract -i image.bin extra *cache
+
+ # Move them into the source directory
+ mv *cache board/google/chromebook_coral
+
+Then add something like this to the devicetree::
+
+ #if IS_ENABLED(CONFIG_HAVE_MRC) || IS_ENABLED(CONFIG_FSP_VERSION2)
+ /* Provide initial contents of the MRC data for faster development */
+ rw-mrc-cache {
+ type = "blob";
+ /* Mirror the offset in spi-flash@0 */
+ offset = <0xff8e0000>;
+ size = <0x10000>;
+ filename = "board/google/chromebook_coral/rw-mrc-cache";
+ };
+ rw-var-mrc-cache {
+ type = "blob";
+ size = <0x1000>;
+ filename = "board/google/chromebook_coral/rw-var-mrc-cache";
+ };
+ #endif
+
+This tells binman to put the cache contents in the same place as the
+`rw-mrc-cache` and `rw-var-mrc-cache` regions defined by the SPI-flash driver.
+
Supported peripherals
---------------------
-- UART
-- SPI flash
-- Video
-- MMC (dev 0) and micro-SD (dev 1)
-- Chrome OS EC
-- Keyboard
-- USB
+The following have U-Boot drivers:
+ - UART
+ - SPI flash
+ - Video
+ - MMC (dev 0) and micro-SD (dev 1)
+ - Chrome OS EC
+ - Cr50 (security chip)
+ - Keyboard
+ - USB
+
To do
-----
- Finish peripherals
- - left-side USB
- - USB-C
- - Cr50 (security chip: a basic driver is running but not included here)
- Sound (Intel I2S support exists, but need da7219 driver)
- - Various minor features supported by LPC, etc.
-- Booting Chrome OS, e.g. with verified boot
-- Integrate with Chrome OS vboot
-- Improvements to booting from coreboot (i.e. as a coreboot target)
- Use FSP-T binary instead of our own CAR implementation
- Use the official FSP package instead of the coreboot one
-- Enable all CPU cores
- Suspend / resume
-- ACPI
+- Fix MMC which seems to try to read even though the card is empty
+- Fix USB3 crash "WARN halted endpoint, queueing URB anyway."
Credits
diff --git a/doc/README.chromium-chainload b/doc/chromium/chainload.rst
similarity index 78%
rename from doc/README.chromium-chainload
rename to doc/chromium/chainload.rst
index 45eaece..7b6bb10 100644
--- a/doc/README.chromium-chainload
+++ b/doc/chromium/chainload.rst
@@ -1,3 +1,6 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2020 Google LLC
+
Running U-Boot from coreboot on Chromebooks
===========================================
@@ -15,7 +18,7 @@
For all of these the standard U-Boot build instructions apply. For example on
-ARM:
+ARM::
sudo apt install gcc-arm-linux-gnueabi
mkdir b
@@ -37,14 +40,17 @@
Nyan-big
--------
-Compiled based on information here:
-https://lists.denx.de/pipermail/u-boot/2015-March/209530.html
-https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big
-https://lists.denx.de/pipermail/u-boot/2017-May/289491.html
-https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card
+Compiled based on information here::
+
+ https://lists.denx.de/pipermail/u-boot/2015-March/209530.html
+ https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big
+ https://lists.denx.de/pipermail/u-boot/2017-May/289491.html
+ https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card
1. Build U-Boot
+Steps::
+
mkdir b
make -j8 O=b/nyan-big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
@@ -61,16 +67,21 @@
3. Build and sign an image
- ./b/nyan-big/tools/mkimage -f doc/chromium/nyan-big.its u-boot-chromium.fit
+Steps::
+
+ ./b/nyan-big/tools/mkimage -f doc/chromium/files/nyan-big.its u-boot-chromium.fit
echo test >dummy.txt
- vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
- --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
- --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
- --bootloader dummy.txt --pack u-boot.kpart
+ vbutil_kernel --arch arm \
+ --keyblock doc/chromium/files/devkeys/kernel.keyblock \
+ --signprivate doc/chromium/files/devkeys/kernel_data_key.vbprivk \
+ --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
+ --bootloader dummy.txt --pack u-boot.kpart
4. Prepare an SD card
+Steps::
+
DISK=/dev/sdc # Replace with your actual SD card device
sudo cgpt create $DISK
sudo cgpt add -b 34 -s 32768 -P 1 -S 1 -t kernel $DISK
@@ -80,6 +91,8 @@
5. Write U-Boot to the SD card
+Steps::
+
sudo dd if=u-boot.kpart of=/dev/sdc1; sync
@@ -90,7 +103,7 @@
'enable_dev_usb_boot'. You only need to do this once.
Reboot the device with the SD card inserted. Press Clrl-U at the developer
-mode screen. It should show something like the following on the display:
+mode screen. It should show something like the following on the display::
U-Boot 2017.07-00637-g242eb42-dirty (May 22 2017 - 06:14:21 -0600)
@@ -104,9 +117,9 @@
7. Known problems
-On the serial console the word MMC is chopped at the start of the line:
+On the serial console the word MMC is chopped at the start of the line::
-C: sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0
+ C: sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0
This is likely due to some problem with change-over of the serial driver
during relocation (or perhaps updating the clock setup in board_init()).
@@ -116,7 +129,7 @@
To check that you copied the u-boot.its file correctly, use these commands.
You should see that the data at 0x100 in u-boot-chromium.fit is the first few
-bytes of U-Boot:
+bytes of U-Boot::
hd u-boot-chromium.fit |head -20
...
@@ -141,34 +154,39 @@
Open include/configs/rk3288_common.h
-Change:
+Change::
-#define CONFIG_SYS_TEXT_BASE 0x00100000
+ #define CONFIG_SYS_TEXT_BASE 0x00100000
-to:
+to::
-#define CONFIG_SYS_TEXT_BASE 0x02000100
+ #define CONFIG_SYS_TEXT_BASE 0x02000100
2. Build U-Boot
+Steps::
+
mkdir b
make -j8 O=b/chromebook_jerry CROSS_COMPILE=arm-linux-gnueabi- \
- chromebook_jerry_defconfig all
+ chromebook_jerry_defconfig all
3. See above
4. Build and sign an image
+Steps::
+
./b/chromebook_jerry/tools/mkimage -f doc/chromium/chromebook_jerry.its \
- u-boot-chromium.fit
+ u-boot-chromium.fit
echo test >dummy.txt
- vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
- --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
- --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
- --bootloader dummy.txt --pack u-boot.kpart
+ vbutil_kernel --arch arm \
+ --keyblock doc/chromium/files/devkeys/kernel.keyblock \
+ --signprivate doc/chromium/files/devkeys/kernel_data_key.vbprivk \
+ --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
+ --bootloader dummy.txt --pack u-boot.kpart
5. See above
@@ -182,7 +200,7 @@
'enable_dev_usb_boot'. You only need to do this once.
Reboot the device with the SD card inserted. Press Clrl-U at the developer
-mode screen. It should show something like the following on the display:
+mode screen. It should show something like the following on the display::
U-Boot 2017.05-00649-g72acdbf-dirty (May 29 2017 - 14:57:05 -0600)
@@ -203,18 +221,18 @@
Other notes
-===========
+-----------
flashrom
---------
+~~~~~~~~
- Used to make a backup of your firmware, or to replace it.
+Used to make a backup of your firmware, or to replace it.
- See: https://www.chromium.org/chromium-os/packages/cros-flashrom
+See: https://www.chromium.org/chromium-os/packages/cros-flashrom
coreboot
---------
+~~~~~~~~
Coreboot itself is not designed to actually boot an OS. Instead, a program
called Depthcharge is used. This originally came out of U-Boot and was then
diff --git a/doc/chromium/chromebook_jerry.its b/doc/chromium/files/chromebook_jerry.its
similarity index 100%
rename from doc/chromium/chromebook_jerry.its
rename to doc/chromium/files/chromebook_jerry.its
diff --git a/doc/chromium/devkeys/kernel.keyblock b/doc/chromium/files/devkeys/kernel.keyblock
similarity index 100%
rename from doc/chromium/devkeys/kernel.keyblock
rename to doc/chromium/files/devkeys/kernel.keyblock
Binary files differ
diff --git a/doc/chromium/devkeys/kernel_data_key.vbprivk b/doc/chromium/files/devkeys/kernel_data_key.vbprivk
similarity index 100%
rename from doc/chromium/devkeys/kernel_data_key.vbprivk
rename to doc/chromium/files/devkeys/kernel_data_key.vbprivk
Binary files differ
diff --git a/doc/chromium/nyan-big.its b/doc/chromium/files/nyan-big.its
similarity index 100%
rename from doc/chromium/nyan-big.its
rename to doc/chromium/files/nyan-big.its
diff --git a/doc/chromium/index.rst b/doc/chromium/index.rst
new file mode 100644
index 0000000..0722c25
--- /dev/null
+++ b/doc/chromium/index.rst
@@ -0,0 +1,14 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2020 Google LLC
+
+Chromium OS-specific doc
+========================
+
+This provides some information about Chromium OS and U-Boot.
+
+.. toctree::
+ :maxdepth: 2
+
+ overview
+ run_vboot
+ chainload
diff --git a/doc/chromium/overview.rst b/doc/chromium/overview.rst
new file mode 100644
index 0000000..5498ed9
--- /dev/null
+++ b/doc/chromium/overview.rst
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2020 Google LLC
+
+Chromium OS Support in U-Boot
+=============================
+
+Introduction
+------------
+
+This describes how to use U-Boot with Chromium OS. Several options are
+available:
+
+ - Running U-Boot from the 'altfw' feature, which is available on selected
+ Chromebooks from 2019 onwards (initially Grunt). Press '1' from the
+ developer-mode screen to get into U-Boot. See here for details:
+ https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_mode.md
+
+ - Running U-Boot from the disk partition. This involves signing U-Boot and
+ placing it on the disk, for booting as a 'kernel'. See
+ :doc:`chainload` for information on this. This is the only
+ option on non-U-Boot Chromebooks from 2013 to 2018 and is somewhat
+ more involved.
+
+ - Running U-Boot with Chromium OS verified boot. This allows U-Boot to be
+ used instead of either or both of depthcharge (a bootloader which forked
+ from U-Boot in 2013) and coreboot. See :doc:`run_vboot` for more
+ information on this.
+
+ - Running U-Boot from coreboot. This allows U-Boot to run on more devices
+ since many of them only support coreboot as the bootloader and have
+ no bare-metal support in U-Boot. For this, use the 'coreboot' target.
+
+ - Running U-Boot and booting into a Chrome OS image, but without verified
+ boot. This can be useful for testing.
+
+
+Talks and documents
+-------------------
+
+Here is some material relevant to Chromium OS verified boot with U-Boot:
+
+ - "U-Boot with Chrome OS and firmware packaging"
+
+ - Author: Simon Glass
+ - Presented at Open Source Firmware Conference 2018, Erlangen
+ - Describes the work in progress as at the end of 2018
+ - Slides at `OSFC <https://2018.osfc.io/uploads/talk/paper/26/U-Boot_with_Chrome_OS_and_firmware_packaging.pdf>`_
+ - Video on `Youtube <https://www.youtube.com/watch?v=1jknxUvmwpo>`_
+
+ - "Verified Boot in Chrome OS and how to make it work for you"
+
+ - Author: Simon Glass
+ - Presented at ELCE 2013, Edinburgh
+ - Describes the original 2013 implementation as shipped on snow (first
+ `ARM Chromebook was a Samsung Chromebook <https://www.cnet.com/products/samsung-series-3-chromebook-xe303c12-11-6-exynos-5250-2-gb-ram-16-gb-ssd-bilingual-english-french/>`_
+ with Samsung Exynos5250 `review <https://www.cnet.com/reviews/samsung-chromebook-series-3-review/>`_),
+ spring (`HP Chromebook 11 <https://www.cnet.com/products/hp-chromebook-11-g2-11-6-exynos-5250-4-gb-ram-16-gb-emmc/>`_)
+ and pit/pi (`Samsung Chromebook 2 <https://www.cnet.com/products/samsung-chromebook-2-xe503c12-11-6-exynos-5-octa-4-gb-ram-16-gb-ssd/>`_
+ with Exynos 5 Octa 5420 in 2014).
+ - Slides at `Google research <https://research.google/pubs/pub42038/>`_
+ - Video at `Youtube <https://www.youtube.com/watch?v=kdpZC9jFzZA>`_
+
+ - "Chrome University 2018: Chrome OS Firmware and Verified Boot 201"
+
+ - Author: Duncan Laurie
+ - Describes Chrome OS firmware as of 2018 and includes a wide range of
+ topics. This has no U-Boot information, but does cover coreboot and also
+ talks about the Chrome OS EC and Security chip. This is probably the
+ best introduction talk.
+ - Video at `YouTube <https://www.youtube.com/watch?v=WY2sWpuda2g>`_
+
+ - `Chromium OS U-Boot <https://www.chromium.org/developers/u-boot>`_
+
+ - `Firmware porting Guide <https://www.chromium.org/chromium-os/firmware-porting-guide>`_
diff --git a/doc/README.chromium b/doc/chromium/run_vboot.rst
similarity index 67%
rename from doc/README.chromium
rename to doc/chromium/run_vboot.rst
index 75f2f24..41b4f63 100644
--- a/doc/README.chromium
+++ b/doc/chromium/run_vboot.rst
@@ -1,42 +1,14 @@
-Chromium OS Support in U-Boot
-=============================
-
-Introduction
-------------
-
-This describes how to use U-Boot with Chromium OS. Several options are
-available:
-
- - Running U-Boot from the 'altfw' feature, which is available on selected
- Chromebooks from 2019 onwards (initially Grunt). Press '1' from the
- developer-mode screen to get into U-Boot. See here for details:
- https://sites.google.com/a/chromium.org/dev/chromium-os/poking-around-your-chrome-os-device?pli=1
-
- - Running U-Boot from the disk partition. This involves signing U-Boot and
- placing it on the disk, for booting as a 'kernel'. See
- README.chromium-chainload for information on this. This is the only
- option on non-U-Boot Chromebooks from 2013 to 2018 and is somewhat
- more involved.
-
- - Running U-Boot with Chromium OS verified boot. This allows U-Boot to be
- used instead of either or both of depthcharge (a bootloader which forked
- from U-Boot in 2013) and coreboot. See below for more information on
- this.
-
- - Running U-Boot from coreboot. This allows U-Boot to run on more devices
- since many of them only support coreboot as the bootloader and have
- no bare-metal support in U-Boot. For this, use the 'coreboot' target.
-
- - Running U-Boot and booting into a Chrome OS image, but without verified
- boot. This can be useful for testing.
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2020 Google LLC
+.. sectionauthor:: Simon Glass <sjg@chromium.org>
-U-Boot with Chromium OS verified boot
--------------------------------------
+Running U-Boot with Chromium OS verified boot
+=============================================
-To obtain:
+To obtain::
- git clone https://github.com/sglass68/u-boot.git
+ git clone https://github.com/sjg20/u-boot.git
cd u-boot
git checkout cros-master
@@ -46,29 +18,36 @@
git checkout 45964294
# futility: updater: Correct output version for Snow
-To build for sandbox:
+To build for sandbox::
UB=/tmp/b/chromeos_sandbox # U-Boot build directory
cd u-boot
make O=$UB chromeos_sandbox_defconfig
make O=$UB -j20 -s VBOOT_SOURCE=/path/to/vboot_reference \
- MAKEFLAGS_VBOOT=DEBUG=1 QUIET=1
+ MAKEFLAGS_VBOOT=DEBUG=1 QUIET=1
Replace sandbox with another supported target.
This produces $UB/image.bin which contains the firmware binaries in a SPI
flash image.
-To run on sandbox:
+To run on sandbox::
+ CROS=~/cosarm
+ IMG=$CROS/src/build/images/coral/latest/chromiumos_image.bin
$UB/tpl/u-boot-tpl -d $UB/u-boot.dtb.out \
- -L6 -c "host bind 0 $CROS/src/build/images/cheza/latest/chromiumos_image.bin; vboot go auto" \
- -l -w -s state.dtb -r
+ -L6 -c "host bind 0 $IMG; vboot go auto" \
+ -l -w -s state.dtb -r -n -m $UB/ram
+
+ $UB/tpl/u-boot-tpl -d $UB/u-boot.dtb.out -L6 -l \
+ -c "host bind 0 $IMG; vboot go auto" -w -s $UB/state.dtb -r -n -m $UB/mem
+
To run on other boards:
- Install image.bin in the SPI flash of your device
- Boot your system
+ - Install image.bin in the SPI flash of your device
+ - Boot your system
+
Sandbox
-------
@@ -83,7 +62,7 @@
phases into state.dtb and will automatically ensure that memory is shared
between all phases. TPL will jump to SPL and then on to U-Boot proper.
-It is possible to run with debugging on, e.g.
+It is possible to run with debugging on, e.g.::
gdb --args $UB/tpl/u-boot-tpl -d ....
@@ -95,7 +74,7 @@
-----
Basic support is available for samus, using the chromeos_samus target. If you
-have an em100, use:
+have an em100, use::
sudo em100 -s -c W25Q128FW -d $UB/image.bin -t -r
@@ -119,11 +98,20 @@
Several uclasses are provided in cros/:
+UCLASS_CROS_AUX_FW
+ Chrome OS auxiliary firmware
+
- UCLASS_CROS_AUX_FW Chrome OS auxiliary firmware
- UCLASS_CROS_FWSTORE Chrome OS firmware storage
- UCLASS_CROS_NVDATA Chrome OS non-volatile data device
- UCLASS_CROS_VBOOT_EC Chrome OS vboot EC operations
- UCLASS_CROS_VBOOT_FLAG Chrome OS verified boot flag
+UCLASS_CROS_FWSTORE
+ Chrome OS firmware storage
+
+UCLASS_CROS_NVDATA
+ Chrome OS non-volatile data device
+
+UCLASS_CROS_VBOOT_EC
+ Chrome OS vboot EC operations
+
+UCLASS_CROS_VBOOT_FLAG
+ Chrome OS verified boot flag
The existing UCLASS_CROS_EC is also used.
@@ -181,7 +169,7 @@
U-Boot without Chromium OS verified boot
----------------------------------------
-The following script can be used to boot a Chrome OS image on coral:
+The following script can be used to boot a Chrome OS image on coral::
# Read the image header and obtain the address of the kernel
# The offset 4f0 is defined by verified boot and may change for other
@@ -213,6 +201,4 @@
Get the full ACPI tables working with Coral
-Simon Glass
-sjg@chromium.org
7 October 2018
diff --git a/doc/device-tree-bindings/sysinfo/google,coral.txt b/doc/device-tree-bindings/sysinfo/google,coral.txt
new file mode 100644
index 0000000..d8a1a79
--- /dev/null
+++ b/doc/device-tree-bindings/sysinfo/google,coral.txt
@@ -0,0 +1,37 @@
+Google Coral sysinfo information
+================================
+
+This binding allows information about the board to be described. It includes
+the SMBIOS binding as well.
+
+Required properties:
+
+ - compatible: "google,coral"
+ - recovery-gpios: GPIO to use for recovery button (-1 if none)
+ - wite-protect-gpios: GPIO to use for write-protect screw
+ - phase-enforce-gpios: GPIO to indicate the board is in final ship mode
+ - memconfig-gpios: 4 GPIOs to use to read memory config (as base2 int)
+
+Optional properties:
+ - skuconfig-gpios: 2 GPIOs to use to read SKU ID. If not present, the
+ Chromium OS EC SKU_ID is used instead
+
+Example:
+
+board: board {
+ compatible = "google,coral";
+ recovery-gpios = <&gpio_nw (-1) GPIO_ACTIVE_LOW>;
+ write-protect-gpios = <&gpio_nw GPIO_75 GPIO_ACTIVE_HIGH>;
+ phase-enforce-gpios = <&gpio_n GPIO_10 GPIO_ACTIVE_HIGH>;
+ memconfig-gpios = <&gpio_nw GPIO_101 GPIO_ACTIVE_HIGH
+ &gpio_nw GPIO_102 GPIO_ACTIVE_HIGH
+ &gpio_n GPIO_38 GPIO_ACTIVE_HIGH
+ &gpio_n GPIO_45 GPIO_ACTIVE_HIGH>;
+
+ /*
+ * This is used for reef only:
+ *
+ * skuconfig-gpios = <&gpio_nw GPIO_16 GPIO_ACTIVE_HIGH
+ * &gpio_nw GPIO_17 GPIO_ACTIVE_HIGH>;
+ */
+ };
diff --git a/doc/index.rst b/doc/index.rst
index f7aada9..02de1d4 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -87,6 +87,14 @@
android/index
+Chromium OS-specific doc
+------------------------
+
+.. toctree::
+ :maxdepth: 2
+
+ chromium/index
+
Indices and tables
==================
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 35c515f..fb83434 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -21,6 +21,7 @@
booti
bootmenu
button
+ x86/cbsysinfo
conitrace
echo
exception
diff --git a/doc/usage/x86/cbsysinfo.rst b/doc/usage/x86/cbsysinfo.rst
new file mode 100644
index 0000000..8c03a85
--- /dev/null
+++ b/doc/usage/x86/cbsysinfo.rst
@@ -0,0 +1,25 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+cbsysinfo
+=========
+
+Synopis
+-------
+
+::
+
+ cbsysinfo
+
+
+Description
+-----------
+
+This displays information obtained from the coreboot sysinfo table. It is only
+useful when booting U-Boot from coreboot.
+
+Example
+-------
+
+::
+
+ => cbsysinfo
diff --git a/drivers/Makefile b/drivers/Makefile
index c562a71..3510dab 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -38,7 +38,7 @@
obj-$(CONFIG_SPL_BOOTCOUNT_LIMIT) += bootcount/
obj-$(CONFIG_SPL_CACHE_SUPPORT) += cache/
-obj-$(CONFIG_SPL_CPU_SUPPORT) += cpu/
+obj-$(CONFIG_SPL_CPU) += cpu/
obj-$(CONFIG_SPL_CRYPTO_SUPPORT) += crypto/
obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
obj-$(CONFIG_ARMADA_38X) += ddr/marvell/a38x/
diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c
index e2f229b..1c2c3b4 100644
--- a/drivers/block/sandbox.c
+++ b/drivers/block/sandbox.c
@@ -89,7 +89,7 @@
}
#ifdef CONFIG_BLK
-int host_dev_bind(int devnum, char *filename)
+int host_dev_bind(int devnum, char *filename, bool removable)
{
struct host_block_dev *host_dev;
struct udevice *dev;
@@ -146,7 +146,7 @@
}
desc = blk_get_devnum_by_type(IF_TYPE_HOST, devnum);
- desc->removable = 1;
+ desc->removable = removable;
snprintf(desc->vendor, BLK_VEN_SIZE, "U-Boot");
snprintf(desc->product, BLK_PRD_SIZE, "hostfile");
snprintf(desc->revision, BLK_REV_SIZE, "1.0");
@@ -160,7 +160,7 @@
return ret;
}
#else
-int host_dev_bind(int dev, char *filename)
+int host_dev_bind(int dev, char *filename, bool removable)
{
struct host_block_dev *host_dev = find_host_device(dev);
@@ -195,7 +195,7 @@
blk_dev->block_write = host_block_write;
blk_dev->devnum = dev;
blk_dev->part_type = PART_TYPE_UNKNOWN;
- blk_dev->removable = 1;
+ blk_dev->removable = removable;
snprintf(blk_dev->vendor, BLK_VEN_SIZE, "U-Boot");
snprintf(blk_dev->product, BLK_PRD_SIZE, "hostfile");
snprintf(blk_dev->revision, BLK_REV_SIZE, "1.0");
diff --git a/drivers/gpio/intel_gpio.c b/drivers/gpio/intel_gpio.c
index ab46a94..f15ce7b 100644
--- a/drivers/gpio/intel_gpio.c
+++ b/drivers/gpio/intel_gpio.c
@@ -23,6 +23,7 @@
#include <asm/pci.h>
#include <asm/arch/gpio.h>
#include <dm/acpi.h>
+#include <dm/device-internal.h>
#include <dt-bindings/gpio/x86-gpio.h>
static int intel_gpio_get_value(struct udevice *dev, uint offset)
@@ -85,7 +86,7 @@
/*
* GPIO numbers are global in the device tree so it doesn't matter
- * which one is used
+ * which @orig_dev is used
*/
gpio = args->args[0];
ret = intel_pinctrl_get_pad(gpio, &pinctrl, &desc->offset);
@@ -97,6 +98,17 @@
desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
desc->dev = dev;
+ /*
+ * Handle the case where the wrong GPIO device was provided, since this
+ * will not have been probed by the GPIO uclass before calling here
+ * (see gpio_request_tail()).
+ */
+ if (orig_dev != dev) {
+ ret = device_probe(dev);
+ if (ret)
+ return log_msg_ret("probe", ret);
+ }
+
return 0;
}
diff --git a/drivers/misc/cbmem_console.c b/drivers/misc/cbmem_console.c
index 5ba0a54..8bbe33d 100644
--- a/drivers/misc/cbmem_console.c
+++ b/drivers/misc/cbmem_console.c
@@ -9,7 +9,7 @@
#error This driver requires coreboot
#endif
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
struct cbmem_console {
u32 buffer_size;
diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c
index cb8adc4..bc01df0 100644
--- a/drivers/misc/cros_ec_sandbox.c
+++ b/drivers/misc/cros_ec_sandbox.c
@@ -153,10 +153,14 @@
{
struct ec_state *ec = g_state;
+ if (!g_state)
+ return 0;
+
/* We are guaranteed enough space to write basic properties */
fdt_setprop_u32(blob, node, "current-image", ec->current_image);
fdt_setprop(blob, node, "vbnv-context", ec->vbnv_context,
sizeof(ec->vbnv_context));
+
return state_setprop(node, "flash-data", ec->flash_data,
ec->ec_config.flash.length);
}
diff --git a/drivers/misc/p2sb_emul.c b/drivers/misc/p2sb_emul.c
index 973d02d..51f8716 100644
--- a/drivers/misc/p2sb_emul.c
+++ b/drivers/misc/p2sb_emul.c
@@ -7,7 +7,6 @@
*/
#define LOG_CATEGORY UCLASS_MISC
-#define LOG_DEBUG
#include <common.h>
#include <axi.h>
diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c
index fd5dd22..b9ab064 100644
--- a/drivers/mmc/pci_mmc.c
+++ b/drivers/mmc/pci_mmc.c
@@ -53,6 +53,7 @@
host->ioaddr = (void *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
PCI_REGION_MEM);
host->name = dev->name;
+ host->cd_gpio = priv->cd_gpio;
host->mmc = &plat->mmc;
host->mmc->dev = dev;
ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
@@ -68,8 +69,11 @@
{
if (CONFIG_IS_ENABLED(DM_GPIO)) {
struct pci_mmc_priv *priv = dev_get_priv(dev);
+ int ret;
- gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN);
+ ret = gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio,
+ GPIOD_IS_IN);
+ log_debug("cd-gpio %s done, ret=%d\n", dev->name, ret);
}
return 0;
diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c
index 12d1321..cfce00e 100644
--- a/drivers/mtd/spi/sf-uclass.c
+++ b/drivers/mtd/spi/sf-uclass.c
@@ -31,6 +31,15 @@
return log_ret(sf_get_ops(dev)->erase(dev, offset, len));
}
+int spl_flash_get_sw_write_prot(struct udevice *dev)
+{
+ struct dm_spi_flash_ops *ops = sf_get_ops(dev);
+
+ if (!ops->get_sw_write_prot)
+ return -ENOSYS;
+ return log_ret(ops->get_sw_write_prot(dev));
+}
+
/*
* TODO(sjg@chromium.org): This is an old-style function. We should remove
* it when all SPI flash drivers use dm
@@ -46,11 +55,6 @@
return dev_get_uclass_priv(dev);
}
-void spi_flash_free(struct spi_flash *flash)
-{
- device_remove(flash->spi->dev, DM_REMOVE_NORMAL);
-}
-
int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
unsigned int max_hz, unsigned int spi_mode,
struct udevice **devp)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 9ceff0e..786301b 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -75,6 +75,10 @@
#define JEDEC_MFR(info) ((info)->id[0])
#define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2]))
+/* Get software write-protect value (BP bits) */
+int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash);
+
+
#if CONFIG_IS_ENABLED(SPI_FLASH_MTD)
int spi_flash_mtd_register(struct spi_flash *flash);
void spi_flash_mtd_unregister(void);
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 6c87434..3befbe9 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -130,6 +130,13 @@
return mtd->_erase(mtd, &instr);
}
+static int spi_flash_std_get_sw_write_prot(struct udevice *dev)
+{
+ struct spi_flash *flash = dev_get_uclass_priv(dev);
+
+ return spi_flash_cmd_get_sw_write_prot(flash);
+}
+
int spi_flash_std_probe(struct udevice *dev)
{
struct spi_slave *slave = dev_get_parent_priv(dev);
@@ -153,6 +160,7 @@
.read = spi_flash_std_read,
.write = spi_flash_std_write,
.erase = spi_flash_std_erase,
+ .get_sw_write_prot = spi_flash_std_get_sw_write_prot,
};
static const struct udevice_id spi_flash_std_ids[] = {
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index e0efebc..a662553 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -2647,3 +2647,14 @@
return 0;
}
+
+/* U-Boot specific functions, need to extend MTD to support these */
+int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor)
+{
+ int sr = read_sr(nor);
+
+ if (sr < 0)
+ return sr;
+
+ return (sr >> 2) & 7;
+}
diff --git a/drivers/mtd/spi/spi-nor-tiny.c b/drivers/mtd/spi/spi-nor-tiny.c
index 07c8c7b..1d5861d 100644
--- a/drivers/mtd/spi/spi-nor-tiny.c
+++ b/drivers/mtd/spi/spi-nor-tiny.c
@@ -809,3 +809,9 @@
return 0;
}
+
+/* U-Boot specific functions, need to extend MTD to support these */
+int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor)
+{
+ return -ENOTSUPP;
+}
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index a14a4db..7bad4c8 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -349,13 +349,10 @@
}
/* Use double buffering if enabled */
- if (IS_ENABLED(CONFIG_VIDEO_COPY)) {
- if (!plat->base)
- return log_msg_ret("copy", -ENFILE);
+ if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->base)
plat->copy_base = vesa->phys_base_ptr;
- } else {
+ else
plat->base = vesa->phys_base_ptr;
- }
log_debug("base = %lx, copy_base = %lx\n", plat->base, plat->copy_base);
plat->size = vesa->bytes_per_scanline * vesa->y_resolution;
diff --git a/drivers/serial/serial_coreboot.c b/drivers/serial/serial_coreboot.c
index 88c8209..de09c86 100644
--- a/drivers/serial/serial_coreboot.c
+++ b/drivers/serial/serial_coreboot.c
@@ -9,7 +9,7 @@
#include <dm.h>
#include <ns16550.h>
#include <serial.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
static int coreboot_of_to_plat(struct udevice *dev)
{
diff --git a/drivers/sound/tegra_i2s.c b/drivers/sound/tegra_i2s.c
index 5cf8225..932f737 100644
--- a/drivers/sound/tegra_i2s.c
+++ b/drivers/sound/tegra_i2s.c
@@ -4,7 +4,6 @@
* Written by Simon Glass <sjg@chromium.org>
*/
#define LOG_CATEGORY UCLASS_I2S
-#define LOG_DEBUG
#include <common.h>
#include <dm.h>
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 7155d4a..ee30110 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -11,6 +11,7 @@
#include <log.h>
#include <malloc.h>
#include <spi.h>
+#include <spi-mem.h>
#include <dm/device_compat.h>
#include <asm/global_data.h>
#include <dm/device-internal.h>
@@ -199,6 +200,16 @@
ops->set_mode += gd->reloc_off;
if (ops->cs_info)
ops->cs_info += gd->reloc_off;
+ if (ops->mem_ops) {
+ struct spi_controller_mem_ops *mem_ops =
+ (struct spi_controller_mem_ops *)ops->mem_ops;
+ if (mem_ops->adjust_op_size)
+ mem_ops->adjust_op_size += gd->reloc_off;
+ if (mem_ops->supports_op)
+ mem_ops->supports_op += gd->reloc_off;
+ if (mem_ops->exec_op)
+ mem_ops->exec_op += gd->reloc_off;
+ }
reloc_done++;
}
#endif
diff --git a/drivers/timer/sandbox_timer.c b/drivers/timer/sandbox_timer.c
index 2075cd4..c846bfb 100644
--- a/drivers/timer/sandbox_timer.c
+++ b/drivers/timer/sandbox_timer.c
@@ -38,7 +38,8 @@
{
struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
- if (dev_read_bool(dev, "sandbox,timebase-frequency-fallback"))
+ if (CONFIG_IS_ENABLED(CPU) &&
+ dev_read_bool(dev, "sandbox,timebase-frequency-fallback"))
return timer_timebase_fallback(dev);
else if (!uc_priv->clock_rate)
uc_priv->clock_rate = SANDBOX_TIMER_RATE;
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
index 6f00a5d..73b4a5c 100644
--- a/drivers/timer/timer-uclass.c
+++ b/drivers/timer/timer-uclass.c
@@ -83,11 +83,7 @@
return 0;
}
-/*
- * TODO: should be CONFIG_IS_ENABLED(CPU), but the SPL config has _SUPPORT on
- * the end...
- */
-#if defined(CONFIG_CPU) || defined(CONFIG_SPL_CPU_SUPPORT)
+#if CONFIG_IS_ENABLED(CPU)
int timer_timebase_fallback(struct udevice *dev)
{
struct udevice *cpu;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 667157c..63ae2ba 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -241,7 +241,7 @@
config VIDEO_COREBOOT
bool "Enable coreboot framebuffer driver support"
- depends on X86 && SYS_COREBOOT
+ depends on X86
help
Turn on this option to enable a framebuffer driver when U-Boot is
loaded by coreboot where the graphics device is configured by
diff --git a/drivers/video/coreboot.c b/drivers/video/coreboot.c
index 0a5fb08..7237542 100644
--- a/drivers/video/coreboot.c
+++ b/drivers/video/coreboot.c
@@ -5,9 +5,10 @@
#include <common.h>
#include <dm.h>
+#include <init.h>
#include <vbe.h>
#include <video.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
static int save_vesa_mode(struct cb_framebuffer *fb,
struct vesa_mode_info *vesa)
@@ -17,7 +18,7 @@
* running on the serial console.
*/
if (!fb)
- return -ENXIO;
+ return log_msg_ret("save", -ENXIO);
vesa->x_resolution = fb->x_resolution;
vesa->y_resolution = fb->y_resolution;
@@ -44,16 +45,23 @@
struct vesa_mode_info *vesa = &mode_info.vesa;
int ret;
+ if (ll_boot_init())
+ return log_msg_ret("ll", -ENODEV);
+
printf("Video: ");
/* Initialize vesa_mode_info structure */
ret = save_vesa_mode(fb, vesa);
- if (ret)
+ if (ret) {
+ ret = log_msg_ret("save", ret);
goto err;
+ }
ret = vbe_setup_video_priv(vesa, uc_priv, plat);
- if (ret)
+ if (ret) {
+ ret = log_msg_ret("setup", ret);
goto err;
+ }
printf("%dx%dx%d\n", uc_priv->xsize, uc_priv->ysize,
vesa->bits_per_pixel);
@@ -61,7 +69,7 @@
return 0;
err:
- printf("No video mode configured in coreboot!\n");
+ printf("No video mode configured in coreboot (err=%d)\n", ret);
return ret;
}
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c
index 9007aa7..415ea28 100644
--- a/fs/cbfs/cbfs.c
+++ b/fs/cbfs/cbfs.c
@@ -79,6 +79,57 @@
dest->offset = be32_to_cpu(src->offset);
}
+/**
+ * fill_node() - Fill a node struct with information from the CBFS
+ *
+ * @node: Node to fill
+ * @start: Pointer to the start of the CBFS file in memory
+ * @header: Pointer to the header information (in our enddianess)
+ * @return 0 if OK, -EBADF if the header is too small
+ */
+static int fill_node(struct cbfs_cachenode *node, void *start,
+ struct cbfs_fileheader *header)
+{
+ uint name_len;
+ uint offset;
+
+ /* Check the header is large enough */
+ if (header->offset < sizeof(struct cbfs_fileheader))
+ return -EBADF;
+
+ node->next = NULL;
+ node->type = header->type;
+ node->data = start + header->offset;
+ node->data_length = header->len;
+ name_len = header->offset - sizeof(struct cbfs_fileheader);
+ node->name = start + sizeof(struct cbfs_fileheader);
+ node->name_length = name_len;
+ node->attr_offset = header->attributes_offset;
+ node->comp_algo = CBFS_COMPRESS_NONE;
+ node->decomp_size = 0;
+
+ for (offset = node->attr_offset; offset < header->offset;) {
+ const struct cbfs_file_attribute *attr;
+ uint tag, len;
+
+ attr = start + offset;
+ tag = be32_to_cpu(attr->tag);
+ len = be32_to_cpu(attr->len);
+ if (tag == CBFS_FILE_ATTR_TAG_COMPRESSION) {
+ struct cbfs_file_attr_compression *comp;
+
+ comp = start + offset;
+ node->comp_algo = be32_to_cpu(comp->compression);
+ node->decomp_size =
+ be32_to_cpu(comp->decompressed_size);
+ }
+
+ offset += len;
+ }
+
+ return 0;
+}
+
/*
* Given a starting position in memory, scan forward, bounded by a size, and
* find the next valid CBFS file. No memory is allocated by this function. The
@@ -87,7 +138,7 @@
* @param start The location in memory to start from.
* @param size The size of the memory region to search.
* @param align The alignment boundaries to check on.
- * @param new_node A pointer to the file structure to load.
+ * @param node A pointer to the file structure to load.
* @param used A pointer to the count of of bytes scanned through,
* including the file if one is found.
*
@@ -95,7 +146,7 @@
* is found.
*/
static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size,
- int align, struct cbfs_cachenode *new_node,
+ int align, struct cbfs_cachenode *node,
int *used)
{
struct cbfs_fileheader header;
@@ -104,8 +155,7 @@
while (size >= align) {
const struct cbfs_fileheader *file_header = start;
- u32 name_len;
- u32 step;
+ int ret;
/* Check if there's a file here. */
if (memcmp(good_file_magic, &file_header->magic,
@@ -117,25 +167,13 @@
}
swap_file_header(&header, file_header);
- if (header.offset < sizeof(struct cbfs_fileheader)) {
+ ret = fill_node(node, start, &header);
+ if (ret) {
priv->result = CBFS_BAD_FILE;
- return -EBADF;
+ return log_msg_ret("fill", ret);
}
- new_node->next = NULL;
- new_node->type = header.type;
- new_node->data = start + header.offset;
- new_node->data_length = header.len;
- name_len = header.offset - sizeof(struct cbfs_fileheader);
- new_node->name = (char *)file_header +
- sizeof(struct cbfs_fileheader);
- new_node->name_length = name_len;
- new_node->attributes_offset = header.attributes_offset;
- step = header.len;
- if (step % align)
- step = step + align - step % align;
-
- *used += step;
+ *used += ALIGN(header.len, align);
return 0;
}
@@ -146,7 +184,7 @@
static int file_cbfs_fill_cache(struct cbfs_priv *priv, int size, int align)
{
struct cbfs_cachenode *cache_node;
- struct cbfs_cachenode *new_node;
+ struct cbfs_cachenode *node;
struct cbfs_cachenode **cache_tail = &priv->file_cache;
void *start;
@@ -164,21 +202,20 @@
int used;
int ret;
- new_node = (struct cbfs_cachenode *)
- malloc(sizeof(struct cbfs_cachenode));
- if (!new_node)
+ node = malloc(sizeof(struct cbfs_cachenode));
+ if (!node)
return -ENOMEM;
- ret = file_cbfs_next_file(priv, start, size, align, new_node,
+ ret = file_cbfs_next_file(priv, start, size, align, node,
&used);
if (ret < 0) {
- free(new_node);
+ free(node);
if (ret == -ENOENT)
break;
return ret;
}
- *cache_tail = new_node;
- cache_tail = &new_node->next;
+ *cache_tail = node;
+ cache_tail = &node->next;
size -= used;
start += used;
@@ -276,18 +313,26 @@
return cbfs_init(&cbfs_s, end_of_rom);
}
-int cbfs_init_mem(ulong base, struct cbfs_priv **privp)
+int cbfs_init_mem(ulong base, ulong size, bool require_hdr,
+ struct cbfs_priv **privp)
{
struct cbfs_priv priv_s, *priv = &priv_s;
int ret;
/*
- * Use a local variable to start with until we know that the CBFS is
- * valid.
+ * Use a local variable to start with until we know that the * CBFS is
+ * valid. Note that size is detected from the header, if present,
+ * meaning the parameter is ignored.
*/
ret = cbfs_load_header_ptr(priv, base);
- if (ret)
- return ret;
+ if (ret) {
+ if (require_hdr || size == CBFS_SIZE_UNKNOWN)
+ return ret;
+ memset(priv, '\0', sizeof(struct cbfs_priv));
+ priv->header.rom_size = size;
+ priv->header.align = CBFS_ALIGN_SIZE;
+ priv->start = (void *)base;
+ }
ret = file_cbfs_fill_cache(priv, priv->header.rom_size,
priv->header.align);
@@ -317,6 +362,17 @@
}
}
+const struct cbfs_cachenode *cbfs_get_first(const struct cbfs_priv *priv)
+{
+ return priv->file_cache;
+}
+
+void cbfs_get_next(const struct cbfs_cachenode **filep)
+{
+ if (*filep)
+ *filep = (*filep)->next;
+}
+
const struct cbfs_cachenode *file_cbfs_get_first(void)
{
struct cbfs_priv *priv = &cbfs_s;
diff --git a/include/cbfs.h b/include/cbfs.h
index 5f296d6..ae94f1d 100644
--- a/include/cbfs.h
+++ b/include/cbfs.h
@@ -9,6 +9,8 @@
#include <compiler.h>
#include <linux/compiler.h>
+struct cbfs_priv;
+
enum cbfs_result {
CBFS_SUCCESS = 0,
CBFS_NOT_INITIALIZED,
@@ -42,6 +44,8 @@
enum {
CBFS_HEADER_MAGIC = 0x4f524243,
+ CBFS_SIZE_UNKNOWN = 0xffffffff,
+ CBFS_ALIGN_SIZE = 0x40,
};
/**
@@ -68,8 +72,54 @@
/* offset to struct cbfs_file_attribute or 0 */
u32 attributes_offset;
u32 offset;
+ char filename[];
} __packed;
+/**
+ * These are standard values for the known compression alogrithms that coreboot
+ * knows about for stages and payloads. Of course, other CBFS users can use
+ * whatever values they want, as long as they understand them.
+ */
+#define CBFS_COMPRESS_NONE 0
+#define CBFS_COMPRESS_LZMA 1
+#define CBFS_COMPRESS_LZ4 2
+
+/*
+ * Depending on how the header was initialized, it may be backed with 0x00 or
+ * 0xff, so support both
+ */
+#define CBFS_FILE_ATTR_TAG_UNUSED 0
+#define CBFS_FILE_ATTR_TAG_UNUSED2 0xffffffff
+#define CBFS_FILE_ATTR_TAG_COMPRESSION 0x42435a4c
+#define CBFS_FILE_ATTR_TAG_HASH 0x68736148
+
+/*
+ * The common fields of extended cbfs file attributes. Attributes are expected
+ * to start with tag/len, then append their specific fields
+ */
+struct cbfs_file_attribute {
+ u32 tag;
+ /* len covers the whole structure, incl. tag and len */
+ u32 len;
+ u8 data[0];
+} __packed;
+
+struct cbfs_file_attr_compression {
+ u32 tag;
+ u32 len;
+ /* whole file compression format. 0 if no compression. */
+ u32 compression;
+ u32 decompressed_size;
+} __packed;
+
+struct cbfs_file_attr_hash {
+ u32 tag;
+ u32 len;
+ u32 hash_type;
+ /* hash_data is len - sizeof(struct) bytes */
+ u8 hash_data[];
+} __packed;
+
struct cbfs_cachenode {
struct cbfs_cachenode *next;
void *data;
@@ -77,7 +127,9 @@
u32 type;
u32 data_length;
u32 name_length;
- u32 attributes_offset;
+ u32 attr_offset;
+ u32 comp_algo;
+ u32 decomp_size;
};
/**
@@ -111,6 +163,21 @@
const struct cbfs_header *file_cbfs_get_header(void);
/**
+ * cbfs_get_first() - Get the first file in a CBFS
+ *
+ * @return pointer to first file, or NULL if it is empty
+ */
+const struct cbfs_cachenode *cbfs_get_first(const struct cbfs_priv *priv);
+
+/**
+ * cbfs_get_next() - Get the next file in a CBFS
+ *
+ * @filep: Pointer to current file; updated to point to the next file, if any,
+ * else NULL
+ */
+void cbfs_get_next(const struct cbfs_cachenode **filep);
+
+/**
* file_cbfs_get_first() - Get a handle for the first file in CBFS.
*
* @return A handle for the first file in CBFS, NULL on error.
@@ -133,8 +200,6 @@
*/
const struct cbfs_cachenode *file_cbfs_find(const char *name);
-struct cbfs_priv;
-
/**
* cbfs_find_file() - Find a file in a given CBFS
*
@@ -149,11 +214,13 @@
* cbfs_init_mem() - Set up a new CBFS
*
* @base: Base address of CBFS
+ * @size: Size of CBFS if known, else CBFS_SIZE_UNKNOWN
+ * @require_header: true to read a header at the start, false to not require one
* @cbfsp: Returns a pointer to CBFS on success
* @return 0 if OK, -ve on error
*/
-int cbfs_init_mem(ulong base, struct cbfs_priv **privp);
-
+int cbfs_init_mem(ulong base, ulong size, bool require_hdr,
+ struct cbfs_priv **privp);
/***************************************************************************/
/* All of the functions below can be used without first initializing CBFS. */
diff --git a/include/command.h b/include/command.h
index 747f8f8..137cfbc 100644
--- a/include/command.h
+++ b/include/command.h
@@ -389,6 +389,14 @@
return 0; \
}
+#define _CMD_REMOVE_REP(_name, _cmd) \
+ int __remove_ ## _name(void) \
+ { \
+ if (0) \
+ _cmd(NULL, 0, 0, NULL, NULL); \
+ return 0; \
+ }
+
#define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep, \
_usage, _help, _comp) \
{ #_name, _maxargs, 0 ? _cmd_rep : NULL, NULL, _usage, \
@@ -405,7 +413,7 @@
#define U_BOOT_CMDREP_COMPLETE(_name, _maxargs, _cmd_rep, _usage, \
_help, _comp) \
- _CMD_REMOVE(sub_ ## _name, _cmd_rep)
+ _CMD_REMOVE_REP(sub_ ## _name, _cmd_rep)
#endif /* CONFIG_CMDLINE */
diff --git a/include/configs/chromebook_coral.h b/include/configs/chromebook_coral.h
index 6e8e8ec..00760b8 100644
--- a/include/configs/chromebook_coral.h
+++ b/include/configs/chromebook_coral.h
@@ -12,13 +12,13 @@
#define CONFIG_BOOTCOMMAND \
"tpm init; tpm startup TPM2_SU_CLEAR; " \
- "read mmc 2:2 100000 0 80; setexpr loader *001004f0; " \
+ "read mmc 0:2 100000 0 80; setexpr loader *001004f0; " \
"setexpr size *00100518; setexpr blocks $size / 200; " \
- "read mmc 2:2 100000 80 $blocks; setexpr setup $loader - 1000; " \
+ "read mmc 0:2 100000 80 $blocks; setexpr setup $loader - 1000; " \
"setexpr cmdline_ptr $loader - 2000; " \
"setexpr.s cmdline *$cmdline_ptr; " \
"setexpr cmdline gsub %U \\\\${uuid}; " \
- "if part uuid mmc 2:2 uuid; then " \
+ "if part uuid mmc 0:2 uuid; then " \
"zboot start 100000 0 0 0 $setup cmdline; " \
"zboot load; zboot setup; zboot dump; zboot go;" \
"fi"
diff --git a/include/dm/of_extra.h b/include/dm/of_extra.h
index ca15df2..fc4f974 100644
--- a/include/dm/of_extra.h
+++ b/include/dm/of_extra.h
@@ -11,7 +11,11 @@
enum fmap_compress_t {
FMAP_COMPRESS_NONE,
+ FMAP_COMPRESS_LZMA,
FMAP_COMPRESS_LZ4,
+
+ FMAP_COMPRESS_COUNT,
+ FMAP_COMPRESS_UNKNOWN,
};
enum fmap_hash_t {
@@ -30,6 +34,10 @@
enum fmap_hash_t hash_algo; /* Hash algorithm */
const uint8_t *hash; /* Hash value */
int hash_size; /* Hash size */
+ /* Node pointer if CBFS, else NULL */
+ const struct cbfs_cachenode *cbfs_node;
+ /* Hash node pointer if CBFS, else NULL */
+ const struct cbfs_cachenode *cbfs_hash_node;
};
/**
diff --git a/include/image.h b/include/image.h
index 138c83d..bcd126d 100644
--- a/include/image.h
+++ b/include/image.h
@@ -886,6 +886,11 @@
}
static inline int image_check_arch(const image_header_t *hdr, uint8_t arch)
{
+#ifndef USE_HOSTCC
+ /* Let's assume that sandbox can load any architecture */
+ if (IS_ENABLED(CONFIG_SANDBOX))
+ return true;
+#endif
return (image_get_arch(hdr) == arch) ||
(image_get_arch(hdr) == IH_ARCH_ARM && arch == IH_ARCH_ARM64);
}
diff --git a/include/malloc.h b/include/malloc.h
index e15e528..024b18b 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -880,6 +880,8 @@
#else
+void malloc_simple_info(void);
+
#if CONFIG_IS_ENABLED(SYS_MALLOC_SIMPLE)
#define malloc malloc_simple
#define realloc realloc_simple
@@ -887,7 +889,6 @@
static inline void free(void *ptr) {}
void *calloc(size_t nmemb, size_t size);
void *realloc_simple(void *ptr, size_t size);
-void malloc_simple_info(void);
#else
# ifdef USE_DL_PREFIX
diff --git a/include/sandboxblockdev.h b/include/sandboxblockdev.h
index c1f0afb..4006e94 100644
--- a/include/sandboxblockdev.h
+++ b/include/sandboxblockdev.h
@@ -14,6 +14,13 @@
int fd;
};
-int host_dev_bind(int dev, char *filename);
+/**
+ * host_dev_bind() - Bind or unbind a device
+ *
+ * @dev: Device number (0=first slot)
+ * @filename: Host filename to use, or NULL to unbind
+ * @removable: true if the block device should mark itself as removable
+ */
+int host_dev_bind(int dev, char *filename, bool removable);
#endif
diff --git a/include/smbios.h b/include/smbios.h
index ecc4fd1..ffeefb4 100644
--- a/include/smbios.h
+++ b/include/smbios.h
@@ -14,6 +14,10 @@
#define SMBIOS_MAJOR_VER 3
#define SMBIOS_MINOR_VER 0
+enum {
+ SMBIOS_STR_MAX = 64, /* Maximum length allowed for a string */
+};
+
/* SMBIOS structure types */
enum {
SMBIOS_BIOS_INFORMATION = 0,
@@ -269,4 +273,20 @@
*/
int smbios_update_version(const char *version);
+/**
+ * smbios_update_version_full() - Update the version string
+ *
+ * This can be called after the SMBIOS tables are written (e.g. after the U-Boot
+ * main loop has started) to update the BIOS version string (SMBIOS table 0).
+ * It scans for the correct place to put the version, so does not need U-Boot
+ * to have actually written the tables itself (e.g. if a previous bootloader
+ * did it).
+ *
+ * @smbios_tab: Start of SMBIOS tables
+ * @version: New version string to use
+ * @return 0 if OK, -ENOENT if no version string was previously written,
+ * -ENOSPC if the new string is too large to fit
+ */
+int smbios_update_version_full(void *smbios_tab, const char *version);
+
#endif /* _SMBIOS_H_ */
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 85cae32..3d747c9 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -35,6 +35,19 @@
int (*write)(struct udevice *dev, u32 offset, size_t len,
const void *buf);
int (*erase)(struct udevice *dev, u32 offset, size_t len);
+ /**
+ * get_sw_write_prot() - Check state of software write-protect feature
+ *
+ * SPI flash chips can lock a region of the flash defined by a
+ * 'protected area'. This function checks if this protected area is
+ * defined.
+ *
+ * @dev: SPI flash device
+ * @return 0 if no region is write-protected, 1 if a region is
+ * write-protected, -ENOSYS if the driver does not implement this,
+ * other -ve value on error
+ */
+ int (*get_sw_write_prot)(struct udevice *dev);
};
/* Access the serial operations for a device */
@@ -77,6 +90,20 @@
int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len);
/**
+ * spl_flash_get_sw_write_prot() - Check state of software write-protect feature
+ *
+ * SPI flash chips can lock a region of the flash defined by a
+ * 'protected area'. This function checks if this protected area is
+ * defined.
+ *
+ * @dev: SPI flash device
+ * @return 0 if no region is write-protected, 1 if a region is
+ * write-protected, -ENOSYS if the driver does not implement this,
+ * other -ve value on error
+ */
+int spl_flash_get_sw_write_prot(struct udevice *dev);
+
+/**
* spi_flash_std_probe() - Probe a SPI flash device
*
* This is the standard internal method for probing a SPI flash device to
@@ -97,7 +124,9 @@
unsigned int max_hz, unsigned int spi_mode);
/* Compatibility function - this is the old U-Boot API */
-void spi_flash_free(struct spi_flash *flash);
+static inline void spi_flash_free(struct spi_flash *flash)
+{
+}
static inline int spi_flash_read(struct spi_flash *flash, u32 offset,
size_t len, void *buf)
diff --git a/include/sysinfo.h b/include/sysinfo.h
index 270ac1b..68fad25 100644
--- a/include/sysinfo.h
+++ b/include/sysinfo.h
@@ -37,9 +37,13 @@
enum sysinfo_id {
SYSINFO_ID_NONE,
+ /* For SMBIOS tables */
SYSINFO_ID_SMBIOS_SYSTEM_VERSION,
SYSINFO_ID_SMBIOS_BASEBOARD_VERSION,
+ /* For show_board_info() */
+ SYSINFO_ID_BOARD_MODEL,
+
/* First value available for downstream/board used */
SYSINFO_ID_USER = 0x1000,
};
diff --git a/lib/Kconfig b/lib/Kconfig
index 7288340..80ff244 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -642,7 +642,7 @@
config BLOBLIST_TABLES
bool "Put tables in a bloblist"
- depends on X86
+ depends on X86 && BLOBLIST
help
Normally tables are placed at address 0xf0000 and can be up to 64KB
long. With this option, tables are instead placed in the bloblist
diff --git a/lib/binman.c b/lib/binman.c
index 6040ec8..530df6a 100644
--- a/lib/binman.c
+++ b/lib/binman.c
@@ -128,8 +128,8 @@
if (!ofnode_valid(node))
return log_msg_ret("node", -ENOENT);
binman->image = node;
- log_debug("binman: Selected image subnode '%s'\n",
- ofnode_get_name(binman->image));
+ log_info("binman: Selected image subnode '%s'\n",
+ ofnode_get_name(binman->image));
return 0;
}
diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
index b89f988..34203f9 100644
--- a/lib/smbios-parser.c
+++ b/lib/smbios-parser.c
@@ -3,6 +3,8 @@
* Copyright (C) 2020, Bachmann electronic GmbH
*/
+#define LOG_CATEGORY LOGC_BOOT
+
#include <common.h>
#include <smbios.h>
@@ -94,3 +96,39 @@
return string_from_smbios_table(header, index);
}
+
+int smbios_update_version_full(void *smbios_tab, const char *version)
+{
+ const struct smbios_header *hdr;
+ struct smbios_type0 *bios;
+ uint old_len, len;
+ char *ptr;
+
+ log_info("Updating SMBIOS table at %p\n", smbios_tab);
+ hdr = smbios_header(smbios_tab, SMBIOS_BIOS_INFORMATION);
+ if (!hdr)
+ return log_msg_ret("tab", -ENOENT);
+ bios = (struct smbios_type0 *)hdr;
+ ptr = (char *)smbios_string(hdr, bios->bios_ver);
+ if (!ptr)
+ return log_msg_ret("str", -ENOMEDIUM);
+
+ /*
+ * This string is supposed to have at least enough bytes and is
+ * padded with spaces. Update it, taking care not to move the
+ * \0 terminator, so that other strings in the string table
+ * are not disturbed. See smbios_add_string()
+ */
+ old_len = strnlen(ptr, SMBIOS_STR_MAX);
+ len = strnlen(version, SMBIOS_STR_MAX);
+ if (len > old_len)
+ return log_ret(-ENOSPC);
+
+ log_debug("Replacing SMBIOS type 0 version string '%s'\n", ptr);
+ memcpy(ptr, version, len);
+#ifdef LOG_DEBUG
+ print_buffer((ulong)ptr, ptr, 1, old_len + 1, 0);
+#endif
+
+ return 0;
+}
diff --git a/lib/smbios.c b/lib/smbios.c
index 7d463c8..9eb226e 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -20,10 +20,6 @@
DECLARE_GLOBAL_DATA_PTR;
-enum {
- SMBIOS_STR_MAX = 64, /* Maximum length allowed for a string */
-};
-
/**
* struct smbios_ctx - context for writing SMBIOS tables
*
diff --git a/test/cmd/test_echo.c b/test/cmd/test_echo.c
index aa5cebc..9d60d7d 100644
--- a/test/cmd/test_echo.c
+++ b/test/cmd/test_echo.c
@@ -44,9 +44,10 @@
int i;
for (i = 0; i < ARRAY_SIZE(echo_data); ++i) {
+ ut_silence_console(uts);
console_record_reset_enable();
ut_assertok(run_command(echo_data[i].cmd, 0));
- gd->flags &= ~GD_FLG_RECORD;
+ ut_unsilence_console(uts);
console_record_readline(uts->actual_str,
sizeof(uts->actual_str));
ut_asserteq_str(echo_data[i].expected, uts->actual_str);
diff --git a/test/dm/sf.c b/test/dm/sf.c
index cc1fc4d..17d43fe 100644
--- a/test/dm/sf.c
+++ b/test/dm/sf.c
@@ -21,7 +21,7 @@
/* Simple test of sandbox SPI flash */
static int dm_test_spi_flash(struct unit_test_state *uts)
{
- struct udevice *dev;
+ struct udevice *dev, *emul;
int full_size = 0x200000;
int size = 0x10000;
u8 *src, *dst;
@@ -51,6 +51,14 @@
ut_assertok(spi_flash_read_dm(dev, 0, size, dst));
ut_asserteq_mem(src, dst, size);
+ /* Try the write-protect stuff */
+ ut_assertok(uclass_first_device_err(UCLASS_SPI_EMUL, &emul));
+ ut_asserteq(0, spl_flash_get_sw_write_prot(dev));
+ sandbox_sf_set_block_protect(emul, 1);
+ ut_asserteq(1, spl_flash_get_sw_write_prot(dev));
+ sandbox_sf_set_block_protect(emul, 0);
+ ut_asserteq(0, spl_flash_get_sw_write_prot(dev));
+
/* Check mapping */
ut_assertok(dm_spi_get_mmap(dev, &map_base, &map_size, &offset));
ut_asserteq(0x1000, map_base);
diff --git a/test/lib/test_print.c b/test/lib/test_print.c
index 12972f1..a60a5a5 100644
--- a/test/lib/test_print.c
+++ b/test/lib/test_print.c
@@ -18,12 +18,14 @@
static int test_print_freq(struct unit_test_state *uts,
uint64_t freq, char *expected)
{
+ ut_silence_console(uts);
console_record_reset_enable();
print_freq(freq, ";\n");
- gd->flags &= ~GD_FLG_RECORD;
+ ut_unsilence_console(uts);
console_record_readline(uts->actual_str, sizeof(uts->actual_str));
ut_asserteq_str(expected, uts->actual_str);
ut_assertok(ut_check_console_end(uts));
+
return 0;
}
@@ -46,12 +48,14 @@
static int test_print_size(struct unit_test_state *uts,
uint64_t freq, char *expected)
{
+ ut_silence_console(uts);
console_record_reset_enable();
print_size(freq, ";\n");
- gd->flags &= ~GD_FLG_RECORD;
+ ut_unsilence_console(uts);
console_record_readline(uts->actual_str, sizeof(uts->actual_str));
ut_asserteq_str(expected, uts->actual_str);
ut_assertok(ut_check_console_end(uts));
+
return 0;
}
diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst
index 15314d1..1aa2459 100644
--- a/tools/binman/binman.rst
+++ b/tools/binman/binman.rst
@@ -472,6 +472,13 @@
information about what needs to be fixed. See missing-blob-help for the
message for each tag.
+no-expanded:
+ By default binman substitutes entries with expanded versions if available,
+ so that a `u-boot` entry type turns into `u-boot-expanded`, for example. The
+ `--no-expanded` command-line option disables this globally. The
+ `no-expanded` property disables this just for a single entry. Put the
+ `no-expanded` boolean property in the node to select this behaviour.
+
The attributes supported for images and sections are described below. Several
are similar to those for entries.
@@ -555,6 +562,13 @@
'end-at-4gb' property is not applicable where CONFIG_SYS_TEXT_BASE +
Image size != 4gb.
+align-default:
+ Specifies the default alignment for entries in this section, if they do
+ not specify an alignment. Note that this only applies to top-level entries
+ in the section (direct subentries), not any subentries of those entries.
+ This means that each section must specify its own default alignment, if
+ required.
+
Examples of the above options can be found in the tests. See the
tools/binman/test directory.
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index f6faa15..a91211e 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -248,6 +248,19 @@
+Entry: collection: An entry which contains a collection of other entries
+------------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - content: List of phandles to entries to include
+
+This allows reusing the contents of other entries. The contents of the
+listed entries are combined to form this entry. This serves as a useful
+base class for entry types which need to process data from elsewhere in
+the image, not necessarily child entries.
+
+
+
Entry: cros-ec-rw: A blob entry which contains a Chromium OS read-write EC image
--------------------------------------------------------------------------------
@@ -783,6 +796,8 @@
file, since the first 16 bytes are skipped when writing.
name-prefix: Adds a prefix to the name of every entry in the section
when writing out the map
+ align_default: Default alignment for this section, if no alignment is
+ given in the entry
Properties:
allow_missing: True if this section permits external blobs to be
@@ -863,7 +878,7 @@
in the binman README for more information.
Note that this entry is automatically replaced with u-boot-expanded unless
---no-expanded is used.
+--no-expanded is used or the node has a 'no-expanded' property.
@@ -984,7 +999,7 @@
binman uses that to look up symbols to write into the SPL binary.
Note that this entry is automatically replaced with u-boot-spl-expanded
-unless --no-expanded is used.
+unless --no-expanded is used or the node has a 'no-expanded' property.
@@ -1113,7 +1128,7 @@
binman uses that to look up symbols to write into the TPL binary.
Note that this entry is automatically replaced with u-boot-tpl-expanded
-unless --no-expanded is used.
+unless --no-expanded is used or the node has a 'no-expanded' property.
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 1cfa024..7022271 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -164,7 +164,8 @@
if obj and expanded:
# Check whether to use the expanded entry
new_etype = etype + '-expanded'
- if obj.UseExpanded(node, etype, new_etype):
+ can_expand = not fdt_util.GetBool(node, 'no-expanded')
+ if can_expand and obj.UseExpanded(node, etype, new_etype):
etype = new_etype
else:
obj = None
@@ -200,6 +201,8 @@
if tools.NotPowerOfTwo(self.align):
raise ValueError("Node '%s': Alignment %s must be a power of two" %
(self._node.path, self.align))
+ if self.section and self.align is None:
+ self.align = self.section.align_default
self.pad_before = fdt_util.GetInt(self._node, 'pad-before', 0)
self.pad_after = fdt_util.GetInt(self._node, 'pad-after', 0)
self.align_size = fdt_util.GetInt(self._node, 'align-size')
@@ -437,6 +440,11 @@
"""Convenience function to raise an error referencing a node"""
raise ValueError("Node '%s': %s" % (self._node.path, msg))
+ def Info(self, msg):
+ """Convenience function to log info referencing a node"""
+ tag = "Info '%s'" % self._node.path
+ tout.Detail('%30s: %s' % (tag, msg))
+
def Detail(self, msg):
"""Convenience function to log detail referencing a node"""
tag = "Node '%s'" % self._node.path
@@ -476,9 +484,13 @@
"""
return self._node.path
- def GetData(self):
+ def GetData(self, required=True):
"""Get the contents of an entry
+ Args:
+ required: True if the data must be present, False if it is OK to
+ return None
+
Returns:
bytes content of the entry, excluding any padding. If the entry is
compressed, the compressed data is returned
diff --git a/tools/binman/etype/cbfs.py b/tools/binman/etype/cbfs.py
index 1daddeb..44db7b9 100644
--- a/tools/binman/etype/cbfs.py
+++ b/tools/binman/etype/cbfs.py
@@ -169,6 +169,7 @@
super().__init__(section, etype, node)
self._cbfs_arg = fdt_util.GetString(node, 'cbfs-arch', 'x86')
+ self.align_default = None
self._cbfs_entries = OrderedDict()
self._ReadSubnodes()
self.reader = None
diff --git a/tools/binman/etype/collection.py b/tools/binman/etype/collection.py
new file mode 100644
index 0000000..1625575
--- /dev/null
+++ b/tools/binman/etype/collection.py
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+# Support for a collection of entries from other parts of an image
+
+from collections import OrderedDict
+import os
+
+from binman.entry import Entry
+from dtoc import fdt_util
+
+class Entry_collection(Entry):
+ """An entry which contains a collection of other entries
+
+ Properties / Entry arguments:
+ - content: List of phandles to entries to include
+
+ This allows reusing the contents of other entries. The contents of the
+ listed entries are combined to form this entry. This serves as a useful
+ base class for entry types which need to process data from elsewhere in
+ the image, not necessarily child entries.
+ """
+ def __init__(self, section, etype, node):
+ super().__init__(section, etype, node)
+ self.content = fdt_util.GetPhandleList(self._node, 'content')
+ if not self.content:
+ self.Raise("Collection must have a 'content' property")
+
+ def GetContents(self, required):
+ """Get the contents of this entry
+
+ Args:
+ required: True if the data must be present, False if it is OK to
+ return None
+
+ Returns:
+ bytes content of the entry
+ """
+ # Join up all the data
+ self.Info('Getting contents, required=%s' % required)
+ data = b''
+ for entry_phandle in self.content:
+ entry_data = self.section.GetContentsByPhandle(entry_phandle, self,
+ required)
+ if not required and entry_data is None:
+ self.Info('Contents not available yet')
+ # Data not available yet
+ return None
+ data += entry_data
+
+ self.Info('Returning contents size %x' % len(data))
+
+ return data
+
+ def ObtainContents(self):
+ data = self.GetContents(False)
+ if data is None:
+ return False
+ self.SetContents(data)
+ return True
+
+ def ProcessContents(self):
+ # The blob may have changed due to WriteSymbols()
+ data = self.GetContents(True)
+ return self.ProcessContentsUpdate(data)
diff --git a/tools/binman/etype/mkimage.py b/tools/binman/etype/mkimage.py
index e9f8272..e499775 100644
--- a/tools/binman/etype/mkimage.py
+++ b/tools/binman/etype/mkimage.py
@@ -36,6 +36,7 @@
super().__init__(section, etype, node)
self._args = fdt_util.GetString(self._node, 'args').split(' ')
self._mkimage_entries = OrderedDict()
+ self.align_default = None
self._ReadSubnodes()
def ObtainContents(self):
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index cce1500..c3bac02 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -36,6 +36,8 @@
file, since the first 16 bytes are skipped when writing.
name-prefix: Adds a prefix to the name of every entry in the section
when writing out the map
+ align_default: Default alignment for this section, if no alignment is
+ given in the entry
Properties:
allow_missing: True if this section permits external blobs to be
@@ -76,6 +78,7 @@
if self._skip_at_start is None:
self._skip_at_start = 0
self._name_prefix = fdt_util.GetString(self._node, 'name-prefix')
+ self.align_default = fdt_util.GetInt(self._node, 'align-default', 0)
filename = fdt_util.GetString(self._node, 'filename')
if filename:
self._filename = filename
@@ -180,7 +183,7 @@
return data
- def _BuildSectionData(self):
+ def _BuildSectionData(self, required):
"""Build the contents of a section
This places all entries at the right place, dealing with padding before
@@ -188,13 +191,20 @@
pad-before and pad-after properties in the section items) since that is
handled by the parent section.
+ Args:
+ required: True if the data must be present, False if it is OK to
+ return None
+
Returns:
Contents of the section (bytes)
"""
section_data = b''
for entry in self._entries.values():
- data = self.GetPaddedDataForEntry(entry, entry.GetData())
+ entry_data = entry.GetData(required)
+ if not required and entry_data is None:
+ return None
+ data = self.GetPaddedDataForEntry(entry, entry_data)
# Handle empty space before the entry
pad = (entry.offset or 0) - self._skip_at_start - len(section_data)
if pad > 0:
@@ -226,18 +236,24 @@
data = self.GetData()
return section.GetPaddedDataForEntry(self, data)
- def GetData(self):
+ def GetData(self, required=True):
"""Get the contents of an entry
This builds the contents of the section, stores this as the contents of
the section and returns it
+ Args:
+ required: True if the data must be present, False if it is OK to
+ return None
+
Returns:
bytes content of the section, made up for all all of its subentries.
This excludes any padding. If the section is compressed, the
compressed data is returned
"""
- data = self._BuildSectionData()
+ data = self._BuildSectionData(required)
+ if data is None:
+ return None
self.SetContents(data)
return data
@@ -263,7 +279,7 @@
self._SortEntries()
self._ExpandEntries()
- data = self._BuildSectionData()
+ data = self._BuildSectionData(True)
self.SetContents(data)
self.CheckSize()
@@ -360,16 +376,20 @@
def GetEntries(self):
return self._entries
- def GetContentsByPhandle(self, phandle, source_entry):
+ def GetContentsByPhandle(self, phandle, source_entry, required):
"""Get the data contents of an entry specified by a phandle
This uses a phandle to look up a node and and find the entry
- associated with it. Then it returnst he contents of that entry.
+ associated with it. Then it returns the contents of that entry.
+
+ The node must be a direct subnode of this section.
Args:
phandle: Phandle to look up (integer)
source_entry: Entry containing that phandle (used for error
reporting)
+ required: True if the data must be present, False if it is OK to
+ return None
Returns:
data from associated entry (as a string), or None if not found
@@ -379,7 +399,7 @@
source_entry.Raise("Cannot find node for phandle %d" % phandle)
for entry in self._entries.values():
if entry._node == node:
- return entry.GetData()
+ return entry.GetData(required)
source_entry.Raise("Cannot find entry for node '%s'" % node.name)
def LookupSymbol(self, sym_name, optional, msg, base_addr, entries=None):
diff --git a/tools/binman/etype/u_boot.py b/tools/binman/etype/u_boot.py
index d2eaba6..e8d180a 100644
--- a/tools/binman/etype/u_boot.py
+++ b/tools/binman/etype/u_boot.py
@@ -25,7 +25,7 @@
in the binman README for more information.
Note that this entry is automatically replaced with u-boot-expanded unless
- --no-expanded is used.
+ --no-expanded is used or the node has a 'no-expanded' property.
"""
def __init__(self, section, etype, node):
super().__init__(section, etype, node)
diff --git a/tools/binman/etype/u_boot_spl.py b/tools/binman/etype/u_boot_spl.py
index 1c39f98..6f79bf5 100644
--- a/tools/binman/etype/u_boot_spl.py
+++ b/tools/binman/etype/u_boot_spl.py
@@ -32,7 +32,7 @@
binman uses that to look up symbols to write into the SPL binary.
Note that this entry is automatically replaced with u-boot-spl-expanded
- unless --no-expanded is used.
+ unless --no-expanded is used or the node has a 'no-expanded' property.
"""
def __init__(self, section, etype, node):
super().__init__(section, etype, node)
diff --git a/tools/binman/etype/u_boot_tpl.py b/tools/binman/etype/u_boot_tpl.py
index 95d9bd6..0c575df 100644
--- a/tools/binman/etype/u_boot_tpl.py
+++ b/tools/binman/etype/u_boot_tpl.py
@@ -32,7 +32,7 @@
binman uses that to look up symbols to write into the TPL binary.
Note that this entry is automatically replaced with u-boot-tpl-expanded
- unless --no-expanded is used.
+ unless --no-expanded is used or the node has a 'no-expanded' property.
"""
def __init__(self, section, etype, node):
super().__init__(section, etype, node)
diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py
index eba5351..c0a6a28 100644
--- a/tools/binman/etype/vblock.py
+++ b/tools/binman/etype/vblock.py
@@ -9,12 +9,13 @@
from collections import OrderedDict
import os
-from binman.entry import Entry, EntryArg
+from binman.entry import EntryArg
+from binman.etype.collection import Entry_collection
from dtoc import fdt_util
from patman import tools
-class Entry_vblock(Entry):
+class Entry_vblock(Entry_collection):
"""An entry which contains a Chromium OS verified boot block
Properties / Entry arguments:
@@ -37,9 +38,6 @@
"""
def __init__(self, section, etype, node):
super().__init__(section, etype, node)
- self.content = fdt_util.GetPhandleList(self._node, 'content')
- if not self.content:
- self.Raise("Vblock must have a 'content' property")
(self.keydir, self.keyblock, self.signprivate, self.version,
self.kernelkey, self.preamble_flags) = self.GetEntryArgsOrProps([
EntryArg('keydir', str),
@@ -49,15 +47,21 @@
EntryArg('kernelkey', str),
EntryArg('preamble-flags', int)])
- def GetVblock(self):
+ def GetVblock(self, required):
+ """Get the contents of this entry
+
+ Args:
+ required: True if the data must be present, False if it is OK to
+ return None
+
+ Returns:
+ bytes content of the entry, which is the signed vblock for the
+ provided data
+ """
# Join up the data files to be signed
- input_data = b''
- for entry_phandle in self.content:
- data = self.section.GetContentsByPhandle(entry_phandle, self)
- if data is None:
- # Data not available yet
- return False
- input_data += data
+ input_data = self.GetContents(required)
+ if input_data is None:
+ return None
uniq = self.GetUniqueName()
output_fname = tools.GetOutputFilename('vblock.%s' % uniq)
@@ -79,13 +83,13 @@
return tools.ReadFile(output_fname)
def ObtainContents(self):
- data = self.GetVblock()
- if data is False:
+ data = self.GetVblock(False)
+ if data is None:
return False
self.SetContents(data)
return True
def ProcessContents(self):
# The blob may have changed due to WriteSymbols()
- data = self.GetVblock()
+ data = self.GetVblock(True)
return self.ProcessContentsUpdate(data)
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 81c213a..89fe661 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -1344,13 +1344,19 @@
data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
- def checkSymbols(self, dts, base_data, u_boot_offset):
+ def checkSymbols(self, dts, base_data, u_boot_offset, entry_args=None,
+ use_expanded=False):
"""Check the image contains the expected symbol values
Args:
dts: Device tree file to use for test
base_data: Data before and after 'u-boot' section
u_boot_offset: Offset of 'u-boot' section in image
+ entry_args: Dict of entry args to supply to binman
+ key: arg name
+ value: value of that arg
+ use_expanded: True to use expanded entries where available, e.g.
+ 'u-boot-expanded' instead of 'u-boot'
"""
elf_fname = self.ElfTestFile('u_boot_binman_syms')
syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
@@ -1359,7 +1365,8 @@
addr)
self._SetupSplElf('u_boot_binman_syms')
- data = self._DoReadFile(dts)
+ data = self._DoReadFileDtb(dts, entry_args=entry_args,
+ use_expanded=use_expanded)[0]
# The image should contain the symbols from u_boot_binman_syms.c
# Note that image_pos is adjusted by the base address of the image,
# which is 0x10 in our test image
@@ -1377,7 +1384,7 @@
def testSymbolsNoDtb(self):
"""Test binman can assign symbols embedded in U-Boot SPL"""
- self.checkSymbols('192_symbols_nodtb.dts',
+ self.checkSymbols('196_symbols_nodtb.dts',
U_BOOT_SPL_NODTB_DATA + U_BOOT_SPL_DTB_DATA,
0x38)
@@ -1711,7 +1718,7 @@
"""Test we detect a vblock which has no content to sign"""
with self.assertRaises(ValueError) as e:
self._DoReadFile('075_vblock_no_content.dts')
- self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
+ self.assertIn("Node '/binman/vblock': Collection must have a 'content' "
'property', str(e.exception))
def testVblockBadPhandle(self):
@@ -4460,5 +4467,47 @@
start += fdt_size + len(U_BOOT_TPL_DATA)
self.assertEqual(len(data), start)
+ def testSymbolsExpanded(self):
+ """Test binman can assign symbols in expanded entries"""
+ entry_args = {
+ 'spl-dtb': '1',
+ }
+ self.checkSymbols('197_symbols_expand.dts', U_BOOT_SPL_NODTB_DATA +
+ U_BOOT_SPL_DTB_DATA, 0x38,
+ entry_args=entry_args, use_expanded=True)
+
+ def testCollection(self):
+ """Test a collection"""
+ data = self._DoReadFile('198_collection.dts')
+ self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA +
+ tools.GetBytes(0xff, 2) + U_BOOT_NODTB_DATA +
+ tools.GetBytes(0xfe, 3) + U_BOOT_DTB_DATA,
+ data)
+
+ def testCollectionSection(self):
+ """Test a collection where a section must be built first"""
+ # Sections never have their contents when GetData() is called, but when
+ # _BuildSectionData() is called with required=True, a section will force
+ # building the contents, producing an error is anything is still
+ # missing.
+ data = self._DoReadFile('199_collection_section.dts')
+ section = U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA
+ self.assertEqual(section + U_BOOT_DATA + tools.GetBytes(0xff, 2) +
+ section + tools.GetBytes(0xfe, 3) + U_BOOT_DATA,
+ data)
+
+ def testAlignDefault(self):
+ """Test that default alignment works on sections"""
+ data = self._DoReadFile('200_align_default.dts')
+ expected = (U_BOOT_DATA + tools.GetBytes(0, 8 - len(U_BOOT_DATA)) +
+ U_BOOT_DATA)
+ # Special alignment for section
+ expected += tools.GetBytes(0, 32 - len(expected))
+ # No alignment within the nested section
+ expected += U_BOOT_DATA + U_BOOT_NODTB_DATA;
+ # Now the final piece, which should be default-aligned
+ expected += tools.GetBytes(0, 88 - len(expected)) + U_BOOT_NODTB_DATA
+ self.assertEqual(expected, data)
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/test/192_symbols_nodtb.dts b/tools/binman/test/196_symbols_nodtb.dts
similarity index 100%
rename from tools/binman/test/192_symbols_nodtb.dts
rename to tools/binman/test/196_symbols_nodtb.dts
diff --git a/tools/binman/test/197_symbols_expand.dts b/tools/binman/test/197_symbols_expand.dts
new file mode 100644
index 0000000..8aee76d
--- /dev/null
+++ b/tools/binman/test/197_symbols_expand.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pad-byte = <0xff>;
+ u-boot-spl {
+ };
+
+ u-boot {
+ offset = <0x38>;
+ no-expanded;
+ };
+
+ u-boot-spl2 {
+ type = "u-boot-spl";
+ };
+ };
+};
diff --git a/tools/binman/test/198_collection.dts b/tools/binman/test/198_collection.dts
new file mode 100644
index 0000000..484a1b0
--- /dev/null
+++ b/tools/binman/test/198_collection.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ collection {
+ content = <&u_boot_nodtb &dtb>;
+ };
+ fill {
+ size = <2>;
+ fill-byte = [ff];
+ };
+ u_boot_nodtb: u-boot-nodtb {
+ };
+ fill2 {
+ type = "fill";
+ size = <3>;
+ fill-byte = [fe];
+ };
+ dtb: u-boot-dtb {
+ };
+ };
+};
diff --git a/tools/binman/test/199_collection_section.dts b/tools/binman/test/199_collection_section.dts
new file mode 100644
index 0000000..03a7319
--- /dev/null
+++ b/tools/binman/test/199_collection_section.dts
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ collection {
+ content = <§ion &u_boot>;
+ };
+ fill {
+ size = <2>;
+ fill-byte = [ff];
+ };
+ section: section {
+ u-boot-nodtb {
+ };
+ u-boot-dtb {
+ };
+ };
+ fill2 {
+ type = "fill";
+ size = <3>;
+ fill-byte = [fe];
+ };
+ u_boot: u-boot {
+ no-expanded;
+ };
+ };
+};
diff --git a/tools/binman/test/200_align_default.dts b/tools/binman/test/200_align_default.dts
new file mode 100644
index 0000000..1b15577
--- /dev/null
+++ b/tools/binman/test/200_align_default.dts
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ align-default = <8>;
+ u-boot {
+ };
+
+ u-boot-align {
+ type = "u-boot";
+ };
+
+ section {
+ align = <32>;
+ u-boot {
+ };
+
+ u-boot-nodtb {
+ };
+ };
+
+ u-boot-nodtb {
+ };
+ };
+};
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index 25ce513..3996971 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -103,6 +103,8 @@
"""A device tree property
Properties:
+ node: Node containing this property
+ offset: Offset of the property (None if still to be synced)
name: Property name (as per the device tree)
value: Property value as a string of bytes, or a list of strings of
bytes
@@ -114,7 +116,7 @@
self.name = name
self.value = None
self.bytes = bytes(data)
- self.dirty = False
+ self.dirty = offset is None
if not data:
self.type = Type.BOOL
self.value = True
@@ -228,9 +230,14 @@
Raises:
FdtException if auto_resize is False and there is not enough space
"""
- if self._offset is None or self.dirty:
+ if self.dirty:
node = self._node
fdt_obj = node._fdt._fdt_obj
+ node_name = fdt_obj.get_name(node._offset)
+ if node_name and node_name != node.name:
+ raise ValueError("Internal error, node '%s' name mismatch '%s'" %
+ (node.path, node_name))
+
if auto_resize:
while fdt_obj.setprop(node.Offset(), self.name, self.bytes,
(libfdt.NOSPACE,)) == -libfdt.NOSPACE:
@@ -239,13 +246,15 @@
fdt_obj.setprop(node.Offset(), self.name, self.bytes)
else:
fdt_obj.setprop(node.Offset(), self.name, self.bytes)
+ self.dirty = False
class Node:
"""A device tree node
Properties:
- offset: Integer offset in the device tree
+ parent: Parent Node
+ offset: Integer offset in the device tree (None if to be synced)
name: Device tree node tname
path: Full path to node, along with the node name itself
_fdt: Device tree object
@@ -324,6 +333,11 @@
fdt_obj = self._fdt._fdt_obj
if self._offset != my_offset:
self._offset = my_offset
+ name = fdt_obj.get_name(self._offset)
+ if name and self.name != name:
+ raise ValueError("Internal error, node '%s' name mismatch '%s'" %
+ (self.path, name))
+
offset = fdt_obj.first_subnode(self._offset, QUIET_NOTFOUND)
for subnode in self.subnodes:
if subnode.name != fdt_obj.get_name(offset):
@@ -339,8 +353,8 @@
p = fdt_obj.get_property_by_offset(poffset)
prop = self.props.get(p.name)
if not prop:
- raise ValueError("Internal error, property '%s' missing, "
- 'offset %d' % (p.name, poffset))
+ raise ValueError("Internal error, node '%s' property '%s' missing, "
+ 'offset %d' % (self.path, p.name, poffset))
prop.RefreshOffset(poffset)
poffset = fdt_obj.next_property_offset(poffset, QUIET_NOTFOUND)
@@ -447,8 +461,13 @@
Args:
prop_name: Name of property to add
val: Bytes value of property
+
+ Returns:
+ Prop added
"""
- self.props[prop_name] = Prop(self, None, prop_name, val)
+ prop = Prop(self, None, prop_name, val)
+ self.props[prop_name] = prop
+ return prop
def AddString(self, prop_name, val):
"""Add a new string property to a node
@@ -459,9 +478,12 @@
Args:
prop_name: Name of property to add
val: String value of property
+
+ Returns:
+ Prop added
"""
val = bytes(val, 'utf-8')
- self.AddData(prop_name, val + b'\0')
+ return self.AddData(prop_name, val + b'\0')
def AddInt(self, prop_name, val):
"""Add a new integer property to a node
@@ -472,8 +494,11 @@
Args:
prop_name: Name of property to add
val: Integer value of property
+
+ Returns:
+ Prop added
"""
- self.AddData(prop_name, struct.pack('>I', val))
+ return self.AddData(prop_name, struct.pack('>I', val))
def AddSubnode(self, name):
"""Add a new subnode to the node
@@ -499,9 +524,13 @@
auto_resize: Resize the device tree automatically if it does not
have enough space for the update
+ Returns:
+ True if the node had to be added, False if it already existed
+
Raises:
FdtException if auto_resize is False and there is not enough space
"""
+ added = False
if self._offset is None:
# The subnode doesn't exist yet, so add it
fdt_obj = self._fdt._fdt_obj
@@ -515,23 +544,45 @@
else:
offset = fdt_obj.add_subnode(self.parent._offset, self.name)
self._offset = offset
+ added = True
+
+ # Sync the existing subnodes first, so that we can rely on the offsets
+ # being correct. As soon as we add new subnodes, it pushes all the
+ # existing subnodes up.
+ for node in reversed(self.subnodes):
+ if node._offset is not None:
+ node.Sync(auto_resize)
- # Sync subnodes in reverse so that we don't disturb node offsets for
- # nodes that are earlier in the DT. This avoids an O(n^2) rescan of
- # node offsets.
+ # Sync subnodes in reverse so that we get the expected order. Each
+ # new node goes at the start of the subnode list. This avoids an O(n^2)
+ # rescan of node offsets.
+ num_added = 0
for node in reversed(self.subnodes):
- node.Sync(auto_resize)
+ if node.Sync(auto_resize):
+ num_added += 1
+ if num_added:
+ # Reorder our list of nodes to put the new ones first, since that's
+ # what libfdt does
+ old_count = len(self.subnodes) - num_added
+ subnodes = self.subnodes[old_count:] + self.subnodes[:old_count]
+ self.subnodes = subnodes
- # Sync properties now, whose offsets should not have been disturbed.
- # We do this after subnodes, since this disturbs the offsets of these
- # properties. Note that new properties will have an offset of None here,
- # which Python 3 cannot sort against int. So use a large value instead
- # to ensure that the new properties are added first.
+ # Sync properties now, whose offsets should not have been disturbed,
+ # since properties come before subnodes. This is done after all the
+ # subnode processing above, since updating properties can disturb the
+ # offsets of those subnodes.
+ # Properties are synced in reverse order, with new properties added
+ # before existing properties are synced. This ensures that the offsets
+ # of earlier properties are not disturbed.
+ # Note that new properties will have an offset of None here, which
+ # Python cannot sort against int. So use a large value instead so that
+ # new properties are added first.
prop_list = sorted(self.props.values(),
key=lambda prop: prop._offset or 1 << 31,
reverse=True)
for prop in prop_list:
prop.Sync(auto_resize)
+ return added
class Fdt:
@@ -642,8 +693,9 @@
Raises:
FdtException if auto_resize is False and there is not enough space
"""
+ self.CheckCache()
self._root.Sync(auto_resize)
- self.Invalidate()
+ self.Refresh()
def Pack(self):
"""Pack the device tree down to its minimum size
@@ -652,7 +704,7 @@
build up in the device tree binary.
"""
CheckErr(self._fdt_obj.pack(), 'pack')
- self.Invalidate()
+ self.Refresh()
def GetContents(self):
"""Get the contents of the FDT
@@ -704,11 +756,11 @@
if self._cached_offsets:
return
self.Refresh()
- self._cached_offsets = True
def Refresh(self):
"""Refresh the offset cache"""
self._root.Refresh(0)
+ self._cached_offsets = True
def GetStructOffset(self, offset):
"""Get the file offset of a given struct offset
diff --git a/tools/dtoc/test/dtoc_test_simple.dts b/tools/dtoc/test/dtoc_test_simple.dts
index d8ab861..b5c1274 100644
--- a/tools/dtoc/test/dtoc_test_simple.dts
+++ b/tools/dtoc/test/dtoc_test_simple.dts
@@ -56,4 +56,8 @@
low-power;
};
};
+
+ orig-node {
+ orig = <1 23 4>;
+ };
};
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index 1c3a8a2..856392b 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -154,6 +154,7 @@
def setUp(self):
self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
self.node = self.dtb.GetNode('/spl-test')
+ self.fdt = self.dtb.GetFdtObj()
def testOffset(self):
"""Tests that we can obtain the offset of a node"""
@@ -197,7 +198,7 @@
def testRefreshExtraNode(self):
"""Test refreshing offsets when an expected node is missing"""
# Delete it from the device tre, not our tables
- self.dtb.GetFdtObj().del_node(self.node.Offset())
+ self.fdt.del_node(self.node.Offset())
with self.assertRaises(ValueError) as e:
self.dtb.Refresh()
self.assertIn('Internal error, node name mismatch '
@@ -209,7 +210,7 @@
del self.node.props['notstring']
with self.assertRaises(ValueError) as e:
self.dtb.Refresh()
- self.assertIn("Internal error, property 'notstring' missing, offset ",
+ self.assertIn("Internal error, node '/spl-test' property 'notstring' missing, offset ",
str(e.exception))
def testLookupPhandle(self):
@@ -220,6 +221,66 @@
target = dtb.GetNode('/phandle-target')
self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
+ def testAddNodeSpace(self):
+ """Test adding a single node when out of space"""
+ self.fdt.pack()
+ self.node.AddSubnode('subnode')
+ with self.assertRaises(libfdt.FdtException) as e:
+ self.dtb.Sync(auto_resize=False)
+ self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
+
+ self.dtb.Sync(auto_resize=True)
+ offset = self.fdt.path_offset('/spl-test/subnode')
+ self.assertTrue(offset > 0)
+
+ def testAddNodes(self):
+ """Test adding various subnode and properies"""
+ node = self.dtb.GetNode('/i2c@0')
+
+ # Add one more node next to the pmic one
+ sn1 = node.AddSubnode('node-one')
+ sn1.AddInt('integer-a', 12)
+ sn1.AddInt('integer-b', 23)
+
+ # Sync so that everything is clean
+ self.dtb.Sync(auto_resize=True)
+
+ # Add two subnodes next to pmic and node-one
+ sn2 = node.AddSubnode('node-two')
+ sn2.AddInt('integer-2a', 34)
+ sn2.AddInt('integer-2b', 45)
+
+ sn3 = node.AddSubnode('node-three')
+ sn3.AddInt('integer-3', 123)
+
+ # Add a property to the node after i2c@0 to check that this is not
+ # disturbed by adding a subnode to i2c@0
+ orig_node = self.dtb.GetNode('/orig-node')
+ orig_node.AddInt('integer-4', 456)
+
+ # Add a property to the pmic node to check that pmic properties are not
+ # disturbed
+ pmic = self.dtb.GetNode('/i2c@0/pmic@9')
+ pmic.AddInt('integer-5', 567)
+
+ self.dtb.Sync(auto_resize=True)
+
+ def testRefreshNameMismatch(self):
+ """Test name mismatch when syncing nodes and properties"""
+ prop = self.node.AddInt('integer-a', 12)
+
+ wrong_offset = self.dtb.GetNode('/i2c@0')._offset
+ self.node._offset = wrong_offset
+ with self.assertRaises(ValueError) as e:
+ self.dtb.Sync()
+ self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c@0'",
+ str(e.exception))
+
+ with self.assertRaises(ValueError) as e:
+ self.node.Refresh(wrong_offset)
+ self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c@0'",
+ str(e.exception))
+
class TestProp(unittest.TestCase):
"""Test operation of the Prop class"""
@@ -385,17 +446,6 @@
self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
self.dtb.Sync(auto_resize=True)
- def testAddNode(self):
- self.fdt.pack()
- self.node.AddSubnode('subnode')
- with self.assertRaises(libfdt.FdtException) as e:
- self.dtb.Sync(auto_resize=False)
- self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
-
- self.dtb.Sync(auto_resize=True)
- offset = self.fdt.path_offset('/spl-test/subnode')
- self.assertTrue(offset > 0)
-
def testAddMore(self):
"""Test various other methods for adding and setting properties"""
self.node.AddZeroProp('one')