]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/MicrocodeUpdate: Add MP support.
authorJiewen Yao <jiewen.yao@intel.com>
Tue, 27 Dec 2016 06:21:16 +0000 (14:21 +0800)
committerJiewen Yao <jiewen.yao@intel.com>
Wed, 28 Dec 2016 07:09:02 +0000 (15:09 +0800)
Support the case that BSP and AP are using different Microcode.
The previous logic validates new MCU on BSP only.
The enhanced logic will validate MCU on every BSP and AP.
As long as one processor loads the MCU successfully, it will be updated.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
UefiCpuPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
UefiCpuPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c
UefiCpuPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
UefiCpuPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf

index 97f2f353e8a7903f5928d904929b8157efe26b70..ebde93a91eb3034b2647e6e5a2d479649f701e9d 100644 (file)
@@ -284,6 +284,7 @@ FmpSetImage (
 \r
   if (!EFI_ERROR(Status)) {\r
     InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);\r
+    DumpPrivateInfo (MicrocodeFmpPrivate);\r
   }\r
 \r
   return Status;\r
@@ -413,6 +414,47 @@ FmpSetPackageInfo (
   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
@@ -461,9 +503,140 @@ InitializeMicrocodeDescriptor (
   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
@@ -507,7 +680,19 @@ InitializePrivateData (
     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
index 46739ba57a2ca5de333cb3bb6e462c2e47703c9a..4e8f1d5fd8a881d71928d75c78c5b547738f0b99 100644 (file)
 \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
@@ -144,46 +114,92 @@ LoadMicrocode (
 }\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
@@ -208,6 +224,9 @@ GetMicrocodeInfo (
   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
@@ -231,7 +250,15 @@ GetMicrocodeInfo (
         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
@@ -282,19 +309,63 @@ GetMicrocodeInfo (
   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
@@ -304,11 +375,13 @@ GetMicrocodeInfo (
 **/\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
@@ -316,8 +389,7 @@ VerifyMicrocode (
   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
@@ -409,11 +481,10 @@ VerifyMicrocode (
   //\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
@@ -438,8 +509,8 @@ VerifyMicrocode (
                 //\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
@@ -459,11 +530,7 @@ VerifyMicrocode (
       }\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
@@ -472,8 +539,9 @@ VerifyMicrocode (
   //\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
@@ -488,7 +556,7 @@ VerifyMicrocode (
   // 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
@@ -502,31 +570,6 @@ VerifyMicrocode (
   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
@@ -622,7 +665,7 @@ UpdateMicrocode (
   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
@@ -633,7 +676,7 @@ UpdateMicrocode (
 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
@@ -641,7 +684,7 @@ UpdateMicrocodeFlashRegion (
 {\r
   VOID                                    *MicrocodePatchAddress;\r
   UINTN                                   MicrocodePatchRegionSize;\r
-  UINTN                                   CurrentTotalSize;\r
+  UINTN                                   TargetTotalSize;\r
   UINTN                                   UsedRegionSize;\r
   EFI_STATUS                              Status;\r
   VOID                                    *MicrocodePatchScratchBuffer;\r
@@ -669,38 +712,38 @@ UpdateMicrocodeFlashRegion (
   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
@@ -740,23 +783,23 @@ UpdateMicrocodeFlashRegion (
     // 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
@@ -780,17 +823,17 @@ UpdateMicrocodeFlashRegion (
       // +------+---------------+------+================+\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
@@ -815,21 +858,21 @@ UpdateMicrocodeFlashRegion (
     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
@@ -837,7 +880,7 @@ UpdateMicrocodeFlashRegion (
     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
@@ -886,14 +929,9 @@ MicrocodeWrite (
 {\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
@@ -906,7 +944,8 @@ MicrocodeWrite (
   }\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
@@ -914,9 +953,21 @@ MicrocodeWrite (
   }\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
index b4d1bac17dd2ebb565ce50a7bf1c7fe2bea1eaa5..9dc306324e627fe590ad3fb95f620ff73baaa941 100644 (file)
@@ -21,6 +21,7 @@
 #include <Guid/MicrocodeFmp.h>\r
 \r
 #include <Protocol/FirmwareManagement.h>\r
+#include <Protocol/MpService.h>\r
 \r
 #include <Library/BaseLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
@@ -56,6 +57,19 @@ typedef struct {
   BOOLEAN                InUse;\r
 } MICROCODE_INFO;\r
 \r
+typedef struct {\r
+  UINTN                  CpuIndex;\r
+  UINT32                 ProcessorSignature;\r
+  UINT8                  PlatformId;\r
+  UINT32                 MicrocodeRevision;\r
+  UINTN                  MicrocodeIndex;\r
+} PROCESSOR_INFO;\r
+\r
+typedef struct {\r
+  UINT64                 Address;\r
+  UINT32                 Revision;\r
+} MICROCODE_LOAD_BUFFER;\r
+\r
 struct _MICROCODE_FMP_PRIVATE_DATA {\r
   UINT32                               Signature;\r
   EFI_FIRMWARE_MANAGEMENT_PROTOCOL     Fmp;\r
@@ -68,6 +82,10 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
   UINT32                               PackageVersion;\r
   CHAR16                               *PackageVersionName;\r
   MICROCODE_FMP_LAST_ATTEMPT_VARIABLE  LastAttempt;\r
+  EFI_MP_SERVICES_PROTOCOL             *MpService;\r
+  UINTN                                BspIndex;\r
+  UINTN                                ProcessorCount;\r
+  PROCESSOR_INFO                       *ProcessorInfo;\r
 };\r
 \r
 typedef struct _MICROCODE_FMP_PRIVATE_DATA  MICROCODE_FMP_PRIVATE_DATA;\r
@@ -107,11 +125,26 @@ GetMicrocodeRegion (
   OUT UINTN    *MicrocodePatchRegionSize\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
 /**\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
@@ -128,6 +161,40 @@ GetMicrocodeInfo (
   OUT MICROCODE_INFO                 *MicrocodeInfo    OPTIONAL\r
   );\r
 \r
+/**\r
+  Verify Microcode.\r
+\r
+  Caution: This function may receive untrusted input.\r
+\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
+  @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  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  OPTIONAL\r
+  );\r
+\r
 /**\r
   Write Microcode.\r
 \r
@@ -157,6 +224,16 @@ MicrocodeWrite (
   OUT CHAR16                       **AbortReason\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
 /**\r
   Returns information about the current firmware image(s) of the device.\r
 \r
index 7aae348180660d13a8fefbd21f4d554474acf675..55797cf132b1dc26a2331daf479d4c992814e5ba 100644 (file)
 \r
 [Protocols]\r
   gEfiFirmwareManagementProtocolGuid            ## PRODUCES\r
+  gEfiMpServiceProtocolGuid                     ## CONSUMES\r
 \r
 [Pcd]\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress            ## CONSUMES\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize         ## CONSUMES\r
 \r
 [Depex]\r
-  gEfiVariableArchProtocolGuid\r
+  gEfiVariableArchProtocolGuid AND\r
+  gEfiMpServiceProtocolGuid\r
 \r
 [UserExtensions.TianoCore."ExtraFiles"]\r
   MicrocodeUpdateDxeExtra.uni\r