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