From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga09.intel.com (mga09.intel.com []) by mx.groups.io with SMTP id smtpd.web08.12337.1617343099200294881 for ; Thu, 01 Apr 2021 22:58:24 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: ray.ni@intel.com) IronPort-SDR: okGGpaZ6rQ/hE6HDGhAKzd80oGgliKx8TwLeY9S7vvSVBaLkCxjxhagh94dsiFDYPlbi6Fanp9 MRNFKfmXkpRQ== X-IronPort-AV: E=McAfee;i="6000,8403,9941"; a="192501556" X-IronPort-AV: E=Sophos;i="5.81,298,1610438400"; d="scan'208";a="192501556" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2021 22:58:24 -0700 IronPort-SDR: SDPNpfm78uISlygaeVlUr0tO+kN5qMAw9wpI1aOegPOgslztPLJDxnpL+N2uySuGwknOMiwRaz p4I0rNbZGyuw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,298,1610438400"; d="scan'208";a="413029646" Received: from ray-dev.ccr.corp.intel.com ([10.239.158.87]) by fmsmga008.fm.intel.com with ESMTP; 01 Apr 2021 22:58:22 -0700 From: "Ni, Ray" To: devel@edk2.groups.io Cc: Eric Dong , Laszlo Ersek , Rahul Kumar Subject: [PATCH 4/4] UefiCpuPkg/MpInitLib: Consume MicrocodeLib to remove duplicated code Date: Fri, 2 Apr 2021 13:58:07 +0800 Message-Id: <20210402055807.858-5-ray.ni@intel.com> X-Mailer: git-send-email 2.27.0.windows.1 In-Reply-To: <20210402055807.858-1-ray.ni@intel.com> References: <20210402055807.858-1-ray.ni@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Signed-off-by: Ray Ni Cc: Eric Dong Cc: Laszlo Ersek Cc: Rahul Kumar --- UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 1 + UefiCpuPkg/Library/MpInitLib/Microcode.c | 484 ++++-------------- UefiCpuPkg/Library/MpInitLib/MpLib.h | 1 + UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 1 + 4 files changed, 96 insertions(+), 391 deletions(-) diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Lib= rary/MpInitLib/DxeMpInitLib.inf index 860a9750e2..d34419c2a5 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf @@ -52,6 +52,7 @@ [LibraryClasses] SynchronizationLib=0D PcdLib=0D VmgExitLib=0D + MicrocodeLib=0D =0D [Protocols]=0D gEfiTimerArchProtocolGuid ## SOMETIMES_CONSUMES=0D diff --git a/UefiCpuPkg/Library/MpInitLib/Microcode.c b/UefiCpuPkg/Library/= MpInitLib/Microcode.c index 297c2abcd1..105a9f84bf 100644 --- a/UefiCpuPkg/Library/MpInitLib/Microcode.c +++ b/UefiCpuPkg/Library/MpInitLib/Microcode.c @@ -1,70 +1,16 @@ /** @file=0D Implementation of loading microcode on processors.=0D =0D - Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.
=0D + Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.
=0D SPDX-License-Identifier: BSD-2-Clause-Patent=0D =0D **/=0D =0D #include "MpLib.h"=0D =0D -/**=0D - Get microcode update signature of currently loaded microcode update.=0D -=0D - @return Microcode signature.=0D -**/=0D -UINT32=0D -GetCurrentMicrocodeSignature (=0D - VOID=0D - )=0D -{=0D - MSR_IA32_BIOS_SIGN_ID_REGISTER BiosSignIdMsr;=0D -=0D - AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);=0D - AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);=0D - BiosSignIdMsr.Uint64 =3D AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID);=0D - return BiosSignIdMsr.Bits.MicrocodeUpdateSignature;=0D -}=0D -=0D /**=0D Detect whether specified processor can find matching microcode patch and= load it.=0D =0D - Microcode Payload as the following format:=0D - +----------------------------------------+------------------+=0D - | CPU_MICROCODE_HEADER | |=0D - +----------------------------------------+ CheckSum Part1 |=0D - | Microcode Binary | |=0D - +----------------------------------------+------------------+=0D - | CPU_MICROCODE_EXTENDED_TABLE_HEADER | |=0D - +----------------------------------------+ CheckSum Part2 |=0D - | CPU_MICROCODE_EXTENDED_TABLE | |=0D - | ... | |=0D - +----------------------------------------+------------------+=0D -=0D - There may by multiple CPU_MICROCODE_EXTENDED_TABLE in this format.=0D - The count of CPU_MICROCODE_EXTENDED_TABLE is indicated by ExtendedSignat= ureCount=0D - of CPU_MICROCODE_EXTENDED_TABLE_HEADER structure.=0D -=0D - When we are trying to verify the CheckSum32 with extended table.=0D - We should use the fields of exnteded table to replace the corresponding= =0D - fields in CPU_MICROCODE_HEADER structure, and recalculate the=0D - CheckSum32 with CPU_MICROCODE_HEADER + Microcode Binary. We named=0D - it as CheckSum Part3.=0D -=0D - The CheckSum Part2 is used to verify the CPU_MICROCODE_EXTENDED_TABLE_HE= ADER=0D - and CPU_MICROCODE_EXTENDED_TABLE parts. We should make sure CheckSum Par= t2=0D - is correct before we are going to verify each CPU_MICROCODE_EXTENDED_TAB= LE.=0D -=0D - Only ProcessorSignature, ProcessorFlag and CheckSum are different betwee= n=0D - CheckSum Part1 and CheckSum Part3. To avoid multiple computing CheckSum = Part3.=0D - Save an in-complete CheckSum32 from CheckSum Part1 for common parts.=0D - When we are going to calculate CheckSum32, just should use the correspon= ding part=0D - of the ProcessorSignature, ProcessorFlag and CheckSum with in-complete C= heckSum32.=0D -=0D - Notes: CheckSum32 is not a strong verification.=0D - It does not guarantee that the data has not been modified.=0D - CPU has its own mechanism to verify Microcode Binary part.=0D -=0D @param[in] CpuMpData The pointer to CPU MP Data structure.=0D @param[in] ProcessorNumber The handle number of the processor. The ran= ge is=0D from 0 to the total number of logical proce= ssors=0D @@ -76,26 +22,13 @@ MicrocodeDetect ( IN UINTN ProcessorNumber=0D )=0D {=0D - UINT32 ExtendedTableLength;=0D - UINT32 ExtendedTableCount;=0D - CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;=0D - CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;=0D - CPU_MICROCODE_HEADER *MicrocodeEntryPoint;=0D + CPU_MICROCODE_HEADER *Microcode;=0D UINTN MicrocodeEnd;=0D - UINTN Index;=0D - UINT8 PlatformId;=0D - CPUID_VERSION_INFO_EAX Eax;=0D - CPU_AP_DATA *CpuData;=0D - UINT32 CurrentRevision;=0D + CPU_AP_DATA *BspData;=0D UINT32 LatestRevision;=0D - UINTN TotalSize;=0D - UINT32 CheckSum32;=0D - UINT32 InCompleteCheckSum32;=0D - BOOLEAN CorrectMicrocode;=0D - VOID *MicrocodeData;=0D - MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr;=0D + CPU_MICROCODE_HEADER *LatestMicrocode;=0D UINT32 ThreadId;=0D - BOOLEAN IsBspCallIn;=0D + EDKII_PEI_MICROCODE_CPU_ID MicrocodeCpuId;=0D =0D if (CpuMpData->MicrocodePatchRegionSize =3D=3D 0) {=0D //=0D @@ -104,9 +37,6 @@ MicrocodeDetect ( return;=0D }=0D =0D - CurrentRevision =3D GetCurrentMicrocodeSignature ();=0D - IsBspCallIn =3D (ProcessorNumber =3D=3D (UINTN)CpuMpData->BspNumber)= ? TRUE : FALSE;=0D -=0D GetProcessorLocationByApicId (GetInitialApicId (), NULL, NULL, &ThreadId= );=0D if (ThreadId !=3D 0) {=0D //=0D @@ -115,156 +45,35 @@ MicrocodeDetect ( return;=0D }=0D =0D - ExtendedTableLength =3D 0;=0D - //=0D - // Here data of CPUID leafs have not been collected into context buffer,= so=0D - // GetProcessorCpuid() cannot be used here to retrieve CPUID data.=0D - //=0D - AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);=0D + GetProcessorMicrocodeCpuId (&MicrocodeCpuId);=0D =0D - //=0D - // The index of platform information resides in bits 50:52 of MSR IA32_P= LATFORM_ID=0D - //=0D - PlatformIdMsr.Uint64 =3D AsmReadMsr64 (MSR_IA32_PLATFORM_ID);=0D - PlatformId =3D (UINT8) PlatformIdMsr.Bits.PlatformId;=0D -=0D -=0D - //=0D - // Check whether AP has same processor with BSP.=0D - // If yes, direct use microcode info saved by BSP.=0D - //=0D - if (!IsBspCallIn) {=0D + if (ProcessorNumber !=3D (UINTN) CpuMpData->BspNumber) {=0D //=0D - // Get the CPU data for BSP=0D + // Direct use microcode of BSP if AP is the same as BSP.=0D + // Assume BSP calls this routine() before AP.=0D //=0D - CpuData =3D &(CpuMpData->CpuData[CpuMpData->BspNumber]);=0D - if ((CpuData->ProcessorSignature =3D=3D Eax.Uint32) &&=0D - (CpuData->PlatformId =3D=3D PlatformId) &&=0D - (CpuData->MicrocodeEntryAddr !=3D 0)) {=0D - MicrocodeEntryPoint =3D (CPU_MICROCODE_HEADER *)(UINTN) CpuData->Mic= rocodeEntryAddr;=0D - MicrocodeData =3D (VOID *) (MicrocodeEntryPoint + 1);=0D - LatestRevision =3D MicrocodeEntryPoint->UpdateRevision;=0D - goto Done;=0D + BspData =3D &(CpuMpData->CpuData[CpuMpData->BspNumber]);=0D + if ((BspData->ProcessorSignature =3D=3D MicrocodeCpuId.ProcessorSignat= ure) &&=0D + (BspData->PlatformId =3D=3D MicrocodeCpuId.PlatformId) &&=0D + (BspData->MicrocodeEntryAddr !=3D 0)) {=0D + LatestMicrocode =3D (CPU_MICROCODE_HEADER *)(UINTN) BspData->Microco= deEntryAddr;=0D + LatestRevision =3D LatestMicrocode->UpdateRevision;=0D + goto LoadMicrocode;=0D }=0D }=0D =0D - LatestRevision =3D 0;=0D - MicrocodeData =3D NULL;=0D - MicrocodeEnd =3D (UINTN) (CpuMpData->MicrocodePatchAddress + CpuMpData->= MicrocodePatchRegionSize);=0D - MicrocodeEntryPoint =3D (CPU_MICROCODE_HEADER *) (UINTN) CpuMpData->Micr= ocodePatchAddress;=0D + //=0D + // BSP or AP which is different from BSP runs here=0D + // Use 0 as the starting revision to search for microcode because Microc= odePatchInfo HOB needs=0D + // the latest microcode location even it's loaded to the processor.=0D + //=0D + LatestRevision =3D 0;=0D + LatestMicrocode =3D NULL;=0D + Microcode =3D (CPU_MICROCODE_HEADER *) (UINTN) CpuMpData->Microcod= ePatchAddress;=0D + MicrocodeEnd =3D (UINTN) Microcode + (UINTN) CpuMpData->MicrocodePatc= hRegionSize;=0D =0D do {=0D - //=0D - // Check if the microcode is for the Cpu and the version is newer=0D - // and the update can be processed on the platform=0D - //=0D - CorrectMicrocode =3D FALSE;=0D -=0D - if (MicrocodeEntryPoint->DataSize =3D=3D 0) {=0D - TotalSize =3D sizeof (CPU_MICROCODE_HEADER) + 2000;=0D - } else {=0D - TotalSize =3D sizeof (CPU_MICROCODE_HEADER) + MicrocodeEntryPoint->D= ataSize;=0D - }=0D -=0D - ///=0D - /// 0x0 MicrocodeBegin MicrocodeEntry MicrocodeEnd 0xffff= ffff=0D - /// |--------------|---------------|---------------|---------------|=0D - /// valid TotalSize=0D - /// TotalSize is only valid between 0 and (MicrocodeEnd - MicrocodeEnt= ry).=0D - /// And it should be aligned with 4 bytes.=0D - /// If the TotalSize is invalid, skip 1KB to check next entry.=0D - ///=0D - if ( (UINTN)MicrocodeEntryPoint > (MAX_ADDRESS - TotalSize) ||=0D - ((UINTN)MicrocodeEntryPoint + TotalSize) > MicrocodeEnd ||=0D - (TotalSize & 0x3) !=3D 0=0D - ) {=0D - MicrocodeEntryPoint =3D (CPU_MICROCODE_HEADER *) (((UINTN) Microcode= EntryPoint) + SIZE_1KB);=0D - continue;=0D - }=0D -=0D - //=0D - // Save an in-complete CheckSum32 from CheckSum Part1 for common parts= .=0D - //=0D - InCompleteCheckSum32 =3D CalculateSum32 (=0D - (UINT32 *) MicrocodeEntryPoint,=0D - TotalSize=0D - );=0D - InCompleteCheckSum32 -=3D MicrocodeEntryPoint->ProcessorSignature.Uint= 32;=0D - InCompleteCheckSum32 -=3D MicrocodeEntryPoint->ProcessorFlags;=0D - InCompleteCheckSum32 -=3D MicrocodeEntryPoint->Checksum;=0D -=0D - if (MicrocodeEntryPoint->HeaderVersion =3D=3D 0x1) {=0D - //=0D - // It is the microcode header. It is not the padding data between mi= crocode patches=0D - // because the padding data should not include 0x00000001 and it sho= uld be the repeated=0D - // byte format (like 0xXYXYXYXY....).=0D - //=0D - if (MicrocodeEntryPoint->ProcessorSignature.Uint32 =3D=3D Eax.Uint32= &&=0D - MicrocodeEntryPoint->UpdateRevision > LatestRevision &&=0D - (MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId))=0D - ) {=0D - //=0D - // Calculate CheckSum Part1.=0D - //=0D - CheckSum32 =3D InCompleteCheckSum32;=0D - CheckSum32 +=3D MicrocodeEntryPoint->ProcessorSignature.Uint32;=0D - CheckSum32 +=3D MicrocodeEntryPoint->ProcessorFlags;=0D - CheckSum32 +=3D MicrocodeEntryPoint->Checksum;=0D - if (CheckSum32 =3D=3D 0) {=0D - CorrectMicrocode =3D TRUE;=0D - }=0D - } else if ((MicrocodeEntryPoint->DataSize !=3D 0) &&=0D - (MicrocodeEntryPoint->UpdateRevision > LatestRevision)) {= =0D - ExtendedTableLength =3D MicrocodeEntryPoint->TotalSize - (Microcod= eEntryPoint->DataSize +=0D - sizeof (CPU_MICROCODE_HEADER));=0D - if (ExtendedTableLength !=3D 0) {=0D - //=0D - // Extended Table exist, check if the CPU in support list=0D - //=0D - ExtendedTableHeader =3D (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) = ((UINT8 *) (MicrocodeEntryPoint)=0D - + MicrocodeEntryPoint->DataSize + sizeof= (CPU_MICROCODE_HEADER));=0D - //=0D - // Calculate Extended Checksum=0D - //=0D - if ((ExtendedTableLength % 4) =3D=3D 0) {=0D - //=0D - // Calculate CheckSum Part2.=0D - //=0D - CheckSum32 =3D CalculateSum32 ((UINT32 *) ExtendedTableHeader,= ExtendedTableLength);=0D - if (CheckSum32 =3D=3D 0) {=0D - //=0D - // Checksum correct=0D - //=0D - ExtendedTableCount =3D ExtendedTableHeader->ExtendedSignatur= eCount;=0D - ExtendedTable =3D (CPU_MICROCODE_EXTENDED_TABLE *) (Ext= endedTableHeader + 1);=0D - for (Index =3D 0; Index < ExtendedTableCount; Index ++) {=0D - //=0D - // Calculate CheckSum Part3.=0D - //=0D - CheckSum32 =3D InCompleteCheckSum32;=0D - CheckSum32 +=3D ExtendedTable->ProcessorSignature.Uint32;= =0D - CheckSum32 +=3D ExtendedTable->ProcessorFlag;=0D - CheckSum32 +=3D ExtendedTable->Checksum;=0D - if (CheckSum32 =3D=3D 0) {=0D - //=0D - // Verify Header=0D - //=0D - if ((ExtendedTable->ProcessorSignature.Uint32 =3D=3D Eax= .Uint32) &&=0D - (ExtendedTable->ProcessorFlag & (1 << PlatformId)) )= {=0D - //=0D - // Find one=0D - //=0D - CorrectMicrocode =3D TRUE;=0D - break;=0D - }=0D - }=0D - ExtendedTable ++;=0D - }=0D - }=0D - }=0D - }=0D - }=0D - } else {=0D + if (!IsValidMicrocode (Microcode, MicrocodeEnd - (UINTN) Microcode, La= testRevision, &MicrocodeCpuId, 1, TRUE)) {=0D //=0D // It is the padding data between the microcode patches for microcod= e patches alignment.=0D // Because the microcode patch is the multiple of 1-KByte, the paddi= ng data should not=0D @@ -272,156 +81,40 @@ MicrocodeDetect ( // alignment value should be larger than 1-KByte. We could skip SIZE= _1KB padding data to=0D // find the next possible microcode patch header.=0D //=0D - MicrocodeEntryPoint =3D (CPU_MICROCODE_HEADER *) (((UINTN) Microcode= EntryPoint) + SIZE_1KB);=0D + Microcode =3D (CPU_MICROCODE_HEADER *) ((UINTN) Microcode + SIZE_1KB= );=0D continue;=0D }=0D - //=0D - // Get the next patch.=0D - //=0D - if (MicrocodeEntryPoint->DataSize =3D=3D 0) {=0D - TotalSize =3D 2048;=0D - } else {=0D - TotalSize =3D MicrocodeEntryPoint->TotalSize;=0D - }=0D + LatestMicrocode =3D Microcode;=0D + LatestRevision =3D LatestMicrocode->UpdateRevision;=0D =0D - if (CorrectMicrocode) {=0D - LatestRevision =3D MicrocodeEntryPoint->UpdateRevision;=0D - MicrocodeData =3D (VOID *) ((UINTN) MicrocodeEntryPoint + sizeof (CP= U_MICROCODE_HEADER));=0D - }=0D -=0D - MicrocodeEntryPoint =3D (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEn= tryPoint) + TotalSize);=0D - } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));=0D + Microcode =3D (CPU_MICROCODE_HEADER *) (((UINTN) Microcode) + GetMicro= codeLength (Microcode));=0D + } while ((UINTN) Microcode < MicrocodeEnd);=0D =0D -Done:=0D +LoadMicrocode:=0D if (LatestRevision !=3D 0) {=0D //=0D - // Save the detected microcode patch entry address (including the=0D - // microcode patch header) for each processor.=0D + // Save the detected microcode patch entry address (including the micr= ocode=0D + // patch header) for each processor even it's the same as the loaded o= ne.=0D // It will be used when building the microcode patch cache HOB.=0D //=0D - CpuMpData->CpuData[ProcessorNumber].MicrocodeEntryAddr =3D=0D - (UINTN) MicrocodeData - sizeof (CPU_MICROCODE_HEADER);=0D + CpuMpData->CpuData[ProcessorNumber].MicrocodeEntryAddr =3D (UINTN) Lat= estMicrocode;=0D }=0D =0D - if (LatestRevision > CurrentRevision) {=0D + if (LatestRevision > GetProcessorMicrocodeSignature ()) {=0D //=0D // BIOS only authenticate updates that contain a numerically larger re= vision=0D // than the currently loaded revision, where Current Signature < New U= pdate=0D // Revision. A processor with no loaded update is considered to have a= =0D // revision equal to zero.=0D //=0D - ASSERT (MicrocodeData !=3D NULL);=0D - AsmWriteMsr64 (=0D - MSR_IA32_BIOS_UPDT_TRIG,=0D - (UINT64) (UINTN) MicrocodeData=0D - );=0D - }=0D - CpuMpData->CpuData[ProcessorNumber].MicrocodeRevision =3D GetCurrentMicr= ocodeSignature ();=0D -}=0D -=0D -/**=0D - Determine if a microcode patch matchs the specific processor signature a= nd flag.=0D -=0D - @param[in] CpuMpData The pointer to CPU MP Data structure.= =0D - @param[in] ProcessorSignature The processor signature field value=0D - supported by a microcode patch.=0D - @param[in] ProcessorFlags The prcessor flags field value support= ed by=0D - a microcode patch.=0D -=0D - @retval TRUE The specified microcode patch will be loaded.=0D - @retval FALSE The specified microcode patch will not be loaded.=0D -**/=0D -BOOLEAN=0D -IsProcessorMatchedMicrocodePatch (=0D - IN CPU_MP_DATA *CpuMpData,=0D - IN UINT32 ProcessorSignature,=0D - IN UINT32 ProcessorFlags=0D - )=0D -{=0D - UINTN Index;=0D - CPU_AP_DATA *CpuData;=0D -=0D - for (Index =3D 0; Index < CpuMpData->CpuCount; Index++) {=0D - CpuData =3D &CpuMpData->CpuData[Index];=0D - if ((ProcessorSignature =3D=3D CpuData->ProcessorSignature) &&=0D - (ProcessorFlags & (1 << CpuData->PlatformId)) !=3D 0) {=0D - return TRUE;=0D - }=0D + LoadMicrocode (LatestMicrocode);=0D }=0D -=0D - return FALSE;=0D -}=0D -=0D -/**=0D - Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode=0D - patch header with the CPUID and PlatformID of the processors within=0D - system to decide if it will be copied into memory.=0D -=0D - @param[in] CpuMpData The pointer to CPU MP Data structure.= =0D - @param[in] MicrocodeEntryPoint The pointer to the microcode patch hea= der.=0D -=0D - @retval TRUE The specified microcode patch need to be loaded.=0D - @retval FALSE The specified microcode patch dosen't need to be loaded= .=0D -**/=0D -BOOLEAN=0D -IsMicrocodePatchNeedLoad (=0D - IN CPU_MP_DATA *CpuMpData,=0D - CPU_MICROCODE_HEADER *MicrocodeEntryPoint=0D - )=0D -{=0D - BOOLEAN NeedLoad;=0D - UINTN DataSize;=0D - UINTN TotalSize;=0D - CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;=0D - UINT32 ExtendedTableCount;=0D - CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;=0D - UINTN Index;=0D -=0D //=0D - // Check the 'ProcessorSignature' and 'ProcessorFlags' in microcode patc= h header.=0D + // It's possible that the microcode fails to load. Just capture the CPU = microcode revision after loading.=0D //=0D - NeedLoad =3D IsProcessorMatchedMicrocodePatch (=0D - CpuMpData,=0D - MicrocodeEntryPoint->ProcessorSignature.Uint32,=0D - MicrocodeEntryPoint->ProcessorFlags=0D - );=0D -=0D - //=0D - // If the Extended Signature Table exists, check if the processor is in = the=0D - // support list=0D - //=0D - DataSize =3D MicrocodeEntryPoint->DataSize;=0D - TotalSize =3D (DataSize =3D=3D 0) ? 2048 : MicrocodeEntryPoint->TotalSiz= e;=0D - if ((!NeedLoad) && (DataSize !=3D 0) &&=0D - (TotalSize - DataSize > sizeof (CPU_MICROCODE_HEADER) +=0D - sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER)= )) {=0D - ExtendedTableHeader =3D (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT= 8 *) (MicrocodeEntryPoint)=0D - + DataSize + sizeof (CPU_MICROCODE_HEADER));=0D - ExtendedTableCount =3D ExtendedTableHeader->ExtendedSignatureCount;=0D - ExtendedTable =3D (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTabl= eHeader + 1);=0D -=0D - for (Index =3D 0; Index < ExtendedTableCount; Index ++) {=0D - //=0D - // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extende= d=0D - // Signature Table entry with the CPUID and PlatformID of the proces= sors=0D - // within system to decide if it will be copied into memory=0D - //=0D - NeedLoad =3D IsProcessorMatchedMicrocodePatch (=0D - CpuMpData,=0D - ExtendedTable->ProcessorSignature.Uint32,=0D - ExtendedTable->ProcessorFlag=0D - );=0D - if (NeedLoad) {=0D - break;=0D - }=0D - ExtendedTable ++;=0D - }=0D - }=0D -=0D - return NeedLoad;=0D + CpuMpData->CpuData[ProcessorNumber].MicrocodeRevision =3D GetProcessorMi= crocodeSignature ();=0D }=0D =0D -=0D /**=0D Actual worker function that shadows the required microcode patches into = memory.=0D =0D @@ -491,14 +184,16 @@ ShadowMicrocodePatchByPcd ( IN OUT CPU_MP_DATA *CpuMpData=0D )=0D {=0D + UINTN Index;=0D CPU_MICROCODE_HEADER *MicrocodeEntryPoint;=0D UINTN MicrocodeEnd;=0D - UINTN DataSize;=0D UINTN TotalSize;=0D MICROCODE_PATCH_INFO *PatchInfoBuffer;=0D UINTN MaxPatchNumber;=0D UINTN PatchCount;=0D UINTN TotalLoadSize;=0D + EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuIds;=0D + BOOLEAN Valid;=0D =0D //=0D // Initialize the microcode patch related fields in CpuMpData as the val= ues=0D @@ -526,12 +221,34 @@ ShadowMicrocodePatchByPcd ( return;=0D }=0D =0D + MicrocodeCpuIds =3D AllocatePages (=0D + EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * sizeof (EDK= II_PEI_MICROCODE_CPU_ID))=0D + );=0D + if (MicrocodeCpuIds =3D=3D NULL) {=0D + FreePool (PatchInfoBuffer);=0D + return;=0D + }=0D +=0D + for (Index =3D 0; Index < CpuMpData->CpuCount; Index++) {=0D + MicrocodeCpuIds[Index].PlatformId =3D CpuMpData->CpuData[Index= ].PlatformId;=0D + MicrocodeCpuIds[Index].ProcessorSignature =3D CpuMpData->CpuData[Index= ].ProcessorSignature;=0D + }=0D +=0D //=0D // Process the header of each microcode patch within the region.=0D // The purpose is to decide which microcode patch(es) will be loaded int= o memory.=0D + // Microcode checksum is not verified because it's slow when performing = on flash.=0D //=0D do {=0D - if (MicrocodeEntryPoint->HeaderVersion !=3D 0x1) {=0D + Valid =3D IsValidMicrocode (=0D + MicrocodeEntryPoint,=0D + MicrocodeEnd - (UINTN) MicrocodeEntryPoint,=0D + 0,=0D + MicrocodeCpuIds,=0D + CpuMpData->CpuCount,=0D + FALSE=0D + );=0D + if (!Valid) {=0D //=0D // Padding data between the microcode patches, skip 1KB to check nex= t entry.=0D //=0D @@ -539,59 +256,44 @@ ShadowMicrocodePatchByPcd ( continue;=0D }=0D =0D - DataSize =3D MicrocodeEntryPoint->DataSize;=0D - TotalSize =3D (DataSize =3D=3D 0) ? 2048 : MicrocodeEntryPoint->TotalS= ize;=0D - if ( (UINTN)MicrocodeEntryPoint > (MAX_ADDRESS - TotalSize) ||=0D - ((UINTN)MicrocodeEntryPoint + TotalSize) > MicrocodeEnd ||=0D - (DataSize & 0x3) !=3D 0 ||=0D - (TotalSize & (SIZE_1KB - 1)) !=3D 0 ||=0D - TotalSize < DataSize=0D - ) {=0D + PatchCount++;=0D + if (PatchCount > MaxPatchNumber) {=0D //=0D - // Not a valid microcode header, skip 1KB to check next entry.=0D + // Current 'PatchInfoBuffer' cannot hold the information, double the= size=0D + // and allocate a new buffer.=0D //=0D - MicrocodeEntryPoint =3D (CPU_MICROCODE_HEADER *) (((UINTN) Microcode= EntryPoint) + SIZE_1KB);=0D - continue;=0D - }=0D -=0D - if (IsMicrocodePatchNeedLoad (CpuMpData, MicrocodeEntryPoint)) {=0D - PatchCount++;=0D - if (PatchCount > MaxPatchNumber) {=0D + if (MaxPatchNumber > MAX_UINTN / 2 / sizeof (MICROCODE_PATCH_INFO)) = {=0D //=0D - // Current 'PatchInfoBuffer' cannot hold the information, double t= he size=0D - // and allocate a new buffer.=0D + // Overflow check for MaxPatchNumber=0D //=0D - if (MaxPatchNumber > MAX_UINTN / 2 / sizeof (MICROCODE_PATCH_INFO)= ) {=0D - //=0D - // Overflow check for MaxPatchNumber=0D - //=0D - goto OnExit;=0D - }=0D -=0D - PatchInfoBuffer =3D ReallocatePool (=0D - MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO)= ,=0D - 2 * MaxPatchNumber * sizeof (MICROCODE_PATCH_I= NFO),=0D - PatchInfoBuffer=0D - );=0D - if (PatchInfoBuffer =3D=3D NULL) {=0D - goto OnExit;=0D - }=0D - MaxPatchNumber =3D MaxPatchNumber * 2;=0D + goto OnExit;=0D }=0D =0D - //=0D - // Store the information of this microcode patch=0D - //=0D - PatchInfoBuffer[PatchCount - 1].Address =3D (UINTN) MicrocodeEntryPo= int;=0D - PatchInfoBuffer[PatchCount - 1].Size =3D TotalSize;=0D - TotalLoadSize +=3D TotalSize;=0D + PatchInfoBuffer =3D ReallocatePool (=0D + MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),= =0D + 2 * MaxPatchNumber * sizeof (MICROCODE_PATCH_INF= O),=0D + PatchInfoBuffer=0D + );=0D + if (PatchInfoBuffer =3D=3D NULL) {=0D + goto OnExit;=0D + }=0D + MaxPatchNumber =3D MaxPatchNumber * 2;=0D }=0D =0D + TotalSize =3D GetMicrocodeLength (MicrocodeEntryPoint);=0D +=0D + //=0D + // Store the information of this microcode patch=0D + //=0D + PatchInfoBuffer[PatchCount - 1].Address =3D (UINTN) MicrocodeEntryPoin= t;=0D + PatchInfoBuffer[PatchCount - 1].Size =3D TotalSize;=0D + TotalLoadSize +=3D TotalSize;=0D +=0D //=0D // Process the next microcode patch=0D //=0D - MicrocodeEntryPoint =3D (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEn= tryPoint) + TotalSize);=0D - } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));=0D + MicrocodeEntryPoint =3D (CPU_MICROCODE_HEADER *) ((UINTN) MicrocodeEnt= ryPoint + TotalSize);=0D + } while ((UINTN) MicrocodeEntryPoint < MicrocodeEnd);=0D =0D if (PatchCount !=3D 0) {=0D DEBUG ((=0D @@ -607,7 +309,7 @@ OnExit: if (PatchInfoBuffer !=3D NULL) {=0D FreePool (PatchInfoBuffer);=0D }=0D - return;=0D + FreePages (MicrocodeCpuIds, EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * siz= eof (EDKII_PEI_MICROCODE_CPU_ID)));=0D }=0D =0D /**=0D diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpIn= itLib/MpLib.h index 66f9eb2304..e88a5355c9 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -32,6 +32,7 @@ #include =0D #include =0D #include =0D +#include =0D =0D #include =0D =0D diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Lib= rary/MpInitLib/PeiMpInitLib.inf index 49b0ffe8be..36fcb96b58 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf @@ -51,6 +51,7 @@ [LibraryClasses] PeiServicesLib=0D PcdLib=0D VmgExitLib=0D + MicrocodeLib=0D =0D [Pcd]=0D gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONS= UMES=0D --=20 2.27.0.windows.1