diff options
-rw-r--r-- | src/Kconfig | 10 | ||||
-rw-r--r-- | src/include/cbfs.h | 5 | ||||
-rw-r--r-- | src/include/memlayout.h | 2 | ||||
-rw-r--r-- | src/include/symbols.h | 1 | ||||
-rw-r--r-- | src/lib/cbfs_core.c | 40 |
5 files changed, 52 insertions, 6 deletions
diff --git a/src/Kconfig b/src/Kconfig index 6cf31343cc..6f7f459fc1 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -55,6 +55,16 @@ config COMMON_CBFS_SPI_WRAPPER help Use common wrapper to interface CBFS to SPI bootrom. +config MULTIPLE_CBFS_INSTANCES + bool "Multiple CBFS instances in the bootrom" + default n + depends on !ARCH_X86 + help + Account for the firmware image containing more than one CBFS + instance. Locations of instances are known at build time and are + communicated between coreboot stages to make sure the next stage is + loaded from the appropriate instance. + choice prompt "Compiler to use" default COMPILER_GCC diff --git a/src/include/cbfs.h b/src/include/cbfs.h index c46d2a0be3..086fa19eb6 100644 --- a/src/include/cbfs.h +++ b/src/include/cbfs.h @@ -84,5 +84,10 @@ void *cbfs_simple_buffer_unmap(struct cbfs_simple_buffer *buffer, */ int init_default_cbfs_media(struct cbfs_media *media); +#if (IS_ENABLED(CONFIG_MULTIPLE_CBFS_INSTANCES)) +void cbfs_set_header_offset(size_t offset); +#else +static inline void cbfs_set_header_offset(size_t offset) {} +#endif #endif diff --git a/src/include/memlayout.h b/src/include/memlayout.h index a80e03ef85..263dc5ceda 100644 --- a/src/include/memlayout.h +++ b/src/include/memlayout.h @@ -102,4 +102,6 @@ . += sz; #endif +#define CBFS_HEADER_OFFSET(addr) REGION(cbfs_header_offset, addr, 4, 4) + #endif /* __MEMLAYOUT_H */ diff --git a/src/include/symbols.h b/src/include/symbols.h index c3ced87d3f..279c5a214a 100644 --- a/src/include/symbols.h +++ b/src/include/symbols.h @@ -27,6 +27,7 @@ extern u8 _esram[]; #define _sram_size (_esram - _sram) extern u8 _dram[]; +extern u32 _cbfs_header_offset[]; extern u8 _preram_cbmem_console[]; extern u8 _epreram_cbmem_console[]; diff --git a/src/lib/cbfs_core.c b/src/lib/cbfs_core.c index 80d66ca3eb..9f45b3cedc 100644 --- a/src/lib/cbfs_core.c +++ b/src/lib/cbfs_core.c @@ -47,6 +47,25 @@ #include <cbfs.h> #include <string.h> +#include <symbols.h> + +#if IS_ENABLED(CONFIG_MULTIPLE_CBFS_INSTANCES) +void cbfs_set_header_offset(size_t offset) +{ + _cbfs_header_offset[0] = offset; + LOG("header set to: %#zx\n", offset); +} + +static size_t get_header_offset(void) +{ + return _cbfs_header_offset[0]; +} +#else +static size_t get_header_offset(void) +{ + return 0; +} +#endif #include "cbfs_core.h" @@ -73,13 +92,22 @@ const struct cbfs_header *cbfs_get_header(struct cbfs_media *media) offset = *(int32_t *)(uintptr_t)0xfffffffc; header = media->map(media, offset, sizeof(*header)); } else { - int32_t rel_offset; - if (!media->read(media, &rel_offset, CONFIG_CBFS_SIZE - - sizeof(int32_t), sizeof(int32_t))) { - ERROR("Could not read CBFS master header offset!\n"); - return CBFS_HEADER_INVALID_ADDRESS; + + offset = get_header_offset(); + + if (!offset) { + int32_t rel_offset; + size_t cbfs_top = CONFIG_CBFS_SIZE; + DEBUG("CBFS top at offset: 0x%zx\n", cbfs_top); + if (!media->read(media, &rel_offset, cbfs_top - + sizeof(int32_t), + sizeof(int32_t))) { + ERROR("Could not read master header offset!\n"); + media->close(media); + return CBFS_HEADER_INVALID_ADDRESS; + } + offset = cbfs_top + rel_offset; } - offset = CONFIG_CBFS_SIZE + rel_offset; header = media->map(media, offset, sizeof(*header)); } DEBUG("CBFS header offset: 0x%zx/0x%x\n", offset, CONFIG_ROM_SIZE); |