]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/Microcode: Fix incorrect checksum issue for extended table
authorChen A Chen <chen.a.chen@intel.com>
Fri, 15 Feb 2019 06:29:41 +0000 (14:29 +0800)
committerEric Dong <eric.dong@intel.com>
Thu, 21 Feb 2019 08:16:56 +0000 (16:16 +0800)
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1020

The following Microcode payload format is define in SDM spec.
Payload: |MicrocodeHeader|MicrocodeBinary|ExtendedHeader|ExtendedTable|.
When we verify the CheckSum32 with ExtendedTable, we should use the fields
of ExtendedTable to replace corresponding fields in MicrocodeHeader,
and then calculate the CheckSum32 with MicrocodeHeader+MicrocodeBinary.
This patch already verified on ICL platform.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Chen A Chen <chen.a.chen@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Zhang Chao B <chao.b.zhang@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
UefiCpuPkg/Library/MpInitLib/Microcode.c

index d84344c6f56a96fd89140cc0c5935df4b54d1f08..e1f661d6b10431f170cf4246cfe82dabe164e4a7 100644 (file)
@@ -35,6 +35,42 @@ GetCurrentMicrocodeSignature (
 /**\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]  IsBspCallIn  Indicate whether the caller is BSP or not.\r
 **/\r
@@ -57,6 +93,7 @@ MicrocodeDetect (
   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
@@ -121,6 +158,25 @@ MicrocodeDetect (
   MicrocodeData  = NULL;\r
   MicrocodeEnd = (UINTN) (CpuMpData->MicrocodePatchAddress + CpuMpData->MicrocodePatchRegionSize);\r
   MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) CpuMpData->MicrocodePatchAddress;\r
+\r
+  //\r
+  // Save an in-complete CheckSum32 from CheckSum Part1 for common parts.\r
+  //\r
+  if (MicrocodeEntryPoint->DataSize == 0) {\r
+    InCompleteCheckSum32 = CalculateSum32 (\r
+                             (UINT32 *) MicrocodeEntryPoint,\r
+                             sizeof (CPU_MICROCODE_HEADER) + 2000\r
+                             );\r
+  } else {\r
+    InCompleteCheckSum32 = CalculateSum32 (\r
+                             (UINT32 *) MicrocodeEntryPoint,\r
+                             sizeof (CPU_MICROCODE_HEADER) + MicrocodeEntryPoint->DataSize\r
+                             );\r
+  }\r
+  InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorSignature.Uint32;\r
+  InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorFlags;\r
+  InCompleteCheckSum32 -= MicrocodeEntryPoint->Checksum;\r
+\r
   do {\r
     //\r
     // Check if the microcode is for the Cpu and the version is newer\r
@@ -137,14 +193,13 @@ MicrocodeDetect (
           MicrocodeEntryPoint->UpdateRevision > LatestRevision &&\r
           (MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId))\r
           ) {\r
-        if (MicrocodeEntryPoint->DataSize == 0) {\r
-          CheckSum32 = CalculateSum32 ((UINT32 *) MicrocodeEntryPoint, 2048);\r
-        } else {\r
-          CheckSum32 = CalculateSum32 (\r
-                         (UINT32 *) MicrocodeEntryPoint,\r
-                         MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER)\r
-                         );\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
           ProcessorFlags = MicrocodeEntryPoint->ProcessorFlags;\r
@@ -163,6 +218,9 @@ MicrocodeDetect (
           // 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
@@ -171,7 +229,13 @@ MicrocodeDetect (
               ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;\r
               ExtendedTable      = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);\r
               for (Index = 0; Index < ExtendedTableCount; Index ++) {\r
-                CheckSum32 = CalculateSum32 ((UINT32 *) ExtendedTable, sizeof(CPU_MICROCODE_EXTENDED_TABLE));\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