]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/MpInitLib: Consume MicrocodeLib to remove duplicated code
authorRay Ni <ray.ni@intel.com>
Thu, 1 Apr 2021 16:32:44 +0000 (00:32 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 9 Apr 2021 01:43:18 +0000 (01:43 +0000)
Signed-off-by: Ray Ni <ray.ni@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
UefiCpuPkg/Library/MpInitLib/Microcode.c
UefiCpuPkg/Library/MpInitLib/MpLib.h
UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf

index 860a9750e205f5cf609c9df6a7fb220dadd18429..d34419c2a524a9515188cbe243e6f4e349b2ae2a 100644 (file)
@@ -52,6 +52,7 @@
   SynchronizationLib\r
   PcdLib\r
   VmgExitLib\r
+  MicrocodeLib\r
 \r
 [Protocols]\r
   gEfiTimerArchProtocolGuid                     ## SOMETIMES_CONSUMES\r
index 297c2abcd13aacc91ac5d872c738749d622069be..105a9f84bf95bd0f7fc3f71747386a98ba0df547 100644 (file)
@@ -1,70 +1,16 @@
 /** @file\r
   Implementation of loading microcode on processors.\r
 \r
-  Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>\r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "MpLib.h"\r
 \r
-/**\r
-  Get microcode update signature of currently loaded microcode update.\r
-\r
-  @return  Microcode signature.\r
-**/\r
-UINT32\r
-GetCurrentMicrocodeSignature (\r
-  VOID\r
-  )\r
-{\r
-  MSR_IA32_BIOS_SIGN_ID_REGISTER   BiosSignIdMsr;\r
-\r
-  AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);\r
-  AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);\r
-  BiosSignIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID);\r
-  return BiosSignIdMsr.Bits.MicrocodeUpdateSignature;\r
-}\r
-\r
 /**\r
   Detect whether specified processor can find matching microcode patch and load it.\r
 \r
-  Microcode Payload as the following format:\r
-  +----------------------------------------+------------------+\r
-  |          CPU_MICROCODE_HEADER          |                  |\r
-  +----------------------------------------+  CheckSum Part1  |\r
-  |            Microcode Binary            |                  |\r
-  +----------------------------------------+------------------+\r
-  |  CPU_MICROCODE_EXTENDED_TABLE_HEADER   |                  |\r
-  +----------------------------------------+  CheckSum Part2  |\r
-  |      CPU_MICROCODE_EXTENDED_TABLE      |                  |\r
-  |                   ...                  |                  |\r
-  +----------------------------------------+------------------+\r
-\r
-  There may by multiple CPU_MICROCODE_EXTENDED_TABLE in this format.\r
-  The count of CPU_MICROCODE_EXTENDED_TABLE is indicated by ExtendedSignatureCount\r
-  of CPU_MICROCODE_EXTENDED_TABLE_HEADER structure.\r
-\r
-  When we are trying to verify the CheckSum32 with extended table.\r
-  We should use the fields of exnteded table to replace the corresponding\r
-  fields in CPU_MICROCODE_HEADER structure, and recalculate the\r
-  CheckSum32 with CPU_MICROCODE_HEADER + Microcode Binary. We named\r
-  it as CheckSum Part3.\r
-\r
-  The CheckSum Part2 is used to verify the CPU_MICROCODE_EXTENDED_TABLE_HEADER\r
-  and CPU_MICROCODE_EXTENDED_TABLE parts. We should make sure CheckSum Part2\r
-  is correct before we are going to verify each CPU_MICROCODE_EXTENDED_TABLE.\r
-\r
-  Only ProcessorSignature, ProcessorFlag and CheckSum are different between\r
-  CheckSum Part1 and CheckSum Part3. To avoid multiple computing CheckSum Part3.\r
-  Save an in-complete CheckSum32 from CheckSum Part1 for common parts.\r
-  When we are going to calculate CheckSum32, just should use the corresponding part\r
-  of the ProcessorSignature, ProcessorFlag and CheckSum with in-complete CheckSum32.\r
-\r
-  Notes: CheckSum32 is not a strong verification.\r
-         It does not guarantee that the data has not been modified.\r
-         CPU has its own mechanism to verify Microcode Binary part.\r
-\r
   @param[in]  CpuMpData        The pointer to CPU MP Data structure.\r
   @param[in]  ProcessorNumber  The handle number of the processor. The range is\r
                                from 0 to the total number of logical processors\r
@@ -76,26 +22,13 @@ MicrocodeDetect (
   IN UINTN                   ProcessorNumber\r
   )\r
 {\r
-  UINT32                                  ExtendedTableLength;\r
-  UINT32                                  ExtendedTableCount;\r
-  CPU_MICROCODE_EXTENDED_TABLE            *ExtendedTable;\r
-  CPU_MICROCODE_EXTENDED_TABLE_HEADER     *ExtendedTableHeader;\r
-  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;\r
+  CPU_MICROCODE_HEADER                    *Microcode;\r
   UINTN                                   MicrocodeEnd;\r
-  UINTN                                   Index;\r
-  UINT8                                   PlatformId;\r
-  CPUID_VERSION_INFO_EAX                  Eax;\r
-  CPU_AP_DATA                             *CpuData;\r
-  UINT32                                  CurrentRevision;\r
+  CPU_AP_DATA                             *BspData;\r
   UINT32                                  LatestRevision;\r
-  UINTN                                   TotalSize;\r
-  UINT32                                  CheckSum32;\r
-  UINT32                                  InCompleteCheckSum32;\r
-  BOOLEAN                                 CorrectMicrocode;\r
-  VOID                                    *MicrocodeData;\r
-  MSR_IA32_PLATFORM_ID_REGISTER           PlatformIdMsr;\r
+  CPU_MICROCODE_HEADER                    *LatestMicrocode;\r
   UINT32                                  ThreadId;\r
-  BOOLEAN                                 IsBspCallIn;\r
+  EDKII_PEI_MICROCODE_CPU_ID              MicrocodeCpuId;\r
 \r
   if (CpuMpData->MicrocodePatchRegionSize == 0) {\r
     //\r
@@ -104,9 +37,6 @@ MicrocodeDetect (
     return;\r
   }\r
 \r
-  CurrentRevision = GetCurrentMicrocodeSignature ();\r
-  IsBspCallIn     = (ProcessorNumber == (UINTN)CpuMpData->BspNumber) ? TRUE : FALSE;\r
-\r
   GetProcessorLocationByApicId (GetInitialApicId (), NULL, NULL, &ThreadId);\r
   if (ThreadId != 0) {\r
     //\r
@@ -115,156 +45,35 @@ MicrocodeDetect (
     return;\r
   }\r
 \r
-  ExtendedTableLength = 0;\r
-  //\r
-  // Here data of CPUID leafs have not been collected into context buffer, so\r
-  // GetProcessorCpuid() cannot be used here to retrieve CPUID data.\r
-  //\r
-  AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);\r
+  GetProcessorMicrocodeCpuId (&MicrocodeCpuId);\r
 \r
-  //\r
-  // The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID\r
-  //\r
-  PlatformIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);\r
-  PlatformId = (UINT8) PlatformIdMsr.Bits.PlatformId;\r
-\r
-\r
-  //\r
-  // Check whether AP has same processor with BSP.\r
-  // If yes, direct use microcode info saved by BSP.\r
-  //\r
-  if (!IsBspCallIn) {\r
+  if (ProcessorNumber != (UINTN) CpuMpData->BspNumber) {\r
     //\r
-    // Get the CPU data for BSP\r
+    // Direct use microcode of BSP if AP is the same as BSP.\r
+    // Assume BSP calls this routine() before AP.\r
     //\r
-    CpuData = &(CpuMpData->CpuData[CpuMpData->BspNumber]);\r
-    if ((CpuData->ProcessorSignature == Eax.Uint32) &&\r
-        (CpuData->PlatformId == PlatformId) &&\r
-        (CpuData->MicrocodeEntryAddr != 0)) {\r
-      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(UINTN) CpuData->MicrocodeEntryAddr;\r
-      MicrocodeData       = (VOID *) (MicrocodeEntryPoint + 1);\r
-      LatestRevision      = MicrocodeEntryPoint->UpdateRevision;\r
-      goto Done;\r
+    BspData = &(CpuMpData->CpuData[CpuMpData->BspNumber]);\r
+    if ((BspData->ProcessorSignature == MicrocodeCpuId.ProcessorSignature) &&\r
+        (BspData->PlatformId == MicrocodeCpuId.PlatformId) &&\r
+        (BspData->MicrocodeEntryAddr != 0)) {\r
+      LatestMicrocode = (CPU_MICROCODE_HEADER *)(UINTN) BspData->MicrocodeEntryAddr;\r
+      LatestRevision  = LatestMicrocode->UpdateRevision;\r
+      goto LoadMicrocode;\r
     }\r
   }\r
 \r
-  LatestRevision = 0;\r
-  MicrocodeData  = NULL;\r
-  MicrocodeEnd = (UINTN) (CpuMpData->MicrocodePatchAddress + CpuMpData->MicrocodePatchRegionSize);\r
-  MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) CpuMpData->MicrocodePatchAddress;\r
+  //\r
+  // BSP or AP which is different from BSP runs here\r
+  // Use 0 as the starting revision to search for microcode because MicrocodePatchInfo HOB needs\r
+  // the latest microcode location even it's loaded to the processor.\r
+  //\r
+  LatestRevision  = 0;\r
+  LatestMicrocode = NULL;\r
+  Microcode       = (CPU_MICROCODE_HEADER *) (UINTN) CpuMpData->MicrocodePatchAddress;\r
+  MicrocodeEnd    = (UINTN) Microcode + (UINTN) CpuMpData->MicrocodePatchRegionSize;\r
 \r
   do {\r
-    //\r
-    // Check if the microcode is for the Cpu and the version is newer\r
-    // and the update can be processed on the platform\r
-    //\r
-    CorrectMicrocode = FALSE;\r
-\r
-    if (MicrocodeEntryPoint->DataSize == 0) {\r
-      TotalSize = sizeof (CPU_MICROCODE_HEADER) + 2000;\r
-    } else {\r
-      TotalSize = sizeof (CPU_MICROCODE_HEADER) + MicrocodeEntryPoint->DataSize;\r
-    }\r
-\r
-    ///\r
-    /// 0x0       MicrocodeBegin  MicrocodeEntry  MicrocodeEnd      0xffffffff\r
-    /// |--------------|---------------|---------------|---------------|\r
-    ///                                 valid TotalSize\r
-    /// TotalSize is only valid between 0 and (MicrocodeEnd - MicrocodeEntry).\r
-    /// And it should be aligned with 4 bytes.\r
-    /// If the TotalSize is invalid, skip 1KB to check next entry.\r
-    ///\r
-    if ( (UINTN)MicrocodeEntryPoint > (MAX_ADDRESS - TotalSize) ||\r
-         ((UINTN)MicrocodeEntryPoint + TotalSize) > MicrocodeEnd ||\r
-         (TotalSize & 0x3) != 0\r
-       ) {\r
-      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);\r
-      continue;\r
-    }\r
-\r
-    //\r
-    // Save an in-complete CheckSum32 from CheckSum Part1 for common parts.\r
-    //\r
-    InCompleteCheckSum32 = CalculateSum32 (\r
-                             (UINT32 *) MicrocodeEntryPoint,\r
-                             TotalSize\r
-                             );\r
-    InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorSignature.Uint32;\r
-    InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorFlags;\r
-    InCompleteCheckSum32 -= MicrocodeEntryPoint->Checksum;\r
-\r
-    if (MicrocodeEntryPoint->HeaderVersion == 0x1) {\r
-      //\r
-      // It is the microcode header. It is not the padding data between microcode patches\r
-      // because the padding data should not include 0x00000001 and it should be the repeated\r
-      // byte format (like 0xXYXYXYXY....).\r
-      //\r
-      if (MicrocodeEntryPoint->ProcessorSignature.Uint32 == Eax.Uint32 &&\r
-          MicrocodeEntryPoint->UpdateRevision > LatestRevision &&\r
-          (MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId))\r
-          ) {\r
-        //\r
-        // Calculate CheckSum Part1.\r
-        //\r
-        CheckSum32 = InCompleteCheckSum32;\r
-        CheckSum32 += MicrocodeEntryPoint->ProcessorSignature.Uint32;\r
-        CheckSum32 += MicrocodeEntryPoint->ProcessorFlags;\r
-        CheckSum32 += MicrocodeEntryPoint->Checksum;\r
-        if (CheckSum32 == 0) {\r
-          CorrectMicrocode = TRUE;\r
-        }\r
-      } else if ((MicrocodeEntryPoint->DataSize != 0) &&\r
-                 (MicrocodeEntryPoint->UpdateRevision > LatestRevision)) {\r
-        ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize +\r
-                                sizeof (CPU_MICROCODE_HEADER));\r
-        if (ExtendedTableLength != 0) {\r
-          //\r
-          // Extended Table exist, check if the CPU in support list\r
-          //\r
-          ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)\r
-                                  + MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER));\r
-          //\r
-          // Calculate Extended Checksum\r
-          //\r
-          if ((ExtendedTableLength % 4) == 0) {\r
-            //\r
-            // Calculate CheckSum Part2.\r
-            //\r
-            CheckSum32 = CalculateSum32 ((UINT32 *) ExtendedTableHeader, ExtendedTableLength);\r
-            if (CheckSum32 == 0) {\r
-              //\r
-              // Checksum correct\r
-              //\r
-              ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;\r
-              ExtendedTable      = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);\r
-              for (Index = 0; Index < ExtendedTableCount; Index ++) {\r
-                //\r
-                // Calculate CheckSum Part3.\r
-                //\r
-                CheckSum32 = InCompleteCheckSum32;\r
-                CheckSum32 += ExtendedTable->ProcessorSignature.Uint32;\r
-                CheckSum32 += ExtendedTable->ProcessorFlag;\r
-                CheckSum32 += ExtendedTable->Checksum;\r
-                if (CheckSum32 == 0) {\r
-                  //\r
-                  // Verify Header\r
-                  //\r
-                  if ((ExtendedTable->ProcessorSignature.Uint32 == Eax.Uint32) &&\r
-                      (ExtendedTable->ProcessorFlag & (1 << PlatformId)) ) {\r
-                    //\r
-                    // Find one\r
-                    //\r
-                    CorrectMicrocode = TRUE;\r
-                    break;\r
-                  }\r
-                }\r
-                ExtendedTable ++;\r
-              }\r
-            }\r
-          }\r
-        }\r
-      }\r
-    } else {\r
+    if (!IsValidMicrocode (Microcode, MicrocodeEnd - (UINTN) Microcode, LatestRevision, &MicrocodeCpuId, 1, TRUE)) {\r
       //\r
       // It is the padding data between the microcode patches for microcode patches alignment.\r
       // Because the microcode patch is the multiple of 1-KByte, the padding data should not\r
@@ -272,156 +81,40 @@ MicrocodeDetect (
       // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to\r
       // find the next possible microcode patch header.\r
       //\r
-      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);\r
+      Microcode = (CPU_MICROCODE_HEADER *) ((UINTN) Microcode + SIZE_1KB);\r
       continue;\r
     }\r
-    //\r
-    // Get the next patch.\r
-    //\r
-    if (MicrocodeEntryPoint->DataSize == 0) {\r
-      TotalSize = 2048;\r
-    } else {\r
-      TotalSize = MicrocodeEntryPoint->TotalSize;\r
-    }\r
+    LatestMicrocode = Microcode;\r
+    LatestRevision  = LatestMicrocode->UpdateRevision;\r
 \r
-    if (CorrectMicrocode) {\r
-      LatestRevision = MicrocodeEntryPoint->UpdateRevision;\r
-      MicrocodeData = (VOID *) ((UINTN) MicrocodeEntryPoint + sizeof (CPU_MICROCODE_HEADER));\r
-    }\r
-\r
-    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);\r
-  } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));\r
+    Microcode = (CPU_MICROCODE_HEADER *) (((UINTN) Microcode) + GetMicrocodeLength (Microcode));\r
+  } while ((UINTN) Microcode < MicrocodeEnd);\r
 \r
-Done:\r
+LoadMicrocode:\r
   if (LatestRevision != 0) {\r
     //\r
-    // Save the detected microcode patch entry address (including the\r
-    // microcode patch header) for each processor.\r
+    // Save the detected microcode patch entry address (including the microcode\r
+    // patch header) for each processor even it's the same as the loaded one.\r
     // It will be used when building the microcode patch cache HOB.\r
     //\r
-    CpuMpData->CpuData[ProcessorNumber].MicrocodeEntryAddr =\r
-      (UINTN) MicrocodeData -  sizeof (CPU_MICROCODE_HEADER);\r
+    CpuMpData->CpuData[ProcessorNumber].MicrocodeEntryAddr = (UINTN) LatestMicrocode;\r
   }\r
 \r
-  if (LatestRevision > CurrentRevision) {\r
+  if (LatestRevision > GetProcessorMicrocodeSignature ()) {\r
     //\r
     // BIOS only authenticate updates that contain a numerically larger revision\r
     // than the currently loaded revision, where Current Signature < New Update\r
     // Revision. A processor with no loaded update is considered to have a\r
     // revision equal to zero.\r
     //\r
-    ASSERT (MicrocodeData != NULL);\r
-    AsmWriteMsr64 (\r
-        MSR_IA32_BIOS_UPDT_TRIG,\r
-        (UINT64) (UINTN) MicrocodeData\r
-        );\r
-  }\r
-  CpuMpData->CpuData[ProcessorNumber].MicrocodeRevision = GetCurrentMicrocodeSignature ();\r
-}\r
-\r
-/**\r
-  Determine if a microcode patch matchs the specific processor signature and flag.\r
-\r
-  @param[in]  CpuMpData             The pointer to CPU MP Data structure.\r
-  @param[in]  ProcessorSignature    The processor signature field value\r
-                                    supported by a microcode patch.\r
-  @param[in]  ProcessorFlags        The prcessor flags field value supported by\r
-                                    a microcode patch.\r
-\r
-  @retval TRUE     The specified microcode patch will be loaded.\r
-  @retval FALSE    The specified microcode patch will not be loaded.\r
-**/\r
-BOOLEAN\r
-IsProcessorMatchedMicrocodePatch (\r
-  IN CPU_MP_DATA                 *CpuMpData,\r
-  IN UINT32                      ProcessorSignature,\r
-  IN UINT32                      ProcessorFlags\r
-  )\r
-{\r
-  UINTN          Index;\r
-  CPU_AP_DATA    *CpuData;\r
-\r
-  for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
-    CpuData = &CpuMpData->CpuData[Index];\r
-    if ((ProcessorSignature == CpuData->ProcessorSignature) &&\r
-        (ProcessorFlags & (1 << CpuData->PlatformId)) != 0) {\r
-      return TRUE;\r
-    }\r
+    LoadMicrocode (LatestMicrocode);\r
   }\r
-\r
-  return FALSE;\r
-}\r
-\r
-/**\r
-  Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode\r
-  patch header with the CPUID and PlatformID of the processors within\r
-  system to decide if it will be copied into memory.\r
-\r
-  @param[in]  CpuMpData             The pointer to CPU MP Data structure.\r
-  @param[in]  MicrocodeEntryPoint   The pointer to the microcode patch header.\r
-\r
-  @retval TRUE     The specified microcode patch need to be loaded.\r
-  @retval FALSE    The specified microcode patch dosen't need to be loaded.\r
-**/\r
-BOOLEAN\r
-IsMicrocodePatchNeedLoad (\r
-  IN CPU_MP_DATA                 *CpuMpData,\r
-  CPU_MICROCODE_HEADER           *MicrocodeEntryPoint\r
-  )\r
-{\r
-  BOOLEAN                                NeedLoad;\r
-  UINTN                                  DataSize;\r
-  UINTN                                  TotalSize;\r
-  CPU_MICROCODE_EXTENDED_TABLE_HEADER    *ExtendedTableHeader;\r
-  UINT32                                 ExtendedTableCount;\r
-  CPU_MICROCODE_EXTENDED_TABLE           *ExtendedTable;\r
-  UINTN                                  Index;\r
-\r
   //\r
-  // Check the 'ProcessorSignature' and 'ProcessorFlags' in microcode patch header.\r
+  // It's possible that the microcode fails to load. Just capture the CPU microcode revision after loading.\r
   //\r
-  NeedLoad = IsProcessorMatchedMicrocodePatch (\r
-               CpuMpData,\r
-               MicrocodeEntryPoint->ProcessorSignature.Uint32,\r
-               MicrocodeEntryPoint->ProcessorFlags\r
-               );\r
-\r
-  //\r
-  // If the Extended Signature Table exists, check if the processor is in the\r
-  // support list\r
-  //\r
-  DataSize  = MicrocodeEntryPoint->DataSize;\r
-  TotalSize = (DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;\r
-  if ((!NeedLoad) && (DataSize != 0) &&\r
-      (TotalSize - DataSize > sizeof (CPU_MICROCODE_HEADER) +\r
-                              sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER))) {\r
-    ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)\r
-                            + DataSize + sizeof (CPU_MICROCODE_HEADER));\r
-    ExtendedTableCount  = ExtendedTableHeader->ExtendedSignatureCount;\r
-    ExtendedTable       = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);\r
-\r
-    for (Index = 0; Index < ExtendedTableCount; Index ++) {\r
-      //\r
-      // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended\r
-      // Signature Table entry with the CPUID and PlatformID of the processors\r
-      // within system to decide if it will be copied into memory\r
-      //\r
-      NeedLoad = IsProcessorMatchedMicrocodePatch (\r
-                   CpuMpData,\r
-                   ExtendedTable->ProcessorSignature.Uint32,\r
-                   ExtendedTable->ProcessorFlag\r
-                   );\r
-      if (NeedLoad) {\r
-        break;\r
-      }\r
-      ExtendedTable ++;\r
-    }\r
-  }\r
-\r
-  return NeedLoad;\r
+  CpuMpData->CpuData[ProcessorNumber].MicrocodeRevision = GetProcessorMicrocodeSignature ();\r
 }\r
 \r
-\r
 /**\r
   Actual worker function that shadows the required microcode patches into memory.\r
 \r
@@ -491,14 +184,16 @@ ShadowMicrocodePatchByPcd (
   IN OUT CPU_MP_DATA             *CpuMpData\r
   )\r
 {\r
+  UINTN                                  Index;\r
   CPU_MICROCODE_HEADER                   *MicrocodeEntryPoint;\r
   UINTN                                  MicrocodeEnd;\r
-  UINTN                                  DataSize;\r
   UINTN                                  TotalSize;\r
   MICROCODE_PATCH_INFO                   *PatchInfoBuffer;\r
   UINTN                                  MaxPatchNumber;\r
   UINTN                                  PatchCount;\r
   UINTN                                  TotalLoadSize;\r
+  EDKII_PEI_MICROCODE_CPU_ID             *MicrocodeCpuIds;\r
+  BOOLEAN                                Valid;\r
 \r
   //\r
   // Initialize the microcode patch related fields in CpuMpData as the values\r
@@ -526,12 +221,34 @@ ShadowMicrocodePatchByPcd (
     return;\r
   }\r
 \r
+  MicrocodeCpuIds = AllocatePages (\r
+                      EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * sizeof (EDKII_PEI_MICROCODE_CPU_ID))\r
+                      );\r
+  if (MicrocodeCpuIds == NULL) {\r
+    FreePool (PatchInfoBuffer);\r
+    return;\r
+  }\r
+\r
+  for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
+    MicrocodeCpuIds[Index].PlatformId         = CpuMpData->CpuData[Index].PlatformId;\r
+    MicrocodeCpuIds[Index].ProcessorSignature = CpuMpData->CpuData[Index].ProcessorSignature;\r
+  }\r
+\r
   //\r
   // Process the header of each microcode patch within the region.\r
   // The purpose is to decide which microcode patch(es) will be loaded into memory.\r
+  // Microcode checksum is not verified because it's slow when performing on flash.\r
   //\r
   do {\r
-    if (MicrocodeEntryPoint->HeaderVersion != 0x1) {\r
+    Valid = IsValidMicrocode (\r
+              MicrocodeEntryPoint,\r
+              MicrocodeEnd - (UINTN) MicrocodeEntryPoint,\r
+              0,\r
+              MicrocodeCpuIds,\r
+              CpuMpData->CpuCount,\r
+              FALSE\r
+              );\r
+    if (!Valid) {\r
       //\r
       // Padding data between the microcode patches, skip 1KB to check next entry.\r
       //\r
@@ -539,59 +256,44 @@ ShadowMicrocodePatchByPcd (
       continue;\r
     }\r
 \r
-    DataSize  = MicrocodeEntryPoint->DataSize;\r
-    TotalSize = (DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;\r
-    if ( (UINTN)MicrocodeEntryPoint > (MAX_ADDRESS - TotalSize) ||\r
-         ((UINTN)MicrocodeEntryPoint + TotalSize) > MicrocodeEnd ||\r
-         (DataSize & 0x3) != 0 ||\r
-         (TotalSize & (SIZE_1KB - 1)) != 0 ||\r
-         TotalSize < DataSize\r
-       ) {\r
+    PatchCount++;\r
+    if (PatchCount > MaxPatchNumber) {\r
       //\r
-      // Not a valid microcode header, skip 1KB to check next entry.\r
+      // Current 'PatchInfoBuffer' cannot hold the information, double the size\r
+      // and allocate a new buffer.\r
       //\r
-      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);\r
-      continue;\r
-    }\r
-\r
-    if (IsMicrocodePatchNeedLoad (CpuMpData, MicrocodeEntryPoint)) {\r
-      PatchCount++;\r
-      if (PatchCount > MaxPatchNumber) {\r
+      if (MaxPatchNumber > MAX_UINTN / 2 / sizeof (MICROCODE_PATCH_INFO)) {\r
         //\r
-        // Current 'PatchInfoBuffer' cannot hold the information, double the size\r
-        // and allocate a new buffer.\r
+        // Overflow check for MaxPatchNumber\r
         //\r
-        if (MaxPatchNumber > MAX_UINTN / 2 / sizeof (MICROCODE_PATCH_INFO)) {\r
-          //\r
-          // Overflow check for MaxPatchNumber\r
-          //\r
-          goto OnExit;\r
-        }\r
-\r
-        PatchInfoBuffer = ReallocatePool (\r
-                            MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),\r
-                            2 * MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),\r
-                            PatchInfoBuffer\r
-                            );\r
-        if (PatchInfoBuffer == NULL) {\r
-          goto OnExit;\r
-        }\r
-        MaxPatchNumber = MaxPatchNumber * 2;\r
+        goto OnExit;\r
       }\r
 \r
-      //\r
-      // Store the information of this microcode patch\r
-      //\r
-      PatchInfoBuffer[PatchCount - 1].Address = (UINTN) MicrocodeEntryPoint;\r
-      PatchInfoBuffer[PatchCount - 1].Size    = TotalSize;\r
-      TotalLoadSize += TotalSize;\r
+      PatchInfoBuffer = ReallocatePool (\r
+                          MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),\r
+                          2 * MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),\r
+                          PatchInfoBuffer\r
+                          );\r
+      if (PatchInfoBuffer == NULL) {\r
+        goto OnExit;\r
+      }\r
+      MaxPatchNumber = MaxPatchNumber * 2;\r
     }\r
 \r
+    TotalSize = GetMicrocodeLength (MicrocodeEntryPoint);\r
+\r
+    //\r
+    // Store the information of this microcode patch\r
+    //\r
+    PatchInfoBuffer[PatchCount - 1].Address = (UINTN) MicrocodeEntryPoint;\r
+    PatchInfoBuffer[PatchCount - 1].Size    = TotalSize;\r
+    TotalLoadSize += TotalSize;\r
+\r
     //\r
     // Process the next microcode patch\r
     //\r
-    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);\r
-  } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));\r
+    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) ((UINTN) MicrocodeEntryPoint + TotalSize);\r
+  } while ((UINTN) MicrocodeEntryPoint < MicrocodeEnd);\r
 \r
   if (PatchCount != 0) {\r
     DEBUG ((\r
@@ -607,7 +309,7 @@ OnExit:
   if (PatchInfoBuffer != NULL) {\r
     FreePool (PatchInfoBuffer);\r
   }\r
-  return;\r
+  FreePages (MicrocodeCpuIds, EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * sizeof (EDKII_PEI_MICROCODE_CPU_ID)));\r
 }\r
 \r
 /**\r
index 66f9eb2304cb759200673591cff7042ae6fdc26f..e88a5355c983f0fbc66b08c648c5d3c34f8e0d49 100644 (file)
@@ -32,6 +32,7 @@
 #include <Library/MtrrLib.h>\r
 #include <Library/HobLib.h>\r
 #include <Library/PcdLib.h>\r
+#include <Library/MicrocodeLib.h>\r
 \r
 #include <Guid/MicrocodePatchHob.h>\r
 \r
index 49b0ffe8be8a43a81d9fc1f6c32eb1305d516a43..36fcb96b5852c25f39a2d4d1e4932bf281ad1213 100644 (file)
@@ -51,6 +51,7 @@
   PeiServicesLib\r
   PcdLib\r
   VmgExitLib\r
+  MicrocodeLib\r
 \r
 [Pcd]\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber        ## CONSUMES\r