/**\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
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
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
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
// 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
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