Exemplo n.º 1
0
/**
 * Main entry point for the AMD_INIT_ENV function.
 *
 * This entry point is responsible for copying the heap contents from the
 * temp RAM area to main memory.
 *
 * @param[in,out] EnvParams         Required input parameters for the AMD_INIT_ENV
 *                                  entry point.
 *
 * @return        Aggregated status across all internal AMD env calls invoked.
 *
 */
AGESA_STATUS
AmdInitEnv (
  IN OUT   AMD_ENV_PARAMS  *EnvParams
  )
{
  AGESA_STATUS  AgesaStatus;
  AGESA_STATUS  AmdInitEnvStatus;

  AGESA_TESTPOINT (TpIfAmdInitEnvEntry, &EnvParams->StdHeader);

  ASSERT (EnvParams != NULL);
  AmdInitEnvStatus = AGESA_SUCCESS;


  //Copy Temp Ram heap content to Main Ram
  AgesaStatus = CopyHeapToMainRamAtPost (&(EnvParams->StdHeader));
  if (AgesaStatus > AmdInitEnvStatus) {
    AmdInitEnvStatus = AgesaStatus;
  }
  EnvParams->StdHeader.HeapStatus = HEAP_SYSTEM_MEM;
  EnvParams->StdHeader.HeapBasePtr = HeapGetBaseAddress (&EnvParams->StdHeader);
  // Any heap allocate/deallocate/locate buffer should be used after heap is rebuilt from here.
  // After persistent heaps are transferred and rebuilt, HeapLocateBuffer can start to be used in IDS hook.

  //Heap have been relocated, so Debug Print need be init again to get new address
  IDS_PERF_TIMESTAMP (TP_BEGINPROCAMDINITENV, &EnvParams->StdHeader);
  IDS_HDT_CONSOLE_INIT (&EnvParams->StdHeader);
  IDS_HDT_CONSOLE (MAIN_FLOW, "Heap transfer End\n");
  IDS_HDT_CONSOLE (MAIN_FLOW, "AmdInitEnv: Start\n\n");
  IDS_OPTION_HOOK (IDS_PLATFORMCFG_OVERRIDE, &EnvParams->PlatformConfig, &(EnvParams->StdHeader));
  IDS_OPTION_HOOK (IDS_BEFORE_PCI_INIT, EnvParams, &(EnvParams->StdHeader));

  AgesaStatus = S3ScriptInit (&EnvParams->StdHeader);
  if (AgesaStatus > AmdInitEnvStatus) {
    AmdInitEnvStatus = AgesaStatus;
  }

  IDS_PERF_TIMESTAMP (TP_BEGININITENV, &EnvParams->StdHeader);
  AgesaStatus = BldoptFchFunction.InitEnv (EnvParams);
  AmdInitEnvStatus = (AgesaStatus > AmdInitEnvStatus) ? AgesaStatus : AmdInitEnvStatus;
  IDS_PERF_TIMESTAMP (TP_ENDINITENV, &EnvParams->StdHeader);

  IDS_PERF_TIMESTAMP (TP_BEGINGNBINITATENV, &EnvParams->StdHeader);
  AgesaStatus = GnbInitAtEnv (EnvParams);
  if (AgesaStatus > AmdInitEnvStatus) {
    AmdInitEnvStatus = AgesaStatus;
  }
  IDS_PERF_TIMESTAMP (TP_ENDGNBINITATENV, &EnvParams->StdHeader);

  AGESA_TESTPOINT (TpIfAmdInitEnvExit, &EnvParams->StdHeader);
  IDS_HDT_CONSOLE (MAIN_FLOW, "\nAmdInitEnv: End\n");
  IDS_PERF_TIMESTAMP (TP_ENDPROCAMDINITENV, &EnvParams->StdHeader);
  IDS_HDT_CONSOLE_FLUSH_BUFFER (&EnvParams->StdHeader);
  return  AmdInitEnvStatus;
}
Exemplo n.º 2
0
/**
 *  IdsReadyToBootEntry
 *
 * Description
 *    Notify event for gEfiEventReadyToBootGuid, when this event been signaled before booting OS
 *    It will be called.
 *
 *  @param[in]      Event
 *  @param[in,out]  Context
 *
 *
 */
VOID
IdsReadyToBootEntry (
  IN       EFI_EVENT  Event,
  IN       VOID       *Context
  )
{
  AMD_CONFIG_PARAMS StdHeader;
  UINTN Length;
  UINT8 * Tmp;

  Length = sizeof (StdHeader);
  Tmp = (UINT8*) &StdHeader;
  while (Length --) {
    *Tmp++ = 0;
  }

  StdHeader.HeapStatus = HEAP_SYSTEM_MEM;
  StdHeader.HeapBasePtr = HeapGetBaseAddress (&StdHeader);

  BvmReadyToBoot (&StdHeader);

}
Exemplo n.º 3
0
/**
 *
 * Is it SecureS3
 *
 * @param[in]    StdHeader        Header for library and services
 *
 * @retval       TRUE             It's SecureS3
 * @retval       FALSE            It's NOT SecureS3
 *
 */
BOOLEAN
F16MlIsSecureS3 (
    IN       AMD_CONFIG_PARAMS *StdHeader
)
{
    UINT32       SystemCoreNumber;
    UINT64       BaseAddress;
    CPU_SPECIFIC_SERVICES  *IgnoreService;

    // The best way to check IsSecureS3 is locating a PPI which is published by PSP driver
    // But APs don't have PEI service, and can't locate PPI
    // During SecureS3 resume path, PSP driver will relocate heap (including BSP and APs)
    // Below is an alternate solution: checking BSP's heap address
    BaseAddress = HeapGetBaseAddress (StdHeader);
    IgnoreService = NULL;
    SystemCoreNumber = F16MlGetApCoreNumber (IgnoreService, StdHeader);
    BaseAddress = BaseAddress - (SystemCoreNumber * AMD_HEAP_SIZE_PER_CORE);
    if ((BaseAddress != AMD_HEAP_START_ADDRESS) && ((StdHeader->HeapStatus == HEAP_DO_NOT_EXIST_YET) || (StdHeader->HeapStatus == HEAP_LOCAL_CACHE))) {
        return TRUE;
    }

    return FALSE;
}
Exemplo n.º 4
0
/**
 * External AGESA interface to read an Event from the Event Log.
 *
 * This is the implementation of the external AGESA interface entry, as a thin wrapper
 * around the internal log services.
 *
 * @param[in]  Event           The event class, id, and any associated data.
 *
 * @retval     AGESA_SUCCESS   Always Succeeds.
 */
AGESA_STATUS
AmdReadEventLog (
  IN       EVENT_PARAMS *Event
  )
{
  AGESA_EVENT  LogEvent;
  AGESA_STATUS Status;

  AGESA_TESTPOINT (TpIfAmdReadEventLogEntry, &Event->StdHeader);

  ASSERT (Event != NULL);
  Event->StdHeader.HeapBasePtr = HeapGetBaseAddress (&Event->StdHeader);
  Status = GetEventLog (&LogEvent, &Event->StdHeader);

  Event->EventClass = LogEvent.EventClass;
  Event->EventInfo = LogEvent.EventInfo;
  Event->DataParam1 = LogEvent.DataParam1;
  Event->DataParam2 = LogEvent.DataParam2;
  Event->DataParam3 = LogEvent.DataParam3;
  Event->DataParam4 = LogEvent.DataParam4;

  AGESA_TESTPOINT (TpIfAmdReadEventLogExit, &Event->StdHeader);
  return Status;
}
Exemplo n.º 5
0
/**
 * 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]  LocateHeap     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 *LocateHeap,
  IN       AMD_CONFIG_PARAMS *StdHeader
  )
{
  UINT8 *BaseAddress;
  UINT8  AlignTo16Byte;
  UINT32 OffsetOfCurrentNode;
  BOOLEAN HeapLocateFlag;
  HEAP_MANAGER *HeapManager;
  BUFFER_NODE *CurrentNode;
  AGESA_BUFFER_PARAMS  AgesaBuffer;

  ASSERT (StdHeader != NULL);

  HeapLocateFlag = TRUE;
  BaseAddress = (UINT8 *) (UINTN) StdHeader->HeapBasePtr;
  HeapManager = (HEAP_MANAGER *) BaseAddress;

  // Check Heap database is valid
  if ((BaseAddress == NULL) || (HeapManager->Signature != HEAP_SIGNATURE_VALID)) {
    // The base address in StdHeader is incorrect, get base address by itself
    BaseAddress = (UINT8 *) HeapGetBaseAddress (StdHeader);
    HeapManager = (HEAP_MANAGER *) BaseAddress;
    if ((BaseAddress == NULL) || (HeapManager->Signature != HEAP_SIGNATURE_VALID)) {
      // Heap is not available, ASSERT here
      ASSERT (FALSE);
      return AGESA_ERROR;
    }
    StdHeader->HeapBasePtr = (UINT64) BaseAddress;
  }
  OffsetOfCurrentNode =  HeapManager->FirstActiveBufferOffset;
  CurrentNode = (BUFFER_NODE *) (BaseAddress + OffsetOfCurrentNode);

  // Find buffer using internal heap manager
  // Locate the heap using handle = LocateHeap-> BufferHandle
  // If HeapStatus != HEAP_SYSTEM_ MEM
  if ((BaseAddress != NULL) && (HeapManager->Signature == HEAP_SIGNATURE_VALID)) {
    if (OffsetOfCurrentNode == AMD_HEAP_INVALID_HEAP_OFFSET) {
      HeapLocateFlag = FALSE;
    } else {
      while (CurrentNode->BufferHandle != LocateHeap->BufferHandle) {
        if (CurrentNode->OffsetOfNextNode == AMD_HEAP_INVALID_HEAP_OFFSET) {
          HeapLocateFlag = FALSE;
          break;
        } else {
          OffsetOfCurrentNode = CurrentNode->OffsetOfNextNode;
          CurrentNode = (BUFFER_NODE *) (BaseAddress + OffsetOfCurrentNode);
        }
      }
    }
  } else {
    HeapLocateFlag = FALSE;
  }

  if (HeapLocateFlag) {
    AlignTo16Byte = CurrentNode->PadSize;
    LocateHeap->BufferPtr = (UINT8 *) ((UINT8 *) CurrentNode + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL + AlignTo16Byte);
    LocateHeap->BufferSize = CurrentNode->BufferSize - NUM_OF_SENTINEL * SIZE_OF_SENTINEL - AlignTo16Byte;
    return AGESA_SUCCESS;
  } else {
    // If HeapStatus == HEAP_SYSTEM_MEM, try callout function
    if (StdHeader->HeapStatus == HEAP_SYSTEM_MEM) {
      AgesaBuffer.StdHeader = *StdHeader;
      AgesaBuffer.BufferHandle = LocateHeap->BufferHandle;

      AGESA_TESTPOINT (TpIfBeforeLocateHeapBuffer, StdHeader);
      if (AgesaLocateBuffer (0, &AgesaBuffer) != AGESA_SUCCESS) {
        LocateHeap->BufferPtr = NULL;
        return AGESA_ERROR;
      }
      LocateHeap->BufferSize = AgesaBuffer.BufferLength;
      AGESA_TESTPOINT (TpIfAfterLocateHeapBuffer, StdHeader);

      LocateHeap->BufferPtr = (UINT8 *) (AgesaBuffer.BufferPointer);
      return AGESA_SUCCESS;
    }

    // If we are still unable to deallocate the buffer handle, return AGESA_BOUNDS_CHK
    LocateHeap->BufferPtr = NULL;
    LocateHeap->BufferSize = 0;
    if ((BaseAddress != NULL) && (HeapManager->Signature == HEAP_SIGNATURE_VALID)) {
      PutEventLog (AGESA_BOUNDS_CHK,
                   CPU_ERROR_HEAP_BUFFER_HANDLE_IS_NOT_PRESENT,
                   LocateHeap->BufferHandle, 0, 0, 0, StdHeader);
    } else {
      ASSERT (FALSE);
    }
    return AGESA_BOUNDS_CHK;
  }
}
Exemplo n.º 6
0
/**
 * Deallocates a previously allocated buffer in the heap
 *
 * This function will deallocate buffer either by using internal 'AGESA' heapmanager
 * or by using externa (IBV) heapmanager.
 *
 * @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
  )
{
  UINT8 *BaseAddress;
  UINT32 NodeSize;
  UINT32 OffsetOfFreeSpaceNode;
  UINT32 OffsetOfPreviousNode;
  UINT32 OffsetOfCurrentNode;
  BOOLEAN HeapLocateFlag;
  HEAP_MANAGER *HeapManager;
  BUFFER_NODE *CurrentNode;
  BUFFER_NODE *PreviousNode;
  BUFFER_NODE *FreeSpaceNode;
  AGESA_BUFFER_PARAMS  AgesaBuffer;

  ASSERT (StdHeader != NULL);

  HeapLocateFlag = TRUE;
  BaseAddress = (UINT8 *) (UINTN) StdHeader->HeapBasePtr;
  HeapManager = (HEAP_MANAGER *) BaseAddress;

  // Check Heap database is valid
  if ((BaseAddress == NULL) || (HeapManager->Signature != HEAP_SIGNATURE_VALID)) {
    // The base address in StdHeader is incorrect, get base address by itself
    BaseAddress = (UINT8 *) HeapGetBaseAddress (StdHeader);
    HeapManager = (HEAP_MANAGER *) BaseAddress;
    if ((BaseAddress == NULL) || (HeapManager->Signature != HEAP_SIGNATURE_VALID)) {
      // Heap is not available, ASSERT here
      ASSERT (FALSE);
      return AGESA_ERROR;
    }
    StdHeader->HeapBasePtr = (UINT64) BaseAddress;
  }

  OffsetOfPreviousNode = AMD_HEAP_INVALID_HEAP_OFFSET;
  OffsetOfCurrentNode =  HeapManager->FirstActiveBufferOffset;
  CurrentNode = (BUFFER_NODE *) (BaseAddress + OffsetOfCurrentNode);

  // Locate heap
  if ((BaseAddress != NULL) && (HeapManager->Signature == HEAP_SIGNATURE_VALID)) {
    if (OffsetOfCurrentNode == AMD_HEAP_INVALID_HEAP_OFFSET) {
      HeapLocateFlag = FALSE;
    } else {
      while (CurrentNode->BufferHandle != BufferHandle) {
        if (CurrentNode->OffsetOfNextNode == AMD_HEAP_INVALID_HEAP_OFFSET) {
          HeapLocateFlag = FALSE;
          break;
        } else {
          OffsetOfPreviousNode = OffsetOfCurrentNode;
          OffsetOfCurrentNode = CurrentNode->OffsetOfNextNode;
          CurrentNode = (BUFFER_NODE *) (BaseAddress + OffsetOfCurrentNode);
        }
      }
    }
  } else {
    HeapLocateFlag = FALSE;
  }

  if (HeapLocateFlag == TRUE) {
    // CurrentNode points to the buffer which wanted to be deallocated.
    // Remove deallocated heap from active buffer chain.
    if (OffsetOfPreviousNode == AMD_HEAP_INVALID_HEAP_OFFSET) {
      HeapManager->FirstActiveBufferOffset = CurrentNode->OffsetOfNextNode;
    } else {
      PreviousNode = (BUFFER_NODE *) (BaseAddress + OffsetOfPreviousNode);
      PreviousNode->OffsetOfNextNode = CurrentNode->OffsetOfNextNode;
    }
    // Now, CurrentNode become a free space node.
    HeapManager->UsedSize -= CurrentNode->BufferSize + sizeof (BUFFER_NODE);
    // Loop free space chain to see if any free space node is just before/after CurrentNode, then merge them.
    OffsetOfFreeSpaceNode = HeapManager->FirstFreeSpaceOffset;
    FreeSpaceNode = (BUFFER_NODE *) (BaseAddress + OffsetOfFreeSpaceNode);
    while (OffsetOfFreeSpaceNode != AMD_HEAP_INVALID_HEAP_OFFSET) {
      if ((OffsetOfFreeSpaceNode + sizeof (BUFFER_NODE) + FreeSpaceNode->BufferSize) == OffsetOfCurrentNode) {
        DeleteFreeSpaceNode (StdHeader, OffsetOfFreeSpaceNode);
        NodeSize = FreeSpaceNode->BufferSize + CurrentNode->BufferSize + sizeof (BUFFER_NODE);
        OffsetOfCurrentNode = OffsetOfFreeSpaceNode;
        CurrentNode = FreeSpaceNode;
        CurrentNode->BufferSize = NodeSize;
      } else if (OffsetOfFreeSpaceNode == (OffsetOfCurrentNode + sizeof (BUFFER_NODE) + CurrentNode->BufferSize)) {
        DeleteFreeSpaceNode (StdHeader, OffsetOfFreeSpaceNode);
        NodeSize = FreeSpaceNode->BufferSize + CurrentNode->BufferSize + sizeof (BUFFER_NODE);
        CurrentNode->BufferSize = NodeSize;
      }
      OffsetOfFreeSpaceNode = FreeSpaceNode->OffsetOfNextNode;
      FreeSpaceNode = (BUFFER_NODE *) (BaseAddress + OffsetOfFreeSpaceNode);
    }
    InsertFreeSpaceNode (StdHeader, OffsetOfCurrentNode);
    return AGESA_SUCCESS;
  } else {
    // If HeapStatus == HEAP_SYSTEM_MEM, try callout function
    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;
    }
    // If we are still unable to locate the buffer handle, return AGESA_BOUNDS_CHK
    if ((BaseAddress != NULL) && (HeapManager->Signature == HEAP_SIGNATURE_VALID)) {
      PutEventLog (AGESA_BOUNDS_CHK,
                 CPU_ERROR_HEAP_BUFFER_HANDLE_IS_NOT_PRESENT,
                 BufferHandle, 0, 0, 0, StdHeader);
    } else {
      ASSERT (FALSE);
    }
    return AGESA_BOUNDS_CHK;
  }
}
Exemplo n.º 7
0
/**
 * Allocates space for a new buffer in the heap
 *
 * This function will allocate new buffer either by using internal 'AGESA' heapmanager
 * or by using externa (IBV) heapmanager. This function will also determine 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]  AllocateHeapParams structure pointer 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
 * @retval         AGESA_UNSUPPORTED Do not support this kind of heap allocation
 * @retval         AGESA_ERROR       Heap is invaild
 *
 */
AGESA_STATUS
HeapAllocateBuffer (
  IN OUT   ALLOCATE_HEAP_PARAMS *AllocateHeapParams,
  IN OUT   AMD_CONFIG_PARAMS *StdHeader
  )
{
  UINT8 *BaseAddress;
  UINT8  AlignTo16Byte;
  UINT8  CalloutFcnData;
  UINT32 RemainSize;
  UINT32 OffsetOfSplitNode;
  UINT32 OffsetOfNode;
  HEAP_MANAGER *HeapManager;
  BUFFER_NODE *FreeSpaceNode;
  BUFFER_NODE *SplitFreeSpaceNode;
  BUFFER_NODE *CurrentBufferNode;
  BUFFER_NODE *NewBufferNode;
  AGESA_BUFFER_PARAMS  AgesaBuffer;

  ASSERT (StdHeader != NULL);
  if (AllocateHeapParams->Persist == HEAP_RUNTIME_SYSTEM_MEM) {
    ASSERT (StdHeader->HeapStatus == HEAP_SYSTEM_MEM);
    if (StdHeader->HeapStatus != HEAP_SYSTEM_MEM) {
      return AGESA_UNSUPPORTED;
    }
  }

  // At this stage we will decide to either use external (IBV) heap manger
  // or internal (AGESA) heap manager.

  // If (HeapStatus == HEAP_SYSTEM_MEM), then use the call function to call
  // external heap manager
  if (StdHeader->HeapStatus == HEAP_SYSTEM_MEM) {
    AgesaBuffer.StdHeader = *StdHeader;
    AgesaBuffer.BufferHandle = AllocateHeapParams->BufferHandle;
    AgesaBuffer.BufferLength = AllocateHeapParams->RequestedBufferSize;

    if (AllocateHeapParams->Persist == HEAP_RUNTIME_SYSTEM_MEM) {
      CalloutFcnData = HEAP_CALLOUT_RUNTIME;
    } else {
      CalloutFcnData = HEAP_CALLOUT_BOOTTIME;
    }
    AGESA_TESTPOINT (TpIfBeforeAllocateHeapBuffer, StdHeader);
    if (AgesaAllocateBuffer (CalloutFcnData, &AgesaBuffer) != AGESA_SUCCESS) {
      AllocateHeapParams->BufferPtr = NULL;
      return AGESA_ERROR;
    }
    AGESA_TESTPOINT (TpIfAfterAllocateHeapBuffer, StdHeader);

    AllocateHeapParams->BufferPtr = (UINT8 *) (AgesaBuffer.BufferPointer);
    return AGESA_SUCCESS;
  }

  // If (StdHeader->HeapStatus != HEAP_SYSTEM_MEM), then allocated buffer
  // using following AGESA Heap Manager code.

  // Buffer pointer is NULL unless we return a buffer.
  AlignTo16Byte = 0;
  AllocateHeapParams->BufferPtr = NULL;
  AllocateHeapParams->RequestedBufferSize += NUM_OF_SENTINEL * SIZE_OF_SENTINEL;

  // Get base address
  BaseAddress = (UINT8 *) (UINTN) StdHeader->HeapBasePtr;
  HeapManager = (HEAP_MANAGER *) BaseAddress;

  // Check Heap database is valid
  if ((BaseAddress == NULL) || (HeapManager->Signature != HEAP_SIGNATURE_VALID)) {
    // The base address in StdHeader is incorrect, get base address by itself
    BaseAddress = (UINT8 *) HeapGetBaseAddress (StdHeader);
    HeapManager = (HEAP_MANAGER *) BaseAddress;
    if ((BaseAddress == NULL) || (HeapManager->Signature != HEAP_SIGNATURE_VALID)) {
      // Heap is not available, ASSERT here
      ASSERT (FALSE);
      return AGESA_ERROR;
    }
    StdHeader->HeapBasePtr = (UINT64) BaseAddress;
  }

  // Allocate
  CurrentBufferNode = (BUFFER_NODE *) (BaseAddress + sizeof (HEAP_MANAGER));
  // If there already has been a heap with the incoming BufferHandle, we return AGESA_BOUNDS_CHK.
  if (HeapManager->FirstActiveBufferOffset != AMD_HEAP_INVALID_HEAP_OFFSET) {
    CurrentBufferNode = (BUFFER_NODE *) (BaseAddress + HeapManager->FirstActiveBufferOffset);
    while (CurrentBufferNode->OffsetOfNextNode != AMD_HEAP_INVALID_HEAP_OFFSET) {
      if (CurrentBufferNode->BufferHandle == AllocateHeapParams->BufferHandle) {
      PutEventLog (AGESA_BOUNDS_CHK,
                   CPU_ERROR_HEAP_BUFFER_HANDLE_IS_ALREADY_USED,
                   AllocateHeapParams->BufferHandle, 0, 0, 0, StdHeader);
        return AGESA_BOUNDS_CHK;
      } else {
        CurrentBufferNode = (BUFFER_NODE *) (BaseAddress + CurrentBufferNode->OffsetOfNextNode);
      }
    }
    if (CurrentBufferNode->BufferHandle == AllocateHeapParams->BufferHandle) {
      PutEventLog (AGESA_BOUNDS_CHK,
                   CPU_ERROR_HEAP_BUFFER_HANDLE_IS_ALREADY_USED,
                   AllocateHeapParams->BufferHandle, 0, 0, 0, StdHeader);
      return AGESA_BOUNDS_CHK;
    }
  }

  // Find the buffer size that first matches the requested buffer size (i.e. the first free buffer of greater size).
  OffsetOfNode = HeapManager->FirstFreeSpaceOffset;
  FreeSpaceNode = (BUFFER_NODE *) (BaseAddress + OffsetOfNode);
  while (OffsetOfNode != AMD_HEAP_INVALID_HEAP_OFFSET) {
    AlignTo16Byte = (UINT8) ((0x10 - (((UINTN) (VOID *) FreeSpaceNode + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL) & 0xF)) & 0xF);
    AllocateHeapParams->RequestedBufferSize = (UINT32) (AllocateHeapParams->RequestedBufferSize + AlignTo16Byte);
    if (FreeSpaceNode->BufferSize >= AllocateHeapParams->RequestedBufferSize) {
      break;
    }
    AllocateHeapParams->RequestedBufferSize = (UINT32) (AllocateHeapParams->RequestedBufferSize - AlignTo16Byte);
    OffsetOfNode = FreeSpaceNode->OffsetOfNextNode;
    FreeSpaceNode = (BUFFER_NODE *) (BaseAddress + OffsetOfNode);
  }
  if (OffsetOfNode == AMD_HEAP_INVALID_HEAP_OFFSET) {
    // We don't find any free space buffer that matches the requested buffer size.
    PutEventLog (AGESA_BOUNDS_CHK,
                 CPU_ERROR_HEAP_IS_FULL,
                 AllocateHeapParams->BufferHandle, 0, 0, 0, StdHeader);
    return AGESA_BOUNDS_CHK;
  } else {
    // We find one matched free space buffer.
    DeleteFreeSpaceNode (StdHeader, OffsetOfNode);
    NewBufferNode = FreeSpaceNode;
    // Add new buffer node to the buffer chain
    if (HeapManager->FirstActiveBufferOffset == AMD_HEAP_INVALID_HEAP_OFFSET) {
      HeapManager->FirstActiveBufferOffset = sizeof (HEAP_MANAGER);
    } else {
      CurrentBufferNode->OffsetOfNextNode = OffsetOfNode;
    }
    // New buffer size
    RemainSize = FreeSpaceNode->BufferSize - AllocateHeapParams->RequestedBufferSize;
    if (RemainSize > sizeof (BUFFER_NODE)) {
      NewBufferNode->BufferSize = AllocateHeapParams->RequestedBufferSize;
      OffsetOfSplitNode = OffsetOfNode + sizeof (BUFFER_NODE) + NewBufferNode->BufferSize;
      SplitFreeSpaceNode = (BUFFER_NODE *) (BaseAddress + OffsetOfSplitNode);
      SplitFreeSpaceNode->BufferSize = RemainSize - sizeof (BUFFER_NODE);
      InsertFreeSpaceNode (StdHeader, OffsetOfSplitNode);
    } else {
      // Remain size is less than BUFFER_NODE, we use whole size instead of requested size.
      NewBufferNode->BufferSize = FreeSpaceNode->BufferSize;
    }
  }

  // Initialize BUFFER_NODE structure of NewBufferNode
  NewBufferNode->BufferHandle = AllocateHeapParams->BufferHandle;
  if ((AllocateHeapParams->Persist == HEAP_TEMP_MEM) || (AllocateHeapParams->Persist == HEAP_SYSTEM_MEM)) {
    NewBufferNode->Persist = AllocateHeapParams->Persist;
  } else {
    NewBufferNode->Persist = HEAP_LOCAL_CACHE;
  }
  NewBufferNode->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
  NewBufferNode->PadSize = AlignTo16Byte;

  // Clear to 0x00
  LibAmdMemFill ((VOID *) ((UINT8 *) NewBufferNode + sizeof (BUFFER_NODE)), 0x00, NewBufferNode->BufferSize, StdHeader);

  // Debug feature
  SET_SENTINEL_BEFORE (NewBufferNode, AlignTo16Byte);
  SET_SENTINEL_AFTER (NewBufferNode);

  // Update global variables
  HeapManager->UsedSize += NewBufferNode->BufferSize + sizeof (BUFFER_NODE);

  // Now fill in the incoming structure
  AllocateHeapParams->BufferPtr = (UINT8 *) ((UINT8 *) NewBufferNode + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL + AlignTo16Byte);
  AllocateHeapParams->RequestedBufferSize -= (NUM_OF_SENTINEL * SIZE_OF_SENTINEL + AlignTo16Byte);

  return AGESA_SUCCESS;
}