lib/cbmem_top: Add a common cbmem_top implementation

This adds a common cbmem_top implementation to all coreboot target.

In romstage a static variable will be used to cache the result of
cbmem_top_romstage.

In ramstage if CONFIG_RAMSTAGE_CBMEM_TOP_ARG is set a global variable
needs to be populated by the stage entry with the value passed via the
calling arguments. if CONFIG_RAMSTAGE_CBMEM_TOP_ARG is not set the
same implementation as will be used as in romstage.

Change-Id: Ie767542ee25483acc9a56785ce20a885e9a63098
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/36273
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
diff --git a/src/lib/imd_cbmem.c b/src/lib/imd_cbmem.c
index be135c2..cbd4b8f 100644
--- a/src/lib/imd_cbmem.c
+++ b/src/lib/imd_cbmem.c
@@ -13,6 +13,7 @@
  * GNU General Public License for more details.
  */
 
+#include <assert.h>
 #include <boot/coreboot_tables.h>
 #include <bootstate.h>
 #include <bootmem.h>
@@ -44,6 +45,28 @@
 	(!CONFIG(ARCH_X86) || ENV_RAMSTAGE || ENV_POSTCAR || \
 	 !CONFIG(CAR_GLOBAL_MIGRATION))
 
+/* The program loader passes on cbmem_top and the program entry point
+   has to fill in the _cbmem_top_ptr symbol based on the calling arguments. */
+uintptr_t _cbmem_top_ptr;
+
+void *cbmem_top(void)
+{
+	if (ENV_ROMSTAGE
+	    || ((ENV_POSTCAR || ENV_RAMSTAGE)
+		&& !CONFIG(RAMSTAGE_CBMEM_TOP_ARG))) {
+		MAYBE_STATIC_BSS void *top = NULL;
+		if (top)
+			return top;
+		top = cbmem_top_chipset();
+		return top;
+	}
+	if ((ENV_POSTCAR || ENV_RAMSTAGE) && CONFIG(RAMSTAGE_CBMEM_TOP_ARG))
+		return (void *)_cbmem_top_ptr;
+
+	dead_code();
+}
+
+
 static inline struct imd *cbmem_get_imd(void)
 {
 	if (CAN_USE_GLOBALS) {