\r
if (!EFI_ERROR(Status)) {\r
InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);\r
+ DumpPrivateInfo (MicrocodeFmpPrivate);\r
}\r
\r
return Status;\r
return EFI_UNSUPPORTED;\r
}\r
\r
+/**\r
+ Initialize Processor Microcode Index.\r
+\r
+ @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
+**/\r
+VOID\r
+InitializedProcessorMicrocodeIndex (\r
+ IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
+ )\r
+{\r
+ UINTN CpuIndex;\r
+ UINTN MicrocodeIndex;\r
+ UINTN TargetCpuIndex;\r
+ UINT32 AttemptStatus;\r
+ EFI_STATUS Status;\r
+\r
+ for (CpuIndex = 0; CpuIndex < MicrocodeFmpPrivate->ProcessorCount; CpuIndex++) {\r
+ if (MicrocodeFmpPrivate->ProcessorInfo[CpuIndex].MicrocodeIndex != (UINTN)-1) {\r
+ continue;\r
+ }\r
+ for (MicrocodeIndex = 0; MicrocodeIndex < MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) {\r
+ if (!MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex].InUse) {\r
+ continue;\r
+ }\r
+ TargetCpuIndex = CpuIndex;\r
+ Status = VerifyMicrocode(\r
+ MicrocodeFmpPrivate,\r
+ MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex].MicrocodeEntryPoint,\r
+ MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex].TotalSize,\r
+ FALSE,\r
+ &AttemptStatus,\r
+ NULL,\r
+ &TargetCpuIndex\r
+ );\r
+ if (!EFI_ERROR(Status)) {\r
+ MicrocodeFmpPrivate->ProcessorInfo[CpuIndex].MicrocodeIndex = MicrocodeIndex;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
/**\r
Initialize Microcode Descriptor.\r
\r
CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate, MicrocodeFmpPrivate->DescriptorCount, MicrocodeFmpPrivate->ImageDescriptor, MicrocodeFmpPrivate->MicrocodeInfo);\r
ASSERT(CurrentMicrocodeCount == MicrocodeFmpPrivate->DescriptorCount);\r
\r
+ InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);\r
+\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Initialize MicrocodeFmpDriver multiprocessor information.\r
+\r
+ @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
+\r
+ @return EFI_SUCCESS private data is initialized.\r
+**/\r
+EFI_STATUS\r
+InitializeProcessorInfo (\r
+ IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_MP_SERVICES_PROTOCOL *MpService;\r
+ UINTN NumberOfProcessors;\r
+ UINTN NumberOfEnabledProcessors;\r
+ UINTN Index;\r
+ UINTN BspIndex;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpService);\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ MicrocodeFmpPrivate->MpService = MpService;\r
+ MicrocodeFmpPrivate->ProcessorCount = 0;\r
+ MicrocodeFmpPrivate->ProcessorInfo = NULL;\r
+\r
+ Status = MpService->GetNumberOfProcessors (MpService, &NumberOfProcessors, &NumberOfEnabledProcessors);\r
+ ASSERT_EFI_ERROR(Status);\r
+ MicrocodeFmpPrivate->ProcessorCount = NumberOfProcessors;\r
+\r
+ Status = MpService->WhoAmI (MpService, &BspIndex);\r
+ ASSERT_EFI_ERROR(Status);\r
+ MicrocodeFmpPrivate->BspIndex = BspIndex;\r
+\r
+ MicrocodeFmpPrivate->ProcessorInfo = AllocateZeroPool (sizeof(PROCESSOR_INFO) * MicrocodeFmpPrivate->ProcessorCount);\r
+ if (MicrocodeFmpPrivate->ProcessorInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < NumberOfProcessors; Index++) {\r
+ MicrocodeFmpPrivate->ProcessorInfo[Index].CpuIndex = Index;\r
+ MicrocodeFmpPrivate->ProcessorInfo[Index].MicrocodeIndex = (UINTN)-1;\r
+ if (Index == BspIndex) {\r
+ CollectProcessorInfo (&MicrocodeFmpPrivate->ProcessorInfo[Index]);\r
+ } else {\r
+ Status = MpService->StartupThisAP (\r
+ MpService,\r
+ CollectProcessorInfo,\r
+ Index,\r
+ NULL,\r
+ 0,\r
+ &MicrocodeFmpPrivate->ProcessorInfo[Index],\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR(Status);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Dump private information.\r
+\r
+ @param[in] MicrocodeFmpPrivate private data structure.\r
+**/\r
+VOID\r
+DumpPrivateInfo (\r
+ IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
+ )\r
+{\r
+ UINTN Index;\r
+ PROCESSOR_INFO *ProcessorInfo;\r
+ MICROCODE_INFO *MicrocodeInfo;\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;\r
+\r
+ DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));\r
+ DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", MicrocodeFmpPrivate->ProcessorCount));\r
+ DEBUG ((DEBUG_INFO, " BspIndex - 0x%x\n", MicrocodeFmpPrivate->BspIndex));\r
+\r
+ ProcessorInfo = MicrocodeFmpPrivate->ProcessorInfo;\r
+ for (Index = 0; Index < MicrocodeFmpPrivate->ProcessorCount; Index++) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " ProcessorInfo[0x%x] - 0x%08x, 0x%02x, 0x%08x, (0x%x)\n",\r
+ ProcessorInfo[Index].CpuIndex,\r
+ ProcessorInfo[Index].ProcessorSignature,\r
+ ProcessorInfo[Index].PlatformId,\r
+ ProcessorInfo[Index].MicrocodeRevision,\r
+ ProcessorInfo[Index].MicrocodeIndex\r
+ ));\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "MicrocodeInfo:\n"));\r
+ MicrocodeInfo = MicrocodeFmpPrivate->MicrocodeInfo;\r
+ DEBUG ((DEBUG_INFO, " MicrocodeRegion - 0x%x - 0x%x\n", MicrocodeFmpPrivate->MicrocodePatchAddress, MicrocodeFmpPrivate->MicrocodePatchRegionSize));\r
+ DEBUG ((DEBUG_INFO, " MicrocodeCount - 0x%x\n", MicrocodeFmpPrivate->DescriptorCount));\r
+ for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " MicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x)\n",\r
+ Index,\r
+ MicrocodeInfo[Index].MicrocodeEntryPoint,\r
+ MicrocodeInfo[Index].TotalSize,\r
+ MicrocodeInfo[Index].InUse\r
+ ));\r
+ }\r
+\r
+ ImageDescriptor = MicrocodeFmpPrivate->ImageDescriptor;\r
+ DEBUG ((DEBUG_VERBOSE, "ImageDescriptor:\n"));\r
+ for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {\r
+ DEBUG((DEBUG_VERBOSE, " ImageDescriptor (%d)\n", Index));\r
+ DEBUG((DEBUG_VERBOSE, " ImageIndex - 0x%x\n", ImageDescriptor[Index].ImageIndex));\r
+ DEBUG((DEBUG_VERBOSE, " ImageTypeId - %g\n", &ImageDescriptor[Index].ImageTypeId));\r
+ DEBUG((DEBUG_VERBOSE, " ImageId - 0x%lx\n", ImageDescriptor[Index].ImageId));\r
+ DEBUG((DEBUG_VERBOSE, " ImageIdName - %s\n", ImageDescriptor[Index].ImageIdName));\r
+ DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", ImageDescriptor[Index].Version));\r
+ DEBUG((DEBUG_VERBOSE, " VersionName - %s\n", ImageDescriptor[Index].VersionName));\r
+ DEBUG((DEBUG_VERBOSE, " Size - 0x%x\n", ImageDescriptor[Index].Size));\r
+ DEBUG((DEBUG_VERBOSE, " AttributesSupported - 0x%lx\n", ImageDescriptor[Index].AttributesSupported));\r
+ DEBUG((DEBUG_VERBOSE, " AttributesSetting - 0x%lx\n", ImageDescriptor[Index].AttributesSetting));\r
+ DEBUG((DEBUG_VERBOSE, " Compatibilities - 0x%lx\n", ImageDescriptor[Index].Compatibilities));\r
+ DEBUG((DEBUG_VERBOSE, " LowestSupportedImageVersion - 0x%x\n", ImageDescriptor[Index].LowestSupportedImageVersion));\r
+ DEBUG((DEBUG_VERBOSE, " LastAttemptVersion - 0x%x\n", ImageDescriptor[Index].LastAttemptVersion));\r
+ DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", ImageDescriptor[Index].LastAttemptStatus));\r
+ DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", ImageDescriptor[Index].HardwareInstance));\r
+ }\r
+}\r
+\r
/**\r
Initialize MicrocodeFmpDriver private data structure.\r
\r
return EFI_NOT_FOUND;\r
}\r
\r
+ Status = InitializeProcessorInfo (MicrocodeFmpPrivate);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((DEBUG_ERROR, "InitializeProcessorInfo - %r\n", Status));\r
+ return Status;\r
+ }\r
+\r
Status = InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((DEBUG_ERROR, "InitializeMicrocodeDescriptor - %r\n", Status));\r
+ return Status;\r
+ }\r
+\r
+ DumpPrivateInfo (MicrocodeFmpPrivate);\r
\r
return Status;\r
}\r
\r
#include "MicrocodeUpdate.h"\r
\r
-\r
-/**\r
- Verify Microcode.\r
-\r
- Caution: This function may receive untrusted input.\r
-\r
- @param[in] Image The Microcode image buffer.\r
- @param[in] ImageSize The size of Microcode image buffer in bytes.\r
- @param[in] TryLoad Try to load Microcode or not.\r
- @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
- @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more\r
- details for the aborted operation. The buffer is allocated by this function\r
- with AllocatePool(), and it is the caller's responsibility to free it with a\r
- call to FreePool().\r
-\r
- @retval EFI_SUCCESS The Microcode image passes verification.\r
- @retval EFI_VOLUME_CORRUPTED The Microcode image is corrupt.\r
- @retval EFI_INCOMPATIBLE_VERSION The Microcode image version is incorrect.\r
- @retval EFI_UNSUPPORTED The Microcode ProcessorSignature or ProcessorFlags is incorrect.\r
- @retval EFI_SECURITY_VIOLATION The Microcode image fails to load.\r
-**/\r
-EFI_STATUS\r
-VerifyMicrocode (\r
- IN VOID *Image,\r
- IN UINTN ImageSize,\r
- IN BOOLEAN TryLoad,\r
- OUT UINT32 *LastAttemptStatus,\r
- OUT CHAR16 **AbortReason\r
- );\r
-\r
/**\r
Get Microcode Region.\r
\r
}\r
\r
/**\r
- If the Microcode is used by current processor.\r
+ Load Microcode on an Application Processor.\r
+ The function prototype for invoking a function on an Application Processor.\r
+\r
+ @param[in,out] Buffer The pointer to private data buffer.\r
+**/\r
+VOID\r
+EFIAPI\r
+MicrocodeLoadAp (\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ MICROCODE_LOAD_BUFFER *MicrocodeLoadBuffer;\r
+\r
+ MicrocodeLoadBuffer = Buffer;\r
+ MicrocodeLoadBuffer->Revision = LoadMicrocode (MicrocodeLoadBuffer->Address);\r
+}\r
+\r
+/**\r
+ Load new Microcode on this processor\r
\r
- @param[in] MicrocodeEntryPoint The Microcode buffer\r
+ @param[in] MicrocodeFmpPrivate The Microcode driver private data\r
+ @param[in] CpuIndex The index of the processor.\r
+ @param[in] Address The address of new Microcode.\r
+\r
+ @return Loaded Microcode signature.\r
\r
- @retval TRUE The Microcode is used by current processor.\r
- @retval FALSE The Microcode is NOT used by current processor.\r
**/\r
-BOOLEAN\r
-IsMicrocodeInUse (\r
- IN CPU_MICROCODE_HEADER *MicrocodeEntryPoint\r
+UINT32\r
+LoadMicrocodeOnThis (\r
+ IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,\r
+ IN UINTN CpuIndex,\r
+ IN UINT64 Address\r
)\r
{\r
- UINT32 AttemptStatus;\r
- UINTN TotalSize;\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ EFI_MP_SERVICES_PROTOCOL *MpService;\r
+ MICROCODE_LOAD_BUFFER MicrocodeLoadBuffer;\r
\r
- if (MicrocodeEntryPoint->HeaderVersion == 0x1 && MicrocodeEntryPoint->LoaderRevision == 0x1) {\r
- //\r
- // It is the microcode header. It is not the padding data between microcode patches\r
- // becasue the padding data should not include 0x00000001 and it should be the repeated\r
- // byte format (like 0xXYXYXYXY....).\r
- //\r
- if (MicrocodeEntryPoint->DataSize == 0) {\r
- TotalSize = 2048;\r
- } else {\r
- TotalSize = MicrocodeEntryPoint->TotalSize;\r
- }\r
- Status = VerifyMicrocode(MicrocodeEntryPoint, TotalSize, FALSE, &AttemptStatus, NULL);\r
- if (!EFI_ERROR(Status)) {\r
- return TRUE;\r
- }\r
+ if (CpuIndex == MicrocodeFmpPrivate->BspIndex) {\r
+ return LoadMicrocode (Address);\r
+ } else {\r
+ MpService = MicrocodeFmpPrivate->MpService;\r
+ MicrocodeLoadBuffer.Address = Address;\r
+ MicrocodeLoadBuffer.Revision = 0;\r
+ Status = MpService->StartupThisAP (\r
+ MpService,\r
+ MicrocodeLoadAp,\r
+ CpuIndex,\r
+ NULL,\r
+ 0,\r
+ &MicrocodeLoadBuffer,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR(Status);\r
+ return MicrocodeLoadBuffer.Revision;\r
}\r
- return FALSE;\r
+}\r
+\r
+/**\r
+ Collect processor information.\r
+ The function prototype for invoking a function on an Application Processor.\r
+\r
+ @param[in,out] Buffer The pointer to private data buffer.\r
+**/\r
+VOID\r
+EFIAPI\r
+CollectProcessorInfo (\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ PROCESSOR_INFO *ProcessorInfo;\r
+\r
+ ProcessorInfo = Buffer;\r
+ ProcessorInfo->ProcessorSignature = GetCurrentProcessorSignature();\r
+ ProcessorInfo->PlatformId = GetCurrentPlatformId();\r
+ ProcessorInfo->MicrocodeRevision = GetCurrentMicrocodeSignature();\r
}\r
\r
/**\r
Get current Microcode information.\r
\r
- NOTE: The DescriptorCount/ImageDescriptor/MicrocodeInfo in MicrocodeFmpPrivate\r
- are not avaiable in this function.\r
+ The ProcessorInformation (BspIndex/ProcessorCount/ProcessorInfo)\r
+ in MicrocodeFmpPrivate must be initialized.\r
+\r
+ The MicrocodeInformation (DescriptorCount/ImageDescriptor/MicrocodeInfo)\r
+ in MicrocodeFmpPrivate may not be avaiable in this function.\r
\r
@param[in] MicrocodeFmpPrivate The Microcode driver private data\r
@param[in] DescriptorCount The count of Microcode ImageDescriptor allocated.\r
UINTN Count;\r
UINT64 ImageAttributes;\r
BOOLEAN IsInUse;\r
+ EFI_STATUS Status;\r
+ UINT32 AttemptStatus;\r
+ UINTN TargetCpuIndex;\r
\r
MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;\r
MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;\r
TotalSize = MicrocodeEntryPoint->TotalSize;\r
}\r
\r
- IsInUse = IsMicrocodeInUse (MicrocodeEntryPoint);\r
+ TargetCpuIndex = (UINTN)-1;\r
+ Status = VerifyMicrocode(MicrocodeFmpPrivate, MicrocodeEntryPoint, TotalSize, FALSE, &AttemptStatus, NULL, &TargetCpuIndex);\r
+ if (!EFI_ERROR(Status)) {\r
+ IsInUse = TRUE;\r
+ ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount);\r
+ MicrocodeFmpPrivate->ProcessorInfo[TargetCpuIndex].MicrocodeIndex = Count;\r
+ } else {\r
+ IsInUse = FALSE;\r
+ }\r
\r
if (ImageDescriptor != NULL && DescriptorCount > Count) {\r
ImageDescriptor[Count].ImageIndex = (UINT8)(Count + 1);\r
return Count;\r
}\r
\r
+/**\r
+ Return matched processor information.\r
+\r
+ @param[in] MicrocodeFmpPrivate The Microcode driver private data\r
+ @param[in] ProcessorSignature The processor signature to be matched\r
+ @param[in] ProcessorFlags The processor flags to be matched\r
+ @param[in, out] TargetCpuIndex On input, the index of target CPU which tries to match the Microcode. (UINTN)-1 means to try all.\r
+ On output, the index of target CPU which matches the Microcode.\r
+\r
+ @return matched processor information.\r
+**/\r
+PROCESSOR_INFO *\r
+GetMatchedProcessor (\r
+ IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,\r
+ IN UINT32 ProcessorSignature,\r
+ IN UINT32 ProcessorFlags,\r
+ IN OUT UINTN *TargetCpuIndex\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ if (*TargetCpuIndex != (UINTN)-1) {\r
+ Index = *TargetCpuIndex;\r
+ if ((ProcessorSignature == MicrocodeFmpPrivate->ProcessorInfo[Index].ProcessorSignature) &&\r
+ ((ProcessorFlags & (1 << MicrocodeFmpPrivate->ProcessorInfo[Index].PlatformId)) != 0)) {\r
+ return &MicrocodeFmpPrivate->ProcessorInfo[Index];\r
+ } else {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ for (Index = 0; Index < MicrocodeFmpPrivate->ProcessorCount; Index++) {\r
+ if ((ProcessorSignature == MicrocodeFmpPrivate->ProcessorInfo[Index].ProcessorSignature) &&\r
+ ((ProcessorFlags & (1 << MicrocodeFmpPrivate->ProcessorInfo[Index].PlatformId)) != 0)) {\r
+ *TargetCpuIndex = Index;\r
+ return &MicrocodeFmpPrivate->ProcessorInfo[Index];\r
+ }\r
+ }\r
+ return NULL;\r
+}\r
+\r
/**\r
Verify Microcode.\r
\r
Caution: This function may receive untrusted input.\r
\r
- @param[in] Image The Microcode image buffer.\r
- @param[in] ImageSize The size of Microcode image buffer in bytes.\r
- @param[in] TryLoad Try to load Microcode or not.\r
- @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
- @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more\r
- details for the aborted operation. The buffer is allocated by this function\r
- with AllocatePool(), and it is the caller's responsibility to free it with a\r
- call to FreePool().\r
+ @param[in] MicrocodeFmpPrivate The Microcode driver private data\r
+ @param[in] Image The Microcode image buffer.\r
+ @param[in] ImageSize The size of Microcode image buffer in bytes.\r
+ @param[in] TryLoad Try to load Microcode or not.\r
+ @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+ @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more\r
+ details for the aborted operation. The buffer is allocated by this function\r
+ with AllocatePool(), and it is the caller's responsibility to free it with a\r
+ call to FreePool().\r
+ @param[in, out] TargetCpuIndex On input, the index of target CPU which tries to match the Microcode. (UINTN)-1 means to try all.\r
+ On output, the index of target CPU which matches the Microcode.\r
\r
@retval EFI_SUCCESS The Microcode image passes verification.\r
@retval EFI_VOLUME_CORRUPTED The Microcode image is corrupt.\r
**/\r
EFI_STATUS\r
VerifyMicrocode (\r
- IN VOID *Image,\r
- IN UINTN ImageSize,\r
- IN BOOLEAN TryLoad,\r
- OUT UINT32 *LastAttemptStatus,\r
- OUT CHAR16 **AbortReason\r
+ IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,\r
+ IN VOID *Image,\r
+ IN UINTN ImageSize,\r
+ IN BOOLEAN TryLoad,\r
+ OUT UINT32 *LastAttemptStatus,\r
+ OUT CHAR16 **AbortReason, OPTIONAL\r
+ IN OUT UINTN *TargetCpuIndex\r
)\r
{\r
UINTN Index;\r
UINTN TotalSize;\r
UINTN DataSize;\r
UINT32 CurrentRevision;\r
- UINT32 CurrentProcessorSignature;\r
- UINT8 CurrentPlatformId;\r
+ PROCESSOR_INFO *ProcessorInfo;\r
UINT32 CheckSum32;\r
UINTN ExtendedTableLength;\r
UINT32 ExtendedTableCount;\r
//\r
// Check ProcessorSignature/ProcessorFlags\r
//\r
- CorrectMicrocode = FALSE;\r
- CurrentProcessorSignature = GetCurrentProcessorSignature();\r
- CurrentPlatformId = GetCurrentPlatformId();\r
- if ((MicrocodeEntryPoint->ProcessorSignature.Uint32 != CurrentProcessorSignature) ||\r
- ((MicrocodeEntryPoint->ProcessorFlags & (1 << CurrentPlatformId)) == 0)) {\r
+\r
+ ProcessorInfo = GetMatchedProcessor (MicrocodeFmpPrivate, MicrocodeEntryPoint->ProcessorSignature.Uint32, MicrocodeEntryPoint->ProcessorFlags, TargetCpuIndex);\r
+ if (ProcessorInfo == NULL) {\r
+ CorrectMicrocode = FALSE;\r
ExtendedTableLength = TotalSize - (DataSize + sizeof(CPU_MICROCODE_HEADER));\r
if (ExtendedTableLength != 0) {\r
//\r
//\r
// Verify Header\r
//\r
- if ((ExtendedTable->ProcessorSignature.Uint32 == CurrentProcessorSignature) &&\r
- (ExtendedTable->ProcessorFlag & (1 << CurrentPlatformId))) {\r
+ ProcessorInfo = GetMatchedProcessor (MicrocodeFmpPrivate, ExtendedTable->ProcessorSignature.Uint32, ExtendedTable->ProcessorFlag, TargetCpuIndex);\r
+ if (ProcessorInfo != NULL) {\r
//\r
// Find one\r
//\r
}\r
*LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;\r
if (AbortReason != NULL) {\r
- if (MicrocodeEntryPoint->ProcessorSignature.Uint32 != CurrentProcessorSignature) {\r
- *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessSignature"), L"UnsupportedProcessSignature");\r
- } else {\r
- *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessorFlags"), L"UnsupportedProcessorFlags");\r
- }\r
+ *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessSignature/ProcessorFlags"), L"UnsupportedProcessSignature/ProcessorFlags");\r
}\r
return EFI_UNSUPPORTED;\r
}\r
//\r
// Check UpdateRevision\r
//\r
- CurrentRevision = GetCurrentMicrocodeSignature();\r
- if (MicrocodeEntryPoint->UpdateRevision < CurrentRevision) {\r
+ CurrentRevision = ProcessorInfo->MicrocodeRevision;\r
+ if ((MicrocodeEntryPoint->UpdateRevision < CurrentRevision) ||\r
+ (TryLoad && (MicrocodeEntryPoint->UpdateRevision == CurrentRevision))) {\r
if (TryLoad) {\r
DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on UpdateRevision\n"));\r
}\r
// try load MCU\r
//\r
if (TryLoad) {\r
- CurrentRevision = LoadMicrocode((UINTN)MicrocodeEntryPoint + sizeof(CPU_MICROCODE_HEADER));\r
+ CurrentRevision = LoadMicrocodeOnThis(MicrocodeFmpPrivate, ProcessorInfo->CpuIndex, (UINTN)MicrocodeEntryPoint + sizeof(CPU_MICROCODE_HEADER));\r
if (MicrocodeEntryPoint->UpdateRevision != CurrentRevision) {\r
DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on LoadMicrocode\n"));\r
*LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;\r
return EFI_SUCCESS;\r
}\r
\r
-/**\r
- Get current Microcode in used.\r
-\r
- @param[in] MicrocodeFmpPrivate The Microcode driver private data\r
-\r
- @return current Microcode in used.\r
-**/\r
-VOID *\r
-GetCurrentMicrocodeInUse (\r
- IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
- )\r
-{\r
- UINTN Index;\r
-\r
- for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {\r
- if (!MicrocodeFmpPrivate->MicrocodeInfo[Index].InUse) {\r
- continue;\r
- }\r
- if (IsMicrocodeInUse (MicrocodeFmpPrivate->MicrocodeInfo[Index].MicrocodeEntryPoint)) {\r
- return MicrocodeFmpPrivate->MicrocodeInfo[Index].MicrocodeEntryPoint;\r
- }\r
- }\r
- return NULL;\r
-}\r
-\r
/**\r
Get next Microcode entrypoint.\r
\r
Update Microcode flash region.\r
\r
@param[in] MicrocodeFmpPrivate The Microcode driver private data\r
- @param[in] CurrentMicrocodeEntryPoint Current Microcode entrypoint\r
+ @param[in] TargetMicrocodeEntryPoint Target Microcode entrypoint to be updated\r
@param[in] Image The Microcode image buffer.\r
@param[in] ImageSize The size of Microcode image buffer in bytes.\r
@param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
EFI_STATUS\r
UpdateMicrocodeFlashRegion (\r
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,\r
- IN CPU_MICROCODE_HEADER *CurrentMicrocodeEntryPoint,\r
+ IN CPU_MICROCODE_HEADER *TargetMicrocodeEntryPoint,\r
IN VOID *Image,\r
IN UINTN ImageSize,\r
OUT UINT32 *LastAttemptStatus\r
{\r
VOID *MicrocodePatchAddress;\r
UINTN MicrocodePatchRegionSize;\r
- UINTN CurrentTotalSize;\r
+ UINTN TargetTotalSize;\r
UINTN UsedRegionSize;\r
EFI_STATUS Status;\r
VOID *MicrocodePatchScratchBuffer;\r
ScratchBufferSize = 0;\r
\r
//\r
- // Current data collection\r
+ // Target data collection\r
//\r
- CurrentTotalSize = 0;\r
+ TargetTotalSize = 0;\r
AvailableSize = 0;\r
NextMicrocodeEntryPoint = NULL;\r
- if (CurrentMicrocodeEntryPoint != NULL) {\r
- if (CurrentMicrocodeEntryPoint->DataSize == 0) {\r
- CurrentTotalSize = 2048;\r
+ if (TargetMicrocodeEntryPoint != NULL) {\r
+ if (TargetMicrocodeEntryPoint->DataSize == 0) {\r
+ TargetTotalSize = 2048;\r
} else {\r
- CurrentTotalSize = CurrentMicrocodeEntryPoint->TotalSize;\r
+ TargetTotalSize = TargetMicrocodeEntryPoint->TotalSize;\r
}\r
- DEBUG((DEBUG_INFO, " CurrentTotalSize - 0x%x\n", CurrentTotalSize));\r
- NextMicrocodeEntryPoint = GetNextMicrocode(MicrocodeFmpPrivate, CurrentMicrocodeEntryPoint);\r
+ DEBUG((DEBUG_INFO, " TargetTotalSize - 0x%x\n", TargetTotalSize));\r
+ NextMicrocodeEntryPoint = GetNextMicrocode(MicrocodeFmpPrivate, TargetMicrocodeEntryPoint);\r
DEBUG((DEBUG_INFO, " NextMicrocodeEntryPoint - 0x%x\n", NextMicrocodeEntryPoint));\r
if (NextMicrocodeEntryPoint != NULL) {\r
- ASSERT ((UINTN)NextMicrocodeEntryPoint >= ((UINTN)CurrentMicrocodeEntryPoint + CurrentTotalSize));\r
- AvailableSize = (UINTN)NextMicrocodeEntryPoint - (UINTN)CurrentMicrocodeEntryPoint;\r
+ ASSERT ((UINTN)NextMicrocodeEntryPoint >= ((UINTN)TargetMicrocodeEntryPoint + TargetTotalSize));\r
+ AvailableSize = (UINTN)NextMicrocodeEntryPoint - (UINTN)TargetMicrocodeEntryPoint;\r
} else {\r
- AvailableSize = (UINTN)MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN)CurrentMicrocodeEntryPoint;\r
+ AvailableSize = (UINTN)MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN)TargetMicrocodeEntryPoint;\r
}\r
DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize));\r
}\r
- ASSERT (AvailableSize >= CurrentTotalSize);\r
+ ASSERT (AvailableSize >= TargetTotalSize);\r
UsedRegionSize = GetCurrentMicrocodeUsedRegionSize(MicrocodeFmpPrivate);\r
DEBUG((DEBUG_INFO, " UsedRegionSize - 0x%x\n", UsedRegionSize));\r
- ASSERT (UsedRegionSize >= CurrentTotalSize);\r
- if (CurrentMicrocodeEntryPoint != NULL) {\r
- ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >= ((UINTN)CurrentMicrocodeEntryPoint + CurrentTotalSize));\r
+ ASSERT (UsedRegionSize >= TargetTotalSize);\r
+ if (TargetMicrocodeEntryPoint != NULL) {\r
+ ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >= ((UINTN)TargetMicrocodeEntryPoint + TargetTotalSize));\r
}\r
//\r
// Total Size means the Microcode data size.\r
- // Available Size means the Microcode data size plus the pad till next (1) Microcode or (2) the end.\r
+ // Available Size means the Microcode data size plus the pad till (1) next Microcode or (2) the end.\r
//\r
// (1)\r
// +------+-----------+-----+------+===================+\r
// 1.1. Copy new image\r
CopyMem (ScratchBufferPtr, Image, ImageSize);\r
ScratchBufferSize += ImageSize;\r
- ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;\r
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
// 1.2. Pad 0xFF\r
RestSize = AvailableSize - ImageSize;\r
if (RestSize > 0) {\r
SetMem (ScratchBufferPtr, RestSize, 0xFF);\r
ScratchBufferSize += RestSize;\r
- ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;\r
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
}\r
- Status = UpdateMicrocode((UINTN)CurrentMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);\r
+ Status = UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);\r
return Status;\r
}\r
\r
//\r
// 2. If there is enough space to remove old one and add new one, reorg and replace old microcode.\r
//\r
- if (MicrocodePatchRegionSize - (UsedRegionSize - CurrentTotalSize) >= ImageSize) {\r
- if (CurrentMicrocodeEntryPoint == NULL) {\r
+ if (MicrocodePatchRegionSize - (UsedRegionSize - TargetTotalSize) >= ImageSize) {\r
+ if (TargetMicrocodeEntryPoint == NULL) {\r
DEBUG((DEBUG_INFO, "Append new microcode\n"));\r
//\r
// +------+------------+------+===================+\r
// +------+---------------+------+================+\r
//\r
// 2.1. Copy new image\r
- CopyMem (MicrocodePatchScratchBuffer, Image, ImageSize);\r
+ CopyMem (ScratchBufferPtr, Image, ImageSize);\r
ScratchBufferSize += ImageSize;\r
- ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;\r
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
// 2.2. Copy rest images after the old image.\r
if (NextMicrocodeEntryPoint != 0) {\r
RestSize = (UINTN)MicrocodePatchAddress + UsedRegionSize - ((UINTN)NextMicrocodeEntryPoint);\r
- CopyMem (ScratchBufferPtr, (UINT8 *)CurrentMicrocodeEntryPoint + CurrentTotalSize, RestSize);\r
+ CopyMem (ScratchBufferPtr, (UINT8 *)TargetMicrocodeEntryPoint + TargetTotalSize, RestSize);\r
ScratchBufferSize += RestSize;\r
- ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;\r
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
}\r
- Status = UpdateMicrocode((UINTN)CurrentMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);\r
+ Status = UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);\r
}\r
return Status;\r
}\r
MicrocodeInfo = MicrocodeFmpPrivate->MicrocodeInfo;\r
\r
// 3.1. Copy new image\r
- CopyMem (MicrocodePatchScratchBuffer, Image, ImageSize);\r
+ CopyMem (ScratchBufferPtr, Image, ImageSize);\r
ScratchBufferSize += ImageSize;\r
- ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;\r
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
// 3.2. Copy some others to rest buffer\r
for (Index = 0; Index < MicrocodeCount; Index++) {\r
if (!MicrocodeInfo[Index].InUse) {\r
continue;\r
}\r
- if (MicrocodeInfo[Index].MicrocodeEntryPoint == CurrentMicrocodeEntryPoint) {\r
+ if (MicrocodeInfo[Index].MicrocodeEntryPoint == TargetMicrocodeEntryPoint) {\r
continue;\r
}\r
if (MicrocodeInfo[Index].TotalSize <= MicrocodePatchRegionSize - ScratchBufferSize) {\r
CopyMem (ScratchBufferPtr, MicrocodeInfo[Index].MicrocodeEntryPoint, MicrocodeInfo[Index].TotalSize);\r
ScratchBufferSize += MicrocodeInfo[Index].TotalSize;\r
- ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;\r
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
}\r
}\r
// 3.3. Pad 0xFF\r
if (RestSize > 0) {\r
SetMem (ScratchBufferPtr, RestSize, 0xFF);\r
ScratchBufferSize += RestSize;\r
- ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;\r
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
}\r
Status = UpdateMicrocode((UINTN)MicrocodePatchAddress, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);\r
return Status;\r
{\r
EFI_STATUS Status;\r
VOID *AlignedImage;\r
- CPU_MICROCODE_HEADER *CurrentMicrocodeEntryPoint;\r
-\r
- //\r
- // We must get Current MicrocodeEntrypoint *before* VerifyMicrocode,\r
- // because the MicrocodeSignature might be updated in VerifyMicrocode.\r
- //\r
- CurrentMicrocodeEntryPoint = GetCurrentMicrocodeInUse(MicrocodeFmpPrivate);\r
- DEBUG((DEBUG_INFO, " CurrentMicrocodeEntryPoint - 0x%x\n", CurrentMicrocodeEntryPoint));\r
+ CPU_MICROCODE_HEADER *TargetMicrocodeEntryPoint;\r
+ UINTN TargetCpuIndex;\r
+ UINTN TargetMicrcodeIndex;\r
\r
//\r
// MCU must be 16 bytes aligned\r
}\r
\r
*LastAttemptVersion = ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision;\r
- Status = VerifyMicrocode(AlignedImage, ImageSize, TRUE, LastAttemptStatus, AbortReason);\r
+ TargetCpuIndex = (UINTN)-1;\r
+ Status = VerifyMicrocode(MicrocodeFmpPrivate, AlignedImage, ImageSize, TRUE, LastAttemptStatus, AbortReason, &TargetCpuIndex);\r
if (EFI_ERROR(Status)) {\r
DEBUG((DEBUG_ERROR, "Fail to verify Microcode Region\n"));\r
FreePool(AlignedImage);\r
}\r
DEBUG((DEBUG_INFO, "Pass VerifyMicrocode\n"));\r
\r
+ DEBUG((DEBUG_INFO, " TargetCpuIndex - 0x%x\n", TargetCpuIndex));\r
+ ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount);\r
+ TargetMicrcodeIndex = MicrocodeFmpPrivate->ProcessorInfo[TargetCpuIndex].MicrocodeIndex;\r
+ DEBUG((DEBUG_INFO, " TargetMicrcodeIndex - 0x%x\n", TargetMicrcodeIndex));\r
+ if (TargetMicrcodeIndex != (UINTN)-1) {\r
+ ASSERT (TargetMicrcodeIndex < MicrocodeFmpPrivate->DescriptorCount);\r
+ TargetMicrocodeEntryPoint = MicrocodeFmpPrivate->MicrocodeInfo[TargetMicrcodeIndex].MicrocodeEntryPoint;\r
+ } else {\r
+ TargetMicrocodeEntryPoint = NULL;\r
+ }\r
+ DEBUG((DEBUG_INFO, " TargetMicrocodeEntryPoint - 0x%x\n", TargetMicrocodeEntryPoint));\r
+\r
Status = UpdateMicrocodeFlashRegion(\r
MicrocodeFmpPrivate,\r
- CurrentMicrocodeEntryPoint,\r
+ TargetMicrocodeEntryPoint,\r
AlignedImage,\r
ImageSize,\r
LastAttemptStatus\r