lib/cbmem: provide optional cbmem top initialization hook

Provide a hook to allow an optional one-time cbmem_top() initialization.
The new function, cbmem_top_init(), is called on the first expected
initialization of cbmem based on the Kconfig options LATE_CBMEM_INIT
and EARLY_CBMEM_INIT.

Change-Id: I89edd2d11f226217c8e2aaca829b4f375a2cff28
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Signed-off-by: John Zhao <john.zhao@intel.com>
Reviewed-on: https://review.coreboot.org/20847
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
diff --git a/src/lib/imd_cbmem.c b/src/lib/imd_cbmem.c
index ba00c2e..5713c2c 100644
--- a/src/lib/imd_cbmem.c
+++ b/src/lib/imd_cbmem.c
@@ -109,12 +109,31 @@
 	cbmem_initialize_empty_id_size(0, 0);
 }
 
+void __attribute__((weak)) cbmem_top_init(void)
+{
+}
+
+static void cbmem_top_init_once(void)
+{
+	/* Call one-time hook on expected cbmem init during boot. This sequence
+	   assumes first init call is in romstage for early cbmem init and
+	   ramstage for late cbmem init. */
+	if (IS_ENABLED(CONFIG_EARLY_CBMEM_INIT) && !ENV_ROMSTAGE)
+		return;
+	if (IS_ENABLED(CONFIG_LATE_CBMEM_INIT) && !ENV_RAMSTAGE)
+		return;
+
+	cbmem_top_init();
+}
+
 void cbmem_initialize_empty_id_size(u32 id, u64 size)
 {
 	struct imd *imd;
 	struct imd imd_backing;
 	const int no_recovery = 0;
 
+	cbmem_top_init_once();
+
 	imd = imd_init_backing(&imd_backing);
 	imd_handle_init(imd, cbmem_top());
 
@@ -145,6 +164,8 @@
 	struct imd imd_backing;
 	const int recovery = 1;
 
+	cbmem_top_init_once();
+
 	imd = imd_init_backing(&imd_backing);
 	imd_handle_init(imd, cbmem_top());