amd/pi: Add AgesaHeapRebase callout

Implement an optional callout for AgesaHeapRebase which allows AGESA
to override any internal hardcoded heap addresses.

Designate a region in CAR that may be used for pre-mem heap and return
that address before DRAM is configured.  After DRAM is up, the address
in cbmem is returned.

TEST=Boot grunt with patchstack and experimental blob
BUG=b:74518368

Change-Id: Ieda202a6064302b21707bd7ddfabc132cd85ed45
Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com>
Reviewed-on: https://review.coreboot.org/25458
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin Roth <martinroth@google.com>
diff --git a/src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h b/src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h
index 53d5655..97bf208 100644
--- a/src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h
+++ b/src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h
@@ -34,6 +34,7 @@
 } BIOS_BUFFER_NODE;
 
 AGESA_STATUS agesa_GetTempHeapBase(UINT32 Func, UINTN Data, VOID *ConfigPtr);
+AGESA_STATUS agesa_HeapRebase(UINT32 Func, UINTN Data, VOID *ConfigPtr);
 
 AGESA_STATUS agesa_AllocateBuffer(UINT32 Func, UINTN Data, VOID *ConfigPtr);
 AGESA_STATUS agesa_DeallocateBuffer(UINT32 Func, UINTN Data, VOID *ConfigPtr);
diff --git a/src/soc/amd/common/block/pi/Kconfig b/src/soc/amd/common/block/pi/Kconfig
index 547232e..f0917bb 100644
--- a/src/soc/amd/common/block/pi/Kconfig
+++ b/src/soc/amd/common/block/pi/Kconfig
@@ -7,6 +7,14 @@
 
 if SOC_AMD_COMMON_BLOCK_PI
 
+config PI_AGESA_CAR_HEAP_BASE
+	hex
+	default 0x400000
+	help
+	  The AGESA PI blob may be built to allow an optional callout for
+	  AgesaHeapRebase.  If AGESA calls AgesaHeapRebase, this option
+	  determines the location of the heap prior to DRAM availability.
+
 config PI_AGESA_TEMP_RAM_BASE
 	hex
 	default 0x100000
diff --git a/src/soc/amd/common/block/pi/def_callouts.c b/src/soc/amd/common/block/pi/def_callouts.c
index 0adff7d..54b1ede 100644
--- a/src/soc/amd/common/block/pi/def_callouts.c
+++ b/src/soc/amd/common/block/pi/def_callouts.c
@@ -31,6 +31,7 @@
 	{ AGESA_DO_RESET,                 agesa_Reset },
 	{ AGESA_FCH_OEM_CALLOUT,          agesa_fch_initreset },
 	{ AGESA_HALT_THIS_AP,             agesa_HaltThisAp },
+	{ AGESA_HEAP_REBASE,              agesa_HeapRebase },
 	{ AGESA_GNB_PCIE_SLOT_RESET,      agesa_PcieSlotResetControl }
 };
 #else
@@ -46,6 +47,7 @@
 	{ AGESA_READ_SPD,                 agesa_ReadSpd },
 	{ AGESA_GNB_PCIE_SLOT_RESET,      agesa_PcieSlotResetControl },
 	{ AGESA_GET_TEMP_HEAP_BASE,       agesa_GetTempHeapBase },
+	{ AGESA_HEAP_REBASE,              agesa_HeapRebase },
 #if ENV_RAMSTAGE
 	{ AGESA_RUNFUNC_ONAP,             agesa_RunFuncOnAp },
 	{ AGESA_RUNFUNC_ON_ALL_APS,       agesa_RunFcnOnAllAps },
diff --git a/src/soc/amd/common/block/pi/heapmanager.c b/src/soc/amd/common/block/pi/heapmanager.c
index 98a8ce1..54b0cbc 100644
--- a/src/soc/amd/common/block/pi/heapmanager.c
+++ b/src/soc/amd/common/block/pi/heapmanager.c
@@ -56,6 +56,39 @@
 }
 
 /*
+ * Name			agesa_HeapRebase
+ * Brief description	AGESA may use internal hardcoded locations for its
+ *			heap.  Modern implementations allow the base to be
+ *			overridden by calling agesa_HeapRebase.
+ * Input parameters
+ *	Func		Unused
+ *	Data		Unused
+ *	ConfigPtr	Pointer to type AGESA_REBASE_PARAMS
+ * Output parameters
+ *	Status		Indicates whether HeapAddress was successfully
+ *			set.
+ */
+AGESA_STATUS agesa_HeapRebase(UINT32 Func, UINTN Data, VOID *ConfigPtr)
+{
+	AGESA_REBASE_PARAMS *Rebase;
+
+	Rebase = (AGESA_REBASE_PARAMS *)ConfigPtr;
+	if (ENV_BOOTBLOCK) {
+		Rebase->HeapAddress = CONFIG_PI_AGESA_CAR_HEAP_BASE;
+	} else {
+		/*
+		 * todo: remove the if() above and keep the assignment here
+		 * once all AGESA functions are removed from bootblock.
+		 */
+		Rebase->HeapAddress = (UINTN)agesa_heap_base();
+		if (!Rebase->HeapAddress)
+			Rebase->HeapAddress = CONFIG_PI_AGESA_CAR_HEAP_BASE;
+	}
+
+	return AGESA_SUCCESS;
+}
+
+/*
  * Name			FindAllocatedNode
  * Brief description	Find an allocated node that matches the handle.
  * Input parameter	The desired handle.