summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Kconfig10
-rw-r--r--src/include/cbfs.h5
-rw-r--r--src/include/memlayout.h2
-rw-r--r--src/include/symbols.h1
-rw-r--r--src/lib/cbfs_core.c40
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);