summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/cbmem.h5
-rw-r--r--src/lib/imd_cbmem.c24
2 files changed, 20 insertions, 9 deletions
diff --git a/src/include/cbmem.h b/src/include/cbmem.h
index 5b75db0342..6a41ec7615 100644
--- a/src/include/cbmem.h
+++ b/src/include/cbmem.h
@@ -67,9 +67,8 @@ void cbmem_initialize_empty_id_size(u32 id, u64 size);
/* Return the top address for dynamic cbmem. The address returned needs to
* be consistent across romstage and ramstage, and it is required to be
* below 4GiB.
- * Board or chipset should return NULL if any interface that might rely on cbmem
- * (e.g. cbfs, vboot) is used before the cbmem backing store has been
- * initialized. */
+ * x86 boards or chipsets must return NULL before the cbmem backing store has
+ * been initialized. */
void *cbmem_top(void);
/* Add a cbmem entry of a given size and id. These return NULL on failure. The
diff --git a/src/lib/imd_cbmem.c b/src/lib/imd_cbmem.c
index 3e3e2b0637..d72f0b034a 100644
--- a/src/lib/imd_cbmem.c
+++ b/src/lib/imd_cbmem.c
@@ -26,10 +26,23 @@
#include <arch/acpi.h>
#endif
+/*
+ * We need special handling on x86 before ramstage because we cannot use global
+ * variables (we're executing in-place from flash so we don't have a writable
+ * data segment, and we cannot use CAR_GLOBAL here since that mechanism itself
+ * is dependent on CBMEM). Therefore, we have to always try to partially recover
+ * CBMEM from cbmem_top() whenever we try to access it. In other environments
+ * we're not so constrained and just keep the backing imd struct in a global.
+ * This also means that we can easily tell whether CBMEM has explicitly been
+ * initialized or recovered yet on those platforms, and don't need to put the
+ * burden on board or chipset code to tell us by returning NULL from cbmem_top()
+ * before that point.
+ */
+#define CAN_USE_GLOBALS (!IS_ENABLED(CONFIG_ARCH_X86) || ENV_RAMSTAGE)
+
static inline struct imd *cbmem_get_imd(void)
{
- /* Only supply a backing store for imd in ramstage. */
- if (ENV_RAMSTAGE) {
+ if (CAN_USE_GLOBALS) {
static struct imd imd_cbmem;
return &imd_cbmem;
}
@@ -77,11 +90,10 @@ static struct imd *imd_init_backing_with_recover(struct imd *backing)
struct imd *imd;
imd = imd_init_backing(backing);
- if (!ENV_RAMSTAGE) {
+ if (!CAN_USE_GLOBALS) {
+ /* Always partially recover if we can't keep track of whether
+ * we have already initialized CBMEM in this stage. */
imd_handle_init(imd, cbmem_top());
-
- /* Need to partially recover all the time outside of ramstage
- * because there's object storage outside of the stack. */
imd_handle_init_partial_recovery(imd);
}