From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.65; helo=mga03.intel.com; envelope-from=chen.a.chen@intel.com; receiver=edk2-devel@lists.01.org Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 7C885208EB3EC for ; Mon, 18 Feb 2019 22:32:36 -0800 (PST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 18 Feb 2019 22:32:36 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,387,1544515200"; d="scan'208";a="320145991" Received: from chenche4.ccr.corp.intel.com ([10.239.9.12]) by fmsmga006.fm.intel.com with ESMTP; 18 Feb 2019 22:32:34 -0800 From: Chen A Chen To: edk2-devel@lists.01.org Cc: Chen A Chen , Ray Ni , Eric Dong , Zhang Chao B Date: Tue, 19 Feb 2019 14:32:32 +0800 Message-Id: <20190219063232.17508-1-chen.a.chen@intel.com> X-Mailer: git-send-email 2.16.2.windows.1 Subject: [PATCH] UefiCpuPkg/Microcode: Fix incorrect checksum issue for extended table X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Feb 2019 06:32:37 -0000 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 Cc: Ray Ni Cc: Eric Dong Cc: Zhang Chao B --- UefiCpuPkg/Library/MpInitLib/Microcode.c | 82 ++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 9 deletions(-) diff --git a/UefiCpuPkg/Library/MpInitLib/Microcode.c b/UefiCpuPkg/Library/MpInitLib/Microcode.c index d84344c6f5..e1f661d6b1 100644 --- a/UefiCpuPkg/Library/MpInitLib/Microcode.c +++ b/UefiCpuPkg/Library/MpInitLib/Microcode.c @@ -35,6 +35,42 @@ GetCurrentMicrocodeSignature ( /** 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] IsBspCallIn Indicate whether the caller is BSP or not. **/ @@ -57,6 +93,7 @@ MicrocodeDetect ( UINT32 LatestRevision; UINTN TotalSize; UINT32 CheckSum32; + UINT32 InCompleteCheckSum32; BOOLEAN CorrectMicrocode; VOID *MicrocodeData; MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr; @@ -121,6 +158,25 @@ MicrocodeDetect ( MicrocodeData = NULL; MicrocodeEnd = (UINTN) (CpuMpData->MicrocodePatchAddress + CpuMpData->MicrocodePatchRegionSize); MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) CpuMpData->MicrocodePatchAddress; + + // + // Save an in-complete CheckSum32 from CheckSum Part1 for common parts. + // + if (MicrocodeEntryPoint->DataSize == 0) { + InCompleteCheckSum32 = CalculateSum32 ( + (UINT32 *) MicrocodeEntryPoint, + sizeof (CPU_MICROCODE_HEADER) + 2000 + ); + } else { + InCompleteCheckSum32 = CalculateSum32 ( + (UINT32 *) MicrocodeEntryPoint, + sizeof (CPU_MICROCODE_HEADER) + MicrocodeEntryPoint->DataSize + ); + } + InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorSignature.Uint32; + InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorFlags; + InCompleteCheckSum32 -= MicrocodeEntryPoint->Checksum; + do { // // Check if the microcode is for the Cpu and the version is newer @@ -137,14 +193,13 @@ MicrocodeDetect ( MicrocodeEntryPoint->UpdateRevision > LatestRevision && (MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId)) ) { - if (MicrocodeEntryPoint->DataSize == 0) { - CheckSum32 = CalculateSum32 ((UINT32 *) MicrocodeEntryPoint, 2048); - } else { - CheckSum32 = CalculateSum32 ( - (UINT32 *) MicrocodeEntryPoint, - MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER) - ); - } + // + // Calculate CheckSum Part1. + // + CheckSum32 = InCompleteCheckSum32; + CheckSum32 += MicrocodeEntryPoint->ProcessorSignature.Uint32; + CheckSum32 += MicrocodeEntryPoint->ProcessorFlags; + CheckSum32 += MicrocodeEntryPoint->Checksum; if (CheckSum32 == 0) { CorrectMicrocode = TRUE; ProcessorFlags = MicrocodeEntryPoint->ProcessorFlags; @@ -163,6 +218,9 @@ MicrocodeDetect ( // Calculate Extended Checksum // if ((ExtendedTableLength % 4) == 0) { + // + // Calculate CheckSum Part2. + // CheckSum32 = CalculateSum32 ((UINT32 *) ExtendedTableHeader, ExtendedTableLength); if (CheckSum32 == 0) { // @@ -171,7 +229,13 @@ MicrocodeDetect ( ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount; ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1); for (Index = 0; Index < ExtendedTableCount; Index ++) { - CheckSum32 = CalculateSum32 ((UINT32 *) ExtendedTable, sizeof(CPU_MICROCODE_EXTENDED_TABLE)); + // + // Calculate CheckSum Part3. + // + CheckSum32 = InCompleteCheckSum32; + CheckSum32 += ExtendedTable->ProcessorSignature.Uint32; + CheckSum32 += ExtendedTable->ProcessorFlag; + CheckSum32 += ExtendedTable->Checksum; if (CheckSum32 == 0) { // // Verify Header -- 2.16.2.windows.1