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:
Ray Ni 2021-04-02 00:32:44 +08:00 committed by mergify[bot]
parent 83c7f8178b
commit bce0328431
4 changed files with 98 additions and 393 deletions

View File

@ -52,6 +52,7 @@
SynchronizationLib SynchronizationLib
PcdLib PcdLib
VmgExitLib VmgExitLib
MicrocodeLib
[Protocols] [Protocols]
gEfiTimerArchProtocolGuid ## SOMETIMES_CONSUMES gEfiTimerArchProtocolGuid ## SOMETIMES_CONSUMES

View File

@ -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)));
} }
/** /**

View File

@ -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>

View File

@ -51,6 +51,7 @@
PeiServicesLib PeiServicesLib
PcdLib PcdLib
VmgExitLib VmgExitLib
MicrocodeLib
[Pcd] [Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES