/** @file\r
MP initialize support functions for PEI phase.\r
\r
- Copyright (c) 2016, 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
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "MpLib.h"\r
-#include <Ppi/EndOfPeiPhase.h>\r
#include <Library/PeiServicesLib.h>\r
+#include <Guid/S3SmmInitDone.h>\r
+#include <Ppi/ShadowMicrocode.h>\r
\r
-//\r
-// Global PEI notify function descriptor on EndofPei event\r
-//\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_NOTIFY_DESCRIPTOR mMpInitLibNotifyList = {\r
- (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
- &gEfiEndOfPeiSignalPpiGuid,\r
- CpuMpEndOfPeiCallback\r
-};\r
+STATIC UINT64 mSevEsPeiWakeupBuffer = BASE_1MB;\r
\r
/**\r
- Get pointer to CPU MP Data structure.\r
+ S3 SMM Init Done notification function.\r
+\r
+ @param PeiServices Indirect reference to the PEI Services Table.\r
+ @param NotifyDesc Address of the notification descriptor data structure.\r
+ @param InvokePpi Address of the PPI that was invoked.\r
+\r
+ @retval EFI_SUCCESS The function completes successfully.\r
\r
- @return The pointer to CPU MP Data structure.\r
**/\r
-CPU_MP_DATA *\r
-GetCpuMpData (\r
- VOID\r
- )\r
-{\r
- CPU_MP_DATA *CpuMpData;\r
+EFI_STATUS\r
+EFIAPI\r
+NotifyOnS3SmmInitDonePpi (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
+ IN VOID *InvokePpi\r
+ );\r
\r
- CpuMpData = GetCpuMpDataFromGuidedHob ();\r
- ASSERT (CpuMpData != NULL);\r
- return CpuMpData;\r
-}\r
+//\r
+// Global function\r
+//\r
+EFI_PEI_NOTIFY_DESCRIPTOR mS3SmmInitDoneNotifyDesc = {\r
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
+ &gEdkiiS3SmmInitDoneGuid,\r
+ NotifyOnS3SmmInitDonePpi\r
+};\r
\r
/**\r
- Save the pointer to CPU MP Data structure.\r
+ S3 SMM Init Done notification function.\r
+\r
+ @param PeiServices Indirect reference to the PEI Services Table.\r
+ @param NotifyDesc Address of the notification descriptor data structure.\r
+ @param InvokePpi Address of the PPI that was invoked.\r
+\r
+ @retval EFI_SUCCESS The function completes successfully.\r
\r
- @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.\r
**/\r
-VOID\r
-SaveCpuMpData (\r
- IN CPU_MP_DATA *CpuMpData\r
+EFI_STATUS\r
+EFIAPI\r
+NotifyOnS3SmmInitDonePpi (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
+ IN VOID *InvokePpi\r
)\r
{\r
- UINT64 Data64;\r
+ CPU_MP_DATA *CpuMpData;\r
+\r
+ CpuMpData = GetCpuMpData ();\r
+\r
//\r
- // Build location of CPU MP DATA buffer in HOB\r
+ // PiSmmCpuDxeSmm driver hardcode change the loop mode to HLT mode.\r
+ // So in this notify function, code need to check the current loop\r
+ // mode, if it is not HLT mode, code need to change loop mode back\r
+ // to the original mode.\r
//\r
- Data64 = (UINT64) (UINTN) CpuMpData;\r
- BuildGuidDataHob (\r
- &mCpuInitMpLibHobGuid,\r
- (VOID *) &Data64,\r
- sizeof (UINT64)\r
- );\r
+ if (CpuMpData->ApLoopMode != ApInHltLoop) {\r
+ CpuMpData->WakeUpByInitSipiSipi = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
- Get available system memory below 1MB by specified size.\r
+ Enable Debug Agent to support source debugging on AP function.\r
\r
- @param[in] CpuMpData The pointer to CPU MP Data structure.\r
**/\r
VOID\r
-BackupAndPrepareWakeupBuffer(\r
- IN CPU_MP_DATA *CpuMpData\r
+EnableDebugAgent (\r
+ VOID\r
)\r
{\r
- CopyMem (\r
- (VOID *) CpuMpData->BackupBuffer,\r
- (VOID *) CpuMpData->WakeupBuffer,\r
- CpuMpData->BackupBufferSize\r
- );\r
- CopyMem (\r
- (VOID *) CpuMpData->WakeupBuffer,\r
- (VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress,\r
- CpuMpData->AddressMap.RendezvousFunnelSize\r
- );\r
}\r
\r
/**\r
- Restore wakeup buffer data.\r
+ Get pointer to CPU MP Data structure.\r
+ For BSP, the pointer is retrieved from HOB.\r
+ For AP, the structure is just after IDT.\r
\r
- @param[in] CpuMpData The pointer to CPU MP Data structure.\r
+ @return The pointer to CPU MP Data structure.\r
**/\r
-VOID\r
-RestoreWakeupBuffer(\r
- IN CPU_MP_DATA *CpuMpData\r
+CPU_MP_DATA *\r
+GetCpuMpData (\r
+ VOID\r
)\r
{\r
- CopyMem (\r
- (VOID *) CpuMpData->WakeupBuffer,\r
- (VOID *) CpuMpData->BackupBuffer,\r
- CpuMpData->BackupBufferSize\r
- );\r
+ CPU_MP_DATA *CpuMpData;\r
+ MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;\r
+ IA32_DESCRIPTOR Idtr;\r
+\r
+ ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);\r
+ if (ApicBaseMsr.Bits.BSP == 1) {\r
+ CpuMpData = GetCpuMpDataFromGuidedHob ();\r
+ ASSERT (CpuMpData != NULL);\r
+ } else {\r
+ AsmReadIdtr (&Idtr);\r
+ CpuMpData = (CPU_MP_DATA *)(Idtr.Base + Idtr.Limit + 1);\r
+ }\r
+\r
+ return CpuMpData;\r
}\r
\r
/**\r
- Notify function on End Of PEI PPI.\r
-\r
- On S3 boot, this function will restore wakeup buffer data.\r
- On normal boot, this function will flag wakeup buffer to be un-used type.\r
-\r
- @param[in] PeiServices The pointer to the PEI Services Table.\r
- @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
- @param[in] Ppi Address of the PPI that was installed.\r
+ Save the pointer to CPU MP Data structure.\r
\r
- @retval EFI_SUCCESS When everything is OK.\r
+ @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.\r
**/\r
-EFI_STATUS\r
-EFIAPI\r
-CpuMpEndOfPeiCallback (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
- IN VOID *Ppi\r
+VOID\r
+SaveCpuMpData (\r
+ IN CPU_MP_DATA *CpuMpData\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_BOOT_MODE BootMode;\r
- CPU_MP_DATA *CpuMpData;\r
- EFI_PEI_HOB_POINTERS Hob;\r
- EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
-\r
- DEBUG ((DEBUG_INFO, "PeiMpInitLib: CpuMpEndOfPeiCallback () invoked\n"));\r
+ UINT64 Data64;\r
\r
- Status = PeiServicesGetBootMode (&BootMode);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- CpuMpData = GetCpuMpData ();\r
- if (BootMode != BOOT_ON_S3_RESUME) {\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
- if (MemoryHob->AllocDescriptor.MemoryBaseAddress == CpuMpData->WakeupBuffer) {\r
- //\r
- // Flag this HOB type to un-used\r
- //\r
- GET_HOB_TYPE (Hob) = EFI_HOB_TYPE_UNUSED;\r
- break;\r
- }\r
- }\r
- Hob.Raw = GET_NEXT_HOB (Hob);\r
- }\r
- } else {\r
- CpuMpData->SaveRestoreFlag = TRUE;\r
- RestoreWakeupBuffer (CpuMpData);\r
- }\r
- return EFI_SUCCESS;\r
+ //\r
+ // Build location of CPU MP DATA buffer in HOB\r
+ //\r
+ Data64 = (UINT64)(UINTN)CpuMpData;\r
+ BuildGuidDataHob (\r
+ &mCpuInitMpLibHobGuid,\r
+ (VOID *)&Data64,\r
+ sizeof (UINT64)\r
+ );\r
}\r
\r
/**\r
**/\r
BOOLEAN\r
CheckOverlapWithAllocatedBuffer (\r
- IN UINTN WakeupBufferStart,\r
- IN UINTN WakeupBufferEnd\r
+ IN UINT64 WakeupBufferStart,\r
+ IN UINT64 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
+ EFI_PEI_HOB_POINTERS Hob;\r
+ EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
+ BOOLEAN Overlapped;\r
+ UINT64 MemoryStart;\r
+ UINT64 MemoryEnd;\r
\r
Overlapped = FALSE;\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
+ MemoryStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
+ MemoryEnd = MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength;\r
if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) {\r
Overlapped = TRUE;\r
break;\r
}\r
}\r
+\r
Hob.Raw = GET_NEXT_HOB (Hob);\r
}\r
+\r
return Overlapped;\r
}\r
\r
**/\r
UINTN\r
GetWakeupBuffer (\r
- IN UINTN WakeupBufferSize\r
+ IN UINTN WakeupBufferSize\r
)\r
{\r
- EFI_PEI_HOB_POINTERS Hob;\r
- UINTN WakeupBufferStart;\r
- UINTN WakeupBufferEnd;\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+ UINT64 WakeupBufferStart;\r
+ UINT64 WakeupBufferEnd;\r
\r
WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);\r
\r
(EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |\r
EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |\r
EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED\r
- )) == 0)\r
- ) {\r
+ )) == 0)\r
+ )\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
+ WakeupBufferEnd = Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength;\r
+ if (ConfidentialComputingGuestHas (CCAttrAmdSevEs) &&\r
+ (WakeupBufferEnd > mSevEsPeiWakeupBuffer))\r
+ {\r
+ //\r
+ // SEV-ES Wakeup buffer should be under 1MB and under any previous one\r
+ //\r
+ WakeupBufferEnd = mSevEsPeiWakeupBuffer;\r
+ } else if (WakeupBufferEnd > BASE_1MB) {\r
//\r
// Wakeup buffer should be under 1MB\r
//\r
WakeupBufferEnd = BASE_1MB;\r
}\r
+\r
while (WakeupBufferEnd > WakeupBufferSize) {\r
//\r
// Wakeup buffer should be aligned on 4KB\r
if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {\r
break;\r
}\r
+\r
if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) {\r
//\r
// If this range is overlapped with existing allocated buffer, skip it\r
WakeupBufferEnd -= WakeupBufferSize;\r
continue;\r
}\r
- DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",\r
- WakeupBufferStart, WakeupBufferSize));\r
- //\r
- // Create a memory allocation HOB.\r
- //\r
- BuildMemoryAllocationHob (\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "WakeupBufferStart = %x, WakeupBufferSize = %x\n",\r
WakeupBufferStart,\r
- WakeupBufferSize,\r
- EfiBootServicesData\r
- );\r
- return WakeupBufferStart;\r
+ WakeupBufferSize\r
+ ));\r
+\r
+ if (ConfidentialComputingGuestHas (CCAttrAmdSevEs)) {\r
+ //\r
+ // Next SEV-ES wakeup buffer allocation must be below this\r
+ // allocation\r
+ //\r
+ mSevEsPeiWakeupBuffer = WakeupBufferStart;\r
+ }\r
+\r
+ return (UINTN)WakeupBufferStart;\r
}\r
}\r
}\r
+\r
//\r
// Find the next HOB\r
//\r
Hob.Raw = GET_NEXT_HOB (Hob);\r
}\r
\r
- return (UINTN) -1;\r
+ return (UINTN)-1;\r
}\r
\r
/**\r
- Allocate reset vector buffer.\r
+ Get available EfiBootServicesCode memory below 4GB by specified size.\r
+\r
+ This buffer is required to safely transfer AP from real address mode to\r
+ protected mode or long mode, due to the fact that the buffer returned by\r
+ GetWakeupBuffer() may be marked as non-executable.\r
+\r
+ @param[in] BufferSize Wakeup transition buffer size.\r
\r
- @param[in, out] CpuMpData The pointer to CPU MP Data structure.\r
+ @retval other Return wakeup transition buffer address below 4GB.\r
+ @retval 0 Cannot find free memory below 4GB.\r
**/\r
-VOID\r
-AllocateResetVector (\r
- IN OUT CPU_MP_DATA *CpuMpData\r
+UINTN\r
+GetModeTransitionBuffer (\r
+ IN UINTN BufferSize\r
)\r
{\r
- UINTN ApResetVectorSize;\r
+ //\r
+ // PEI phase doesn't need to do such transition. So simply return 0.\r
+ //\r
+ return 0;\r
+}\r
\r
- if (CpuMpData->WakeupBuffer == (UINTN) -1) {\r
- ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +\r
- sizeof (MP_CPU_EXCHANGE_INFO);\r
+/**\r
+ Return the address of the SEV-ES AP jump table.\r
\r
- CpuMpData->WakeupBuffer = GetWakeupBuffer (ApResetVectorSize);\r
- CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)\r
- (CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);\r
- BackupAndPrepareWakeupBuffer (CpuMpData);\r
- }\r
+ This buffer is required in order for an SEV-ES guest to transition from\r
+ UEFI into an OS.\r
\r
- if (CpuMpData->SaveRestoreFlag) {\r
- BackupAndPrepareWakeupBuffer (CpuMpData);\r
- }\r
+ @return Return SEV-ES AP jump table buffer\r
+**/\r
+UINTN\r
+GetSevEsAPMemory (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // PEI phase doesn't need to do such transition. So simply return 0.\r
+ //\r
+ return 0;\r
}\r
\r
/**\r
- Free AP reset vector buffer.\r
+ Checks APs status and updates APs status if needed.\r
\r
- @param[in] CpuMpData The pointer to CPU MP Data structure.\r
**/\r
VOID\r
-FreeResetVector (\r
- IN CPU_MP_DATA *CpuMpData\r
+CheckAndUpdateApsStatus (\r
+ VOID\r
)\r
{\r
- if (CpuMpData->SaveRestoreFlag) {\r
- RestoreWakeupBuffer (CpuMpData);\r
- }\r
}\r
\r
/**\r
- Checks APs status and updates APs status if needed.\r
+ Build the microcode patch HOB that contains the base address and size of the\r
+ microcode patch stored in the memory.\r
+\r
+ @param[in] CpuMpData Pointer to the CPU_MP_DATA structure.\r
\r
**/\r
VOID\r
-CheckAndUpdateApsStatus (\r
- VOID\r
+BuildMicrocodeCacheHob (\r
+ IN CPU_MP_DATA *CpuMpData\r
)\r
{\r
+ EDKII_MICROCODE_PATCH_HOB *MicrocodeHob;\r
+ UINTN HobDataLength;\r
+ UINT32 Index;\r
+\r
+ HobDataLength = sizeof (EDKII_MICROCODE_PATCH_HOB) +\r
+ sizeof (UINT64) * CpuMpData->CpuCount;\r
+\r
+ MicrocodeHob = AllocatePool (HobDataLength);\r
+ if (MicrocodeHob == NULL) {\r
+ ASSERT (FALSE);\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Store the information of the memory region that holds the microcode patches.\r
+ //\r
+ MicrocodeHob->MicrocodePatchAddress = CpuMpData->MicrocodePatchAddress;\r
+ MicrocodeHob->MicrocodePatchRegionSize = CpuMpData->MicrocodePatchRegionSize;\r
+\r
+ //\r
+ // Store the detected microcode patch for each processor as well.\r
+ //\r
+ MicrocodeHob->ProcessorCount = CpuMpData->CpuCount;\r
+ for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
+ if (CpuMpData->CpuData[Index].MicrocodeEntryAddr != 0) {\r
+ MicrocodeHob->ProcessorSpecificPatchOffset[Index] =\r
+ CpuMpData->CpuData[Index].MicrocodeEntryAddr - CpuMpData->MicrocodePatchAddress;\r
+ } else {\r
+ MicrocodeHob->ProcessorSpecificPatchOffset[Index] = MAX_UINT64;\r
+ }\r
+ }\r
+\r
+ BuildGuidDataHob (\r
+ &gEdkiiMicrocodePatchHobGuid,\r
+ MicrocodeHob,\r
+ HobDataLength\r
+ );\r
+\r
+ return;\r
}\r
\r
/**\r
**/\r
VOID\r
InitMpGlobalData (\r
- IN CPU_MP_DATA *CpuMpData\r
+ IN CPU_MP_DATA *CpuMpData\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
+ BuildMicrocodeCacheHob (CpuMpData);\r
SaveCpuMpData (CpuMpData);\r
- //\r
- // Register an event for EndOfPei\r
- //\r
- Status = PeiServicesNotifyPpi (&mMpInitLibNotifyList);\r
+\r
+ ///\r
+ /// Install Notify\r
+ ///\r
+ Status = PeiServicesNotifyPpi (&mS3SmmInitDoneNotifyDesc);\r
ASSERT_EFI_ERROR (Status);\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
EFI_STATUS\r
EFIAPI\r
MpInitLibStartupAllAPs (\r
- IN EFI_AP_PROCEDURE Procedure,\r
- IN BOOLEAN SingleThread,\r
- IN EFI_EVENT WaitEvent OPTIONAL,\r
- IN UINTN TimeoutInMicroseconds,\r
- IN VOID *ProcedureArgument OPTIONAL,\r
- OUT UINTN **FailedCpuList OPTIONAL\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN BOOLEAN SingleThread,\r
+ IN EFI_EVENT WaitEvent OPTIONAL,\r
+ IN UINTN TimeoutInMicroseconds,\r
+ IN VOID *ProcedureArgument OPTIONAL,\r
+ OUT UINTN **FailedCpuList OPTIONAL\r
)\r
{\r
if (WaitEvent != NULL) {\r
return EFI_UNSUPPORTED;\r
}\r
\r
- return StartupAllAPsWorker (\r
+ return StartupAllCPUsWorker (\r
Procedure,\r
SingleThread,\r
+ TRUE,\r
NULL,\r
TimeoutInMicroseconds,\r
ProcedureArgument,\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
EFI_STATUS\r
EFIAPI\r
MpInitLibStartupThisAP (\r
- IN EFI_AP_PROCEDURE Procedure,\r
- IN UINTN ProcessorNumber,\r
- IN EFI_EVENT WaitEvent OPTIONAL,\r
- IN UINTN TimeoutInMicroseconds,\r
- IN VOID *ProcedureArgument OPTIONAL,\r
- OUT BOOLEAN *Finished OPTIONAL\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN UINTN ProcessorNumber,\r
+ IN EFI_EVENT WaitEvent OPTIONAL,\r
+ IN UINTN TimeoutInMicroseconds,\r
+ IN VOID *ProcedureArgument OPTIONAL,\r
+ OUT BOOLEAN *Finished OPTIONAL\r
)\r
{\r
if (WaitEvent != NULL) {\r
EFI_STATUS\r
EFIAPI\r
MpInitLibSwitchBSP (\r
- IN UINTN ProcessorNumber,\r
- IN BOOLEAN EnableOldBSP\r
+ IN UINTN ProcessorNumber,\r
+ IN BOOLEAN EnableOldBSP\r
)\r
{\r
return SwitchBSPWorker (ProcessorNumber, EnableOldBSP);\r
EFI_STATUS\r
EFIAPI\r
MpInitLibEnableDisableAP (\r
- IN UINTN ProcessorNumber,\r
- IN BOOLEAN EnableAP,\r
- IN UINT32 *HealthFlag OPTIONAL\r
+ IN UINTN ProcessorNumber,\r
+ IN BOOLEAN EnableAP,\r
+ IN UINT32 *HealthFlag OPTIONAL\r
)\r
{\r
return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);\r
}\r
\r
+/**\r
+ This funtion will try to invoke platform specific microcode shadow logic to\r
+ relocate microcode update patches into memory.\r
+\r
+ @param[in, out] CpuMpData The pointer to CPU MP Data structure.\r
+\r
+ @retval EFI_SUCCESS Shadow microcode success.\r
+ @retval EFI_OUT_OF_RESOURCES No enough resource to complete the operation.\r
+ @retval EFI_UNSUPPORTED Can't find platform specific microcode shadow\r
+ PPI/Protocol.\r
+**/\r
+EFI_STATUS\r
+PlatformShadowMicrocode (\r
+ IN OUT CPU_MP_DATA *CpuMpData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EDKII_PEI_SHADOW_MICROCODE_PPI *ShadowMicrocodePpi;\r
+ UINTN CpuCount;\r
+ EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuId;\r
+ UINTN Index;\r
+ UINTN BufferSize;\r
+ VOID *Buffer;\r
+\r
+ Status = PeiServicesLocatePpi (\r
+ &gEdkiiPeiShadowMicrocodePpiGuid,\r
+ 0,\r
+ NULL,\r
+ (VOID **)&ShadowMicrocodePpi\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ CpuCount = CpuMpData->CpuCount;\r
+ MicrocodeCpuId = (EDKII_PEI_MICROCODE_CPU_ID *)AllocateZeroPool (sizeof (EDKII_PEI_MICROCODE_CPU_ID) * CpuCount);\r
+ if (MicrocodeCpuId == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
+ MicrocodeCpuId[Index].ProcessorSignature = CpuMpData->CpuData[Index].ProcessorSignature;\r
+ MicrocodeCpuId[Index].PlatformId = CpuMpData->CpuData[Index].PlatformId;\r
+ }\r
+\r
+ Status = ShadowMicrocodePpi->ShadowMicrocode (\r
+ ShadowMicrocodePpi,\r
+ CpuCount,\r
+ MicrocodeCpuId,\r
+ &BufferSize,\r
+ &Buffer\r
+ );\r
+ FreePool (MicrocodeCpuId);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ CpuMpData->MicrocodePatchAddress = (UINTN)Buffer;\r
+ CpuMpData->MicrocodePatchRegionSize = BufferSize;\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",\r
+ __FUNCTION__,\r
+ CpuMpData->MicrocodePatchAddress,\r
+ CpuMpData->MicrocodePatchRegionSize\r
+ ));\r
\r
+ return EFI_SUCCESS;\r
+}\r