summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f10/Proc/CPU/heapManager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f10/Proc/CPU/heapManager.c')
-rwxr-xr-xsrc/vendorcode/amd/agesa/f10/Proc/CPU/heapManager.c593
1 files changed, 593 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f10/Proc/CPU/heapManager.c b/src/vendorcode/amd/agesa/f10/Proc/CPU/heapManager.c
new file mode 100755
index 0000000000..b5be972444
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f10/Proc/CPU/heapManager.c
@@ -0,0 +1,593 @@
+/**
+ * @file
+ *
+ * AMD Heap Manager and Heap Allocation APIs, and related functions.
+ *
+ * Contains code that initialize, maintain, and allocate the heap space.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 44323 $ @e \$Date: 2010-12-22 01:24:58 -0700 (Wed, 22 Dec 2010) $
+ *
+ */
+/*******************************************************************************
+ *
+ * Copyright (c) 2011, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuRegisters.h"
+#include "cpuServices.h"
+#include "GeneralServices.h"
+#include "heapManager.h"
+#include "cpuCacheInit.h"
+#include "cpuFamilyTranslation.h"
+#include "Filecode.h"
+#define FILECODE PROC_CPU_HEAPMANAGER_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P U B L I C F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+extern BUILD_OPT_CFG UserOptions;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function initializes the heap for each CPU core.
+ *
+ * Check for already initialized. If not, determine offset of local heap in CAS and
+ * setup initial heap markers and bookkeeping status. Initialize a couple heap items
+ * all cores need, for convenience. Currently these are caching the AP mailbox info and
+ * an initial event log.
+ *
+ * @param[in] StdHeader Handle of Header for calling lib functions and services.
+ *
+ * @retval AGESA_SUCCESS This core's heap is initialized (always succeeds)
+ *
+ */
+AGESA_STATUS
+HeapManagerInit (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ // First Time Initialization
+ // Note: First 16 bytes of buffer is reserved for Heap Manager use
+ UINT16 HeapAlreadyInitSizeDword;
+ UINT8 *HeapBufferPtr;
+ UINT32 *HeapDataPtr;
+ UINT64 MsrData;
+ UINT8 Ignored;
+ CACHE_INFO *CacheInfoPtr;
+ AGESA_STATUS IgnoredSts;
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+
+ GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader);
+ FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **)&CacheInfoPtr, &Ignored, StdHeader);
+
+ if (!IsBsp (StdHeader, &IgnoredSts)) {
+ // APs must transfer their system core number from the mailbox to
+ // a local register while it is still valid.
+ FamilySpecificServices->TransferApCoreNumber (FamilySpecificServices, StdHeader);
+ }
+
+ HeapBufferPtr = (UINT8 *) HeapGetCurrentBase (StdHeader);
+ // check whether the heap manager is already initialized
+ LibAmdMsrRead (AMD_MTRR_VARIABLE_HEAP_MASK, &MsrData, StdHeader);
+ if (MsrData == (CacheInfoPtr->VariableMtrrMask & AMD_HEAP_MTRR_MASK)) {
+ LibAmdMsrRead (AMD_MTRR_VARIABLE_HEAP_BASE, &MsrData, StdHeader);
+ if ((MsrData & 0xFFFFFFFFFFFFFF00ull) == (UINT32) HeapBufferPtr) {
+ // This is not a bug, there are multiple premem basic entry points,
+ // and each will call heap init to make sure create struct will succeed.
+ // If that is later deemed a problem, there needs to be a reasonable test
+ // for the calling code to make to determine if it needs to init heap or not.
+ // In the mean time, add this to the event log
+ PutEventLog (AGESA_SUCCESS,
+ CPU_ERROR_HEAP_IS_ALREADY_INITIALIZED,
+ 0, 0, 0, 0, StdHeader);
+ return AGESA_SUCCESS;
+ }
+ }
+
+ // set variable MTRR base and mask
+ MsrData = (UINT32) HeapBufferPtr;
+ MsrData |= 0x06;
+ LibAmdMsrWrite (AMD_MTRR_VARIABLE_HEAP_BASE, &MsrData, StdHeader);
+ MsrData = CacheInfoPtr->VariableMtrrMask & AMD_HEAP_MTRR_MASK;
+ LibAmdMsrWrite (AMD_MTRR_VARIABLE_HEAP_MASK, &MsrData, StdHeader);
+
+ // set top of memory to a temp value
+ MsrData = (UINT64) (AMD_TEMP_TOM);
+ LibAmdMsrWrite (TOP_MEM, &MsrData, StdHeader);
+
+ // Enable variable MTTRs
+ LibAmdMsrRead (SYS_CFG, &MsrData, StdHeader);
+ MsrData |= AMD_VAR_MTRR_ENABLE_BIT;
+ LibAmdMsrWrite (SYS_CFG, &MsrData, StdHeader);
+
+ // Initialize Heap Space
+ HeapDataPtr = (UINT32 *) HeapBufferPtr;
+ for (HeapAlreadyInitSizeDword = 0; HeapAlreadyInitSizeDword < AMD_HEAP_SIZE_DWORD_PER_CORE; HeapAlreadyInitSizeDword++) {
+ *HeapDataPtr = 0;
+ HeapDataPtr++;
+ }
+
+ // Save size of heap (which is contiguous right now) for later use
+ // Note: We are reserving the first 16 bytes for Heap Manager use
+ ((HEAP_MANAGER*) HeapBufferPtr)->AvailableSize = (AMD_HEAP_SIZE_PER_CORE - sizeof (HEAP_MANAGER));
+
+ StdHeader->HeapStatus = HEAP_LOCAL_CACHE;
+ if (!IsBsp (StdHeader, &IgnoredSts)) {
+ // The BSP's hardware mailbox has not been initialized, so only APs
+ // can do this at this point.
+ CacheApMailbox (StdHeader);
+ }
+ EventLogInitialization (StdHeader);
+ return AGESA_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Allocates space for a new buffer in the heap
+ *
+ * This function determines if whether or not there is enough space for the
+ * new structure. If so, it will zero out the buffer, and return a pointer
+ * to the region.
+ *
+ * @param[in,out] AllocateHeapParamsPtr Structure containing the size of the
+ * desired new region, its handle, and the
+ * return pointer.
+ * @param[in,out] StdHeader Config handle for library and services.
+ *
+ * @retval AGESA_SUCCESS No error
+ * @retval AGESA_BOUNDS_CHK Handle already exists, or not enough
+ * free space
+ *
+ */
+AGESA_STATUS
+HeapAllocateBuffer (
+ IN OUT ALLOCATE_HEAP_PARAMS *AllocateHeapParamsPtr,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 *HeapBufferPtr;
+ UINT8 *StartOfBufferPtr;
+ HEAP_MANAGER *HeapManagerPtr;
+ BUFFER_NODE *HeadNodePtr;
+ BUFFER_NODE *CurrentNodePtr;
+ BUFFER_NODE *NextNodePtr;
+ AGESA_BUFFER_PARAMS AgesaBuffer;
+ UINT32 AmdHeapRamAddress;
+
+ AmdHeapRamAddress = (UINT32) UserOptions.CfgHeapDramAddress;
+
+ // Buffer pointer is NULL unless we return a buffer.
+ AllocateHeapParamsPtr->BufferPtr = NULL;
+
+ // check to see where the heap is
+ if (StdHeader->HeapStatus == HEAP_LOCAL_CACHE) {
+ HeapBufferPtr = (UINT8 *) HeapGetCurrentBase (StdHeader);
+ } else if (StdHeader->HeapStatus == HEAP_TEMP_MEM) {
+ HeapBufferPtr = (UINT8 *) AmdHeapRamAddress;
+ } else if (StdHeader->HeapStatus == HEAP_SYSTEM_MEM) {
+ AgesaBuffer.StdHeader = *StdHeader;
+ AgesaBuffer.BufferHandle = AllocateHeapParamsPtr->BufferHandle;
+ AgesaBuffer.BufferLength = AllocateHeapParamsPtr->RequestedBufferSize;
+
+ AGESA_TESTPOINT (TpIfBeforeAllocateHeapBuffer, StdHeader);
+ if (AgesaAllocateBuffer (0, &AgesaBuffer) != AGESA_SUCCESS) {
+ AllocateHeapParamsPtr->BufferPtr = NULL;
+ return AGESA_ERROR;
+ }
+ AGESA_TESTPOINT (TpIfAfterAllocateHeapBuffer, StdHeader);
+
+ AllocateHeapParamsPtr->BufferPtr = (UINT8 *) (AgesaBuffer.BufferPointer);
+ return AGESA_SUCCESS;
+ } else if (StdHeader->HeapStatus == HEAP_S3_RESUME) {
+ HeapBufferPtr = (UINT8 *)(UINT32) StdHeader->HeapBasePtr;
+ } else {
+ AllocateHeapParamsPtr->BufferPtr = NULL;
+ // Heap buffer is not present.
+ return AGESA_BOUNDS_CHK;
+ }
+
+ HeapManagerPtr = (HEAP_MANAGER *) HeapBufferPtr;
+ StartOfBufferPtr = HeapBufferPtr + sizeof (HEAP_MANAGER);
+ HeadNodePtr = (BUFFER_NODE *) StartOfBufferPtr;
+ CurrentNodePtr = HeadNodePtr;
+
+ // Check if we can allocate space
+ if (AllocateHeapParamsPtr->RequestedBufferSize > (HeapManagerPtr->AvailableSize - sizeof (BUFFER_NODE) - 2 * SIZE_OF_SENTINEL)) {
+ PutEventLog (AGESA_BOUNDS_CHK,
+ CPU_ERROR_HEAP_IS_FULL,
+ AllocateHeapParamsPtr->BufferHandle, 0, 0, 0, StdHeader);
+ return AGESA_BOUNDS_CHK;
+ }
+
+ if (HeadNodePtr->BufferSize == 0) {
+ NextNodePtr = CurrentNodePtr;
+ } else {
+ // locate the last heap, but if there already has been a heap with the incoming BufferHandle, we return AGESA_BOUNDS_CHK.
+ while (CurrentNodePtr->NextNodePtr != NULL) {
+ if (CurrentNodePtr->BufferHandle == AllocateHeapParamsPtr->BufferHandle) {
+ PutEventLog (AGESA_BOUNDS_CHK,
+ CPU_ERROR_HEAP_BUFFER_HANDLE_IS_ALREADY_USED,
+ AllocateHeapParamsPtr->BufferHandle, 0, 0, 0, StdHeader);
+ return AGESA_BOUNDS_CHK;
+ }
+ if (StdHeader->HeapStatus == HEAP_S3_RESUME) {
+ HeapBufferPtr = (UINT8 *) CurrentNodePtr;
+ CurrentNodePtr = (BUFFER_NODE *) &HeapBufferPtr[CurrentNodePtr->BufferSize + sizeof (BUFFER_NODE) + (2 * SIZE_OF_SENTINEL)];
+ } else {
+ CurrentNodePtr = CurrentNodePtr->NextNodePtr;
+ }
+ }
+ if (CurrentNodePtr->BufferHandle == AllocateHeapParamsPtr->BufferHandle) {
+ PutEventLog (AGESA_BOUNDS_CHK,
+ CPU_ERROR_HEAP_BUFFER_HANDLE_IS_ALREADY_USED,
+ AllocateHeapParamsPtr->BufferHandle, 0, 0, 0, StdHeader);
+ return AGESA_BOUNDS_CHK;
+ }
+
+ // Create a new node and link it with previous node
+ CurrentNodePtr->NextNodePtr = (BUFFER_NODE *)
+ (((UINT8 *) CurrentNodePtr) +
+ sizeof (BUFFER_NODE) +
+ CurrentNodePtr->BufferSize +
+ 2 * SIZE_OF_SENTINEL);
+ NextNodePtr = CurrentNodePtr->NextNodePtr;
+ }
+ NextNodePtr->BufferSize = AllocateHeapParamsPtr->RequestedBufferSize;
+ NextNodePtr->NextNodePtr = NULL;
+ NextNodePtr->BufferHandle = AllocateHeapParamsPtr->BufferHandle;
+
+ // Debug feature
+ SET_SENTINEL_BEFORE (NextNodePtr);
+ SET_SENTINEL_AFTER (NextNodePtr);
+
+ // Persist
+ if ((AllocateHeapParamsPtr->Persist == HEAP_TEMP_MEM) || (AllocateHeapParamsPtr->Persist == HEAP_SYSTEM_MEM)) {
+ NextNodePtr->Persist = AllocateHeapParamsPtr->Persist;
+ } else {
+ NextNodePtr->Persist = HEAP_LOCAL_CACHE;
+ }
+
+ // Update global variables
+ HeapManagerPtr->AvailableSize -= NextNodePtr->BufferSize + sizeof (BUFFER_NODE) + 2 * SIZE_OF_SENTINEL;
+
+ // Now fill in the incoming structure
+ AllocateHeapParamsPtr->BufferPtr = (UINT8 *) ((UINT8 *) NextNodePtr + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL);
+ Heap_Check (StdHeader);
+
+ return AGESA_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Deallocates a previously allocated buffer in the heap
+ *
+ * This function finds the buffer to deallocate, defragments the remaining
+ * heap, clears the new remainder, and updates the size of the heap.
+ *
+ * @param[in] BufferHandle Handle of the buffer to free.
+ * @param[in] StdHeader Config handle for library and services.
+ *
+ * @retval AGESA_SUCCESS No error
+ * @retval AGESA_BOUNDS_CHK Handle does not exist on the heap
+ *
+ */
+AGESA_STATUS
+HeapDeallocateBuffer (
+ IN UINT32 BufferHandle,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT16 AboveDeallocationHeapSize;
+ UINT16 DeallocationHeapSize;
+ UINT16 BelowDeallocationHeapSize;
+ UINT16 i;
+ UINT8 *HeapBufferPtr;
+ UINT8 *HeapDataPtr1;
+ UINT8 *HeapDataPtr2;
+ HEAP_MANAGER *HeapManagerPtr;
+ BUFFER_NODE *HeadNodePtr;
+ BUFFER_NODE *PreviousNodePtr;
+ BUFFER_NODE *CurrentNodePtr;
+ BUFFER_NODE *NextNodePtr;
+ AGESA_BUFFER_PARAMS AgesaBuffer;
+ UINT32 AmdHeapRamAddress;
+
+ AmdHeapRamAddress = (UINT32) UserOptions.CfgHeapDramAddress;
+
+ AboveDeallocationHeapSize = 0;
+
+ // Step 1: locate the heap which is expected to be deallocated.
+ if (StdHeader->HeapStatus == HEAP_LOCAL_CACHE) {
+ HeapBufferPtr = (UINT8 *) HeapGetCurrentBase (StdHeader);
+ } else if (StdHeader->HeapStatus == HEAP_TEMP_MEM) {
+ HeapBufferPtr = (UINT8 *) AmdHeapRamAddress;
+ } else if (StdHeader->HeapStatus == HEAP_SYSTEM_MEM) {
+ AgesaBuffer.StdHeader = *StdHeader;
+ AgesaBuffer.BufferHandle = BufferHandle;
+
+ AGESA_TESTPOINT (TpIfBeforeDeallocateHeapBuffer, StdHeader);
+ if (AgesaDeallocateBuffer (0, &AgesaBuffer) != AGESA_SUCCESS) {
+ return AGESA_ERROR;
+ }
+ AGESA_TESTPOINT (TpIfAfterDeallocateHeapBuffer, StdHeader);
+
+ return AGESA_SUCCESS;
+ } else {
+ // Heap buffer is not present.
+ IDS_ERROR_TRAP;
+ return AGESA_BOUNDS_CHK;
+ }
+
+ HeapManagerPtr = (HEAP_MANAGER *) HeapBufferPtr;
+ HeadNodePtr = (BUFFER_NODE *) ((HeapBufferPtr + sizeof (HEAP_MANAGER)));
+ CurrentNodePtr = HeadNodePtr;
+ PreviousNodePtr = CurrentNodePtr;
+
+ while (CurrentNodePtr->BufferHandle != BufferHandle) {
+ AboveDeallocationHeapSize += (CurrentNodePtr->BufferSize) + sizeof (BUFFER_NODE) + 2 * SIZE_OF_SENTINEL;
+ PreviousNodePtr = CurrentNodePtr;
+ if (CurrentNodePtr->NextNodePtr == NULL) {
+ // If we are at the end of the heap and still unable to locate the buffer handle, return AGESA_BOUNDS_CHK
+ PutEventLog (AGESA_BOUNDS_CHK,
+ CPU_ERROR_HEAP_BUFFER_HANDLE_IS_NOT_PRESENT,
+ BufferHandle, 0, 0, 0, StdHeader);
+ return AGESA_BOUNDS_CHK;
+ } else {
+ CurrentNodePtr = CurrentNodePtr->NextNodePtr;
+ }
+ }
+
+ // Step 2: defragment
+
+ // Before:
+ // ------------------------ <- UINT8 * HeapBufferPtr
+ // | Heap Manager 16 Bytes|
+ // ------------------------ ---
+ // | Heap 1 | AboveDeallocationHeapSize
+ // | |
+ // ------------------------ ---
+ // | Heap 2 | <- Deallocate
+ // | | DeallocationHeapSize
+ // ------------------------ ---
+ // | Heap 3 | BelowDeallocationHeapSize
+ // | |
+ // ------------------------ ---
+ // | Unused | UnusedSize = HeapManagerPtr->AvailableSize
+ // ------------------------ ---
+ // After deallocating: shift all subsequent heap buffers up
+ // ------------------------
+ // | Heap Manager 16 Bytes|
+ // ------------------------
+ // | Heap 1 |
+ // | |
+ // ------------------------
+ // | Heap 3 |
+ // | |
+ // ------------------------
+ // | |
+ // | |
+ // | Unused |
+ // ------------------------
+ DeallocationHeapSize = (CurrentNodePtr->BufferSize) + sizeof (BUFFER_NODE) + 2 * SIZE_OF_SENTINEL;
+ BelowDeallocationHeapSize = AMD_HEAP_SIZE_PER_CORE - sizeof (HEAP_MANAGER)
+ - HeapManagerPtr->AvailableSize
+ - AboveDeallocationHeapSize
+ - DeallocationHeapSize;
+ HeapDataPtr1 = (UINT8 *) CurrentNodePtr;
+
+ // if this is the last Heap, then PreviousNodePtr->NextNodePtr = NULL and return
+ if (CurrentNodePtr->NextNodePtr == NULL) {
+ PreviousNodePtr->NextNodePtr = NULL;
+ } else {
+ HeapDataPtr2 = (UINT8 *) (CurrentNodePtr->NextNodePtr);
+ // subtract DeallocationHeapSize from all subsequent NextNodePtr
+ CurrentNodePtr = CurrentNodePtr->NextNodePtr;
+ while (CurrentNodePtr->NextNodePtr != NULL) {
+ NextNodePtr = CurrentNodePtr->NextNodePtr;
+ CurrentNodePtr->NextNodePtr = (BUFFER_NODE *) ((UINT8 *) (CurrentNodePtr->NextNodePtr) - DeallocationHeapSize);
+ CurrentNodePtr = NextNodePtr;
+ }
+ // shift subsequent heap buffers up
+ for (i = 0; i < BelowDeallocationHeapSize; i++) {
+ *HeapDataPtr1 = *HeapDataPtr2;
+ HeapDataPtr1++;
+ HeapDataPtr2++;
+ }
+ }
+
+ // Step 3: clear remainder useless data
+ LibAmdMemFill (HeapDataPtr1, 0, DeallocationHeapSize, StdHeader);
+
+ // Step 4: update unused size
+ HeapManagerPtr->AvailableSize = HeapManagerPtr->AvailableSize + DeallocationHeapSize;
+ return AGESA_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Locates a previously allocated buffer on the heap.
+ *
+ * This function searches the heap for a buffer with the desired handle, and
+ * returns a pointer to the buffer.
+ *
+ * @param[in,out] LocateHeapPtr Structure containing the buffer's handle,
+ * and the return pointer.
+ * @param[in] StdHeader Config handle for library and services.
+ *
+ * @retval AGESA_SUCCESS No error
+ * @retval AGESA_BOUNDS_CHK Handle does not exist on the heap
+ *
+ */
+AGESA_STATUS
+HeapLocateBuffer (
+ IN OUT LOCATE_HEAP_PTR *LocateHeapPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 *HeapBufferPtr;
+ UINT8 *StartOfBufferPtr;
+ HEAP_MANAGER *HeapManagerPtr;
+ BUFFER_NODE *HeadNodePtr;
+ BUFFER_NODE *CurrentNodePtr;
+ BOOLEAN BufferHandleFlag;
+ AGESA_BUFFER_PARAMS AgesaBuffer;
+ UINT32 AmdHeapRamAddress;
+
+ AmdHeapRamAddress = (UINT32) UserOptions.CfgHeapDramAddress;
+
+ ASSERT (StdHeader != NULL);
+
+ BufferHandleFlag = TRUE;
+
+ if (StdHeader->HeapStatus == HEAP_LOCAL_CACHE) {
+ HeapBufferPtr = (UINT8 *) HeapGetCurrentBase (StdHeader);
+ } else if (StdHeader->HeapStatus == HEAP_TEMP_MEM) {
+ HeapBufferPtr = (UINT8 *) AmdHeapRamAddress;
+ } else if (StdHeader->HeapStatus == HEAP_SYSTEM_MEM) {
+ AgesaBuffer.StdHeader = *StdHeader;
+ AgesaBuffer.BufferHandle = LocateHeapPtr->BufferHandle;
+
+ AGESA_TESTPOINT (TpIfBeforeLocateHeapBuffer, StdHeader);
+ if (AgesaLocateBuffer (0, &AgesaBuffer) != AGESA_SUCCESS) {
+ LocateHeapPtr->BufferPtr = NULL;
+ return AGESA_ERROR;
+ }
+ AGESA_TESTPOINT (TpIfAfterLocateHeapBuffer, StdHeader);
+
+ LocateHeapPtr->BufferPtr = (UINT8 *) (AgesaBuffer.BufferPointer);
+ return AGESA_SUCCESS;
+ } else if (StdHeader->HeapStatus == HEAP_S3_RESUME) {
+ HeapBufferPtr = (UINT8 *) (UINT32) StdHeader->HeapBasePtr;
+ } else {
+ return AGESA_BOUNDS_CHK;
+ }
+
+ HeapManagerPtr = (HEAP_MANAGER *) HeapBufferPtr;
+ StartOfBufferPtr = HeapBufferPtr + sizeof (HEAP_MANAGER);
+ HeadNodePtr = (BUFFER_NODE *) StartOfBufferPtr;
+ CurrentNodePtr = HeadNodePtr;
+
+ while (CurrentNodePtr->BufferHandle != LocateHeapPtr->BufferHandle) {
+ if (CurrentNodePtr->NextNodePtr == NULL) {
+ BufferHandleFlag = FALSE;
+ break;
+ } else {
+ if (StdHeader->HeapStatus == HEAP_S3_RESUME) {
+ HeapBufferPtr = (UINT8 *) CurrentNodePtr;
+ CurrentNodePtr = (BUFFER_NODE *) &HeapBufferPtr[CurrentNodePtr->BufferSize + sizeof (BUFFER_NODE) + (2 * SIZE_OF_SENTINEL)];
+ } else {
+ CurrentNodePtr = CurrentNodePtr->NextNodePtr;
+ }
+ }
+ }
+
+ if (BufferHandleFlag) {
+ LocateHeapPtr->BufferPtr = (UINT8 *) ((UINT8 *) CurrentNodePtr + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL);
+ return AGESA_SUCCESS;
+ } else {
+ LocateHeapPtr->BufferPtr = NULL;
+ PutEventLog (AGESA_BOUNDS_CHK,
+ CPU_ERROR_HEAP_BUFFER_HANDLE_IS_NOT_PRESENT,
+ LocateHeapPtr->BufferHandle, 0, 0, 0, StdHeader);
+ return AGESA_BOUNDS_CHK;
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Determines the base address of the executing core's heap.
+ *
+ * This function uses the executing core's socket/core numbers to determine
+ * where it's heap should be located.
+ *
+ * @param[in] StdHeader Config handle for library and services.
+ *
+ * @return A pointer to the executing core's heap.
+ *
+ */
+VOID *
+HeapGetCurrentBase (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 SystemCoreNumber;
+ UINT64 ReturnPtr;
+ AGESA_STATUS IgnoredStatus;
+ CPU_SPECIFIC_SERVICES *FamilyServices;
+
+ if (IsBsp (StdHeader, &IgnoredStatus)) {
+ ReturnPtr = AMD_HEAP_START_ADDRESS;
+ } else {
+ GetCpuServicesOfCurrentCore (&FamilyServices, StdHeader);
+ ASSERT (FamilyServices != NULL);
+
+ SystemCoreNumber = FamilyServices->GetApCoreNumber (FamilyServices, StdHeader);
+ ASSERT (SystemCoreNumber != 0);
+ ASSERT (SystemCoreNumber < 64);
+ ReturnPtr = ((SystemCoreNumber * AMD_HEAP_SIZE_PER_CORE) + AMD_HEAP_START_ADDRESS);
+ }
+ ASSERT (ReturnPtr <= ((AMD_HEAP_REGION_END_ADDRESS + 1) - AMD_HEAP_SIZE_PER_CORE));
+ return ((VOID *) (UINT32) ReturnPtr);
+}