/** @file\r
MP initialize support functions for PEI phase.\r
\r
- Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
\r
#include "MpLib.h"\r
\r
+/**\r
+ Enable Debug Agent to support source debugging on AP function.\r
+\r
+**/\r
+VOID\r
+EnableDebugAgent (\r
+ VOID\r
+ )\r
+{\r
+}\r
+\r
/**\r
Get pointer to CPU MP Data structure.\r
\r
);\r
}\r
\r
+/**\r
+ Check if AP wakeup buffer is overlapped with existing allocated buffer.\r
+\r
+ @param[in] WakeupBufferStart AP wakeup buffer start address.\r
+ @param[in] WakeupBufferEnd AP wakeup buffer end address.\r
+\r
+ @retval TRUE There is overlap.\r
+ @retval FALSE There is no overlap.\r
+**/\r
+BOOLEAN\r
+CheckOverlapWithAllocatedBuffer (\r
+ IN UINTN WakeupBufferStart,\r
+ IN UINTN WakeupBufferEnd\r
+ )\r
+{\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+ EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
+ BOOLEAN Overlapped;\r
+ UINTN MemoryStart;\r
+ UINTN MemoryEnd;\r
+\r
+ Overlapped = FALSE;\r
+ //\r
+ // Get the HOB list for processing\r
+ //\r
+ Hob.Raw = GetHobList ();\r
+ //\r
+ // Collect memory ranges\r
+ //\r
+ while (!END_OF_HOB_LIST (Hob)) {\r
+ if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
+ MemoryHob = Hob.MemoryAllocation;\r
+ MemoryStart = (UINTN) MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
+ MemoryEnd = (UINTN) (MemoryHob->AllocDescriptor.MemoryBaseAddress +\r
+ MemoryHob->AllocDescriptor.MemoryLength);\r
+ if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) {\r
+ Overlapped = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ Hob.Raw = GET_NEXT_HOB (Hob);\r
+ }\r
+ return Overlapped;\r
+}\r
+\r
+/**\r
+ Get available system memory below 1MB by specified size.\r
+\r
+ @param[in] WakeupBufferSize Wakeup buffer size required\r
+\r
+ @retval other Return wakeup buffer address below 1MB.\r
+ @retval -1 Cannot find free memory below 1MB.\r
+**/\r
+UINTN\r
+GetWakeupBuffer (\r
+ IN UINTN WakeupBufferSize\r
+ )\r
+{\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+ UINTN WakeupBufferStart;\r
+ UINTN WakeupBufferEnd;\r
+\r
+ WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);\r
+\r
+ //\r
+ // Get the HOB list for processing\r
+ //\r
+ Hob.Raw = GetHobList ();\r
+\r
+ //\r
+ // Collect memory ranges\r
+ //\r
+ while (!END_OF_HOB_LIST (Hob)) {\r
+ if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+ if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) &&\r
+ (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&\r
+ ((Hob.ResourceDescriptor->ResourceAttribute &\r
+ (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |\r
+ EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED\r
+ )) == 0)\r
+ ) {\r
+ //\r
+ // Need memory under 1MB to be collected here\r
+ //\r
+ WakeupBufferEnd = (UINTN) (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength);\r
+ if (WakeupBufferEnd > BASE_1MB) {\r
+ //\r
+ // Wakeup buffer should be under 1MB\r
+ //\r
+ WakeupBufferEnd = BASE_1MB;\r
+ }\r
+ while (WakeupBufferEnd > WakeupBufferSize) {\r
+ //\r
+ // Wakeup buffer should be aligned on 4KB\r
+ //\r
+ WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);\r
+ if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {\r
+ break;\r
+ }\r
+ if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) {\r
+ //\r
+ // If this range is overlapped with existing allocated buffer, skip it\r
+ // and find the next range\r
+ //\r
+ WakeupBufferEnd -= WakeupBufferSize;\r
+ continue;\r
+ }\r
+ DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",\r
+ WakeupBufferStart, WakeupBufferSize));\r
+ return WakeupBufferStart;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Find the next HOB\r
+ //\r
+ Hob.Raw = GET_NEXT_HOB (Hob);\r
+ }\r
+\r
+ return (UINTN) -1;\r
+}\r
+\r
+/**\r
+ Checks APs status and updates APs status if needed.\r
+\r
+**/\r
+VOID\r
+CheckAndUpdateApsStatus (\r
+ VOID\r
+ )\r
+{\r
+}\r
\r
/**\r
Initialize global data for MP support.\r
IN CPU_MP_DATA *CpuMpData\r
)\r
{\r
-\r
SaveCpuMpData (CpuMpData);\r
}\r
\r
EFI_EVENT is defined in CreateEvent() in\r
the Unified Extensible Firmware Interface\r
Specification.\r
- @param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for\r
+ @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
APs to return from Procedure, either for\r
blocking or non-blocking mode. Zero means\r
infinity. If the timeout expires before\r
OUT UINTN **FailedCpuList OPTIONAL\r
)\r
{\r
- return EFI_UNSUPPORTED;\r
+ if (WaitEvent != NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return StartupAllAPsWorker (\r
+ Procedure,\r
+ SingleThread,\r
+ NULL,\r
+ TimeoutInMicroseconds,\r
+ ProcedureArgument,\r
+ FailedCpuList\r
+ );\r
}\r
\r
/**\r
EFI_EVENT is defined in CreateEvent() in\r
the Unified Extensible Firmware Interface\r
Specification.\r
- @param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for\r
+ @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
this AP to finish this Procedure, either for\r
blocking or non-blocking mode. Zero means\r
infinity. If the timeout expires before\r
OUT BOOLEAN *Finished OPTIONAL\r
)\r
{\r
- return EFI_UNSUPPORTED;\r
+ if (WaitEvent != NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return StartupThisAPWorker (\r
+ Procedure,\r
+ ProcessorNumber,\r
+ NULL,\r
+ TimeoutInMicroseconds,\r
+ ProcedureArgument,\r
+ Finished\r
+ );\r
}\r
\r
/**\r
IN BOOLEAN EnableOldBSP\r
)\r
{\r
- return EFI_UNSUPPORTED;\r
+ return SwitchBSPWorker (ProcessorNumber, EnableOldBSP);\r
}\r
\r
/**\r
IN UINT32 *HealthFlag OPTIONAL\r
)\r
{\r
- return EFI_UNSUPPORTED;\r
+ return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);\r
}\r
\r
\r