/** * 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; }
/** * 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); }
/** * * 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; }
/** * 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; }
/** * 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; } }
/** * 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; } }
/** * 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; }