From nobody Sat Apr 27 10:13:58 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 152446660922059.98450614019316; Sun, 22 Apr 2018 23:56:49 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id ED8BA22742ABA; Sun, 22 Apr 2018 23:56:47 -0700 (PDT) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) (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 AB42C21EA15AC for ; Sun, 22 Apr 2018 23:56:46 -0700 (PDT) Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 22 Apr 2018 23:56:45 -0700 Received: from shwdeopenpsi068.ccr.corp.intel.com ([10.239.158.46]) by fmsmga008.fm.intel.com with ESMTP; 22 Apr 2018 23:56:44 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.20; helo=mga02.intel.com; envelope-from=star.zeng@intel.com; receiver=edk2-devel@lists.01.org X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,316,1520924400"; d="scan'208";a="34522139" From: Star Zeng To: edk2-devel@lists.01.org Date: Mon, 23 Apr 2018 14:56:41 +0800 Message-Id: <1524466601-20812-1-git-send-email-star.zeng@intel.com> X-Mailer: git-send-email 2.7.0.windows.1 Subject: [edk2] [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jiewen Yao , Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" It is the second step for https://bugzilla.tianocore.org/show_bug.cgi?id=3D540. Cc: Jiewen Yao Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Star Zeng --- .../Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c | 184 ++++++++++- .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c | 363 +++++++++++++++++= ++-- .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h | 12 +- .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf | 3 +- 4 files changed, 535 insertions(+), 27 deletions(-) diff --git a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFm= p.c b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c index ebde93a91eb3..8276aaa0279b 100644 --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c @@ -272,7 +272,7 @@ FmpSetImage ( } =20 Status =3D MicrocodeWrite(MicrocodeFmpPrivate, (VOID *)Image, ImageSize,= &MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, &MicrocodeFmpPrivate= ->LastAttempt.LastAttemptStatus, AbortReason); - DEBUG((DEBUG_INFO, "SetImage - LastAttemp Version - 0x%x, State - 0x%x\n= ", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate= ->LastAttempt.LastAttemptStatus)); + DEBUG((DEBUG_INFO, "SetImage - LastAttempt Version - 0x%x, Status - 0x%x= \n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPriva= te->LastAttempt.LastAttemptStatus)); VarStatus =3D gRT->SetVariable( MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME, &gEfiCallerIdGuid, @@ -280,7 +280,7 @@ FmpSetImage ( sizeof(MicrocodeFmpPrivate->LastAttempt), &MicrocodeFmpPrivate->LastAttempt ); - DEBUG((DEBUG_INFO, "SetLastAttemp - %r\n", VarStatus)); + DEBUG((DEBUG_INFO, "SetLastAttempt - %r\n", VarStatus)); =20 if (!EFI_ERROR(Status)) { InitializeMicrocodeDescriptor(MicrocodeFmpPrivate); @@ -415,6 +415,159 @@ FmpSetPackageInfo ( } =20 /** + Sort FIT microcode entries based upon MicrocodeEntryPoint, from low to h= igh. + + @param[in] MicrocodeFmpPrivate private data structure to be initialized. + +**/ +VOID +SortFitMicrocodeInfo ( + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate + ) +{ + FIT_MICROCODE_INFO *FitMicrocodeEntry; + FIT_MICROCODE_INFO *NextFitMicrocodeEntry; + FIT_MICROCODE_INFO TempFitMicrocodeEntry; + FIT_MICROCODE_INFO *FitMicrocodeEntryEnd; + + FitMicrocodeEntry =3D MicrocodeFmpPrivate->FitMicrocodeInfo; + NextFitMicrocodeEntry =3D FitMicrocodeEntry + 1; + FitMicrocodeEntryEnd =3D MicrocodeFmpPrivate->FitMicrocodeInfo + Microco= deFmpPrivate->FitMicrocodeEntryCount; + while (FitMicrocodeEntry < FitMicrocodeEntryEnd) { + while (NextFitMicrocodeEntry < FitMicrocodeEntryEnd) { + if (FitMicrocodeEntry->MicrocodeEntryPoint > NextFitMicrocodeEntry->= MicrocodeEntryPoint) { + CopyMem (&TempFitMicrocodeEntry, FitMicrocodeEntry, sizeof (FIT_MI= CROCODE_INFO)); + CopyMem (FitMicrocodeEntry, NextFitMicrocodeEntry, sizeof (FIT_MIC= ROCODE_INFO)); + CopyMem (NextFitMicrocodeEntry, &TempFitMicrocodeEntry, sizeof (FI= T_MICROCODE_INFO)); + } + + NextFitMicrocodeEntry =3D NextFitMicrocodeEntry + 1; + } + + FitMicrocodeEntry =3D FitMicrocodeEntry + 1; + NextFitMicrocodeEntry =3D FitMicrocodeEntry + 1; + } +} + +/** + Initialize FIT microcode information. + + @param[in] MicrocodeFmpPrivate private data structure to be initialized. + +**/ +VOID +InitializeFitMicrocodeInfo ( + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate + ) +{ + UINT64 FitPointer; + FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry; + UINT32 EntryNum; + UINT32 MicrocodeEntryNum; + UINT32 Index; + UINTN Address; + VOID *MicrocodePatchAddress; + UINTN MicrocodePatchRegionSize; + FIT_MICROCODE_INFO *FitMicrocodeInfo; + UINTN FitMicrocodeIndex; + MICROCODE_INFO *MicrocodeInfo; + UINTN MicrocodeIndex; + + if (MicrocodeFmpPrivate->FitMicrocodeInfo !=3D NULL) { + FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo); + MicrocodeFmpPrivate->FitMicrocodeInfo =3D NULL; + MicrocodeFmpPrivate->FitMicrocodeEntryCount =3D 0; + } + + FitPointer =3D *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS; + if ((FitPointer =3D=3D 0) || + (FitPointer =3D=3D 0xFFFFFFFFFFFFFFFF) || + (FitPointer =3D=3D 0xEEEEEEEEEEEEEEEE)) { + // + // No FIT table; + // + return; + } + FitEntry =3D (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer; + if ((FitEntry[0].Type !=3D FIT_TYPE_00_HEADER) || + (FitEntry[0].Address !=3D FIT_TYPE_00_SIGNATURE)) { + // + // Invalid FIT table; + // + return; + } + + EntryNum =3D *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF; + + // + // Calculate microcode entry number. + // + MicrocodeEntryNum =3D 0; + for (Index =3D 0; Index < EntryNum; Index++) { + if (FitEntry[Index].Type =3D=3D FIT_TYPE_01_MICROCODE) { + MicrocodeEntryNum++; + } + } + if (MicrocodeEntryNum =3D=3D 0) { + // + // No FIT microcode entry. + // + return; + } + + MicrocodeFmpPrivate->FitMicrocodeEntryCount =3D MicrocodeEntryNum; + + // + // Allocate buffer. + // + MicrocodeFmpPrivate->FitMicrocodeInfo =3D AllocateZeroPool (MicrocodeEnt= ryNum * sizeof (FIT_MICROCODE_INFO)); + ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo !=3D NULL); + + MicrocodePatchAddress =3D MicrocodeFmpPrivate->MicrocodePatchAddress; + MicrocodePatchRegionSize =3D MicrocodeFmpPrivate->MicrocodePatchRegionSi= ze; + + // + // Collect microcode entry info. + // + MicrocodeEntryNum =3D 0; + for (Index =3D 0; Index < EntryNum; Index++) { + if (FitEntry[Index].Type =3D=3D FIT_TYPE_01_MICROCODE) { + Address =3D (UINTN) FitEntry[Index].Address; + ASSERT ((Address >=3D (UINTN) MicrocodePatchAddress) && + (Address < ((UINTN) MicrocodePatchAddress + MicrocodePatchRe= gionSize))); + FitMicrocodeInfo =3D &MicrocodeFmpPrivate->FitMicrocodeInfo[Microcod= eEntryNum]; + FitMicrocodeInfo->MicrocodeEntryPoint =3D (CPU_MICROCODE_HEADER *) A= ddress; + if ((*(UINT32 *) Address) =3D=3D 0xFFFFFFFF) { + // + // It is the empty slot as long as the first dword is 0xFFFF_FFFF. + // + FitMicrocodeInfo->Empty =3D TRUE; + } else { + FitMicrocodeInfo->Empty =3D FALSE; + } + MicrocodeEntryNum++; + } + } + + // + // Every microcode should have a FIT microcode entry. + // + for (MicrocodeIndex =3D 0; MicrocodeIndex < MicrocodeFmpPrivate->Descrip= torCount; MicrocodeIndex++) { + MicrocodeInfo =3D &MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex]; + for (FitMicrocodeIndex =3D 0; FitMicrocodeIndex < MicrocodeFmpPrivate-= >FitMicrocodeEntryCount; FitMicrocodeIndex++) { + FitMicrocodeInfo =3D &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicro= codeIndex]; + if (MicrocodeInfo->MicrocodeEntryPoint =3D=3D FitMicrocodeInfo->Micr= ocodeEntryPoint) { + FitMicrocodeInfo->InUse =3D MicrocodeInfo->InUse; + break; + } + } + ASSERT (FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCoun= t); + } + + SortFitMicrocodeInfo (MicrocodeFmpPrivate); +} + +/** Initialize Processor Microcode Index. =20 @param[in] MicrocodeFmpPrivate private data structure to be initialized. @@ -496,6 +649,7 @@ InitializeMicrocodeDescriptor ( if (MicrocodeFmpPrivate->MicrocodeInfo =3D=3D NULL) { MicrocodeFmpPrivate->MicrocodeInfo =3D AllocateZeroPool(MicrocodeFmpPr= ivate->DescriptorCount * sizeof(MICROCODE_INFO)); if (MicrocodeFmpPrivate->MicrocodeInfo =3D=3D NULL) { + FreePool (MicrocodeFmpPrivate->ImageDescriptor); return EFI_OUT_OF_RESOURCES; } } @@ -505,6 +659,8 @@ InitializeMicrocodeDescriptor ( =20 InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate); =20 + InitializeFitMicrocodeInfo (MicrocodeFmpPrivate); + return EFI_SUCCESS; } =20 @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor ( =20 @param[in] MicrocodeFmpPrivate private data structure to be initialized. =20 - @return EFI_SUCCESS private data is initialized. + @return EFI_SUCCESS Processor information is initialized. **/ EFI_STATUS InitializeProcessorInfo ( @@ -583,6 +739,7 @@ DumpPrivateInfo ( PROCESSOR_INFO *ProcessorInfo; MICROCODE_INFO *MicrocodeInfo; EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor; + FIT_MICROCODE_INFO *FitMicrocodeInfo; =20 DEBUG ((DEBUG_INFO, "ProcessorInfo:\n")); DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", MicrocodeFmpPrivate->Pr= ocessorCount)); @@ -635,6 +792,22 @@ DumpPrivateInfo ( DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", Imag= eDescriptor[Index].LastAttemptStatus)); DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", Ima= geDescriptor[Index].HardwareInstance)); } + + if (MicrocodeFmpPrivate->FitMicrocodeInfo !=3D NULL) { + DEBUG ((DEBUG_INFO, "FitMicrocodeInfo:\n")); + FitMicrocodeInfo =3D MicrocodeFmpPrivate->FitMicrocodeInfo; + DEBUG ((DEBUG_INFO, " FitMicrocodeEntryCount - 0x%x\n", MicrocodeFmpP= rivate->FitMicrocodeEntryCount)); + for (Index =3D 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount;= Index++) { + DEBUG (( + DEBUG_INFO, + " FitMicrocodeInfo[0x%x] - 0x%08x, (0x%x, 0x%x)\n", + Index, + FitMicrocodeInfo[Index].MicrocodeEntryPoint, + FitMicrocodeInfo[Index].InUse, + FitMicrocodeInfo[Index].Empty + )); + } + } } =20 /** @@ -671,8 +844,8 @@ InitializePrivateData ( &VarSize, &MicrocodeFmpPrivate->LastAttempt ); - DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus)); - DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", Micro= codeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAt= tempt.LastAttemptStatus)); + DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus)); + DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", Micr= ocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastA= ttempt.LastAttemptStatus)); =20 Result =3D GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddres= s, &MicrocodeFmpPrivate->MicrocodePatchRegionSize); if (!Result) { @@ -688,6 +861,7 @@ InitializePrivateData ( =20 Status =3D InitializeMicrocodeDescriptor(MicrocodeFmpPrivate); if (EFI_ERROR(Status)) { + FreePool (MicrocodeFmpPrivate->ProcessorInfo); DEBUG((DEBUG_ERROR, "InitializeMicrocodeDescriptor - %r\n", Status)); return Status; } diff --git a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUp= date.c b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate= .c index 2cb0adbc44d5..9098712c2fc8 100644 --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c @@ -368,7 +368,7 @@ GetMatchedProcessor ( On output, the index of target CP= U which matches the Microcode. =20 @retval EFI_SUCCESS The Microcode image passes verificatio= n. - @retval EFI_VOLUME_CORRUPTED The Microcode image is corrupt. + @retval EFI_VOLUME_CORRUPTED The Microcode image is corrupted. @retval EFI_INCOMPATIBLE_VERSION The Microcode image version is incorre= ct. @retval EFI_UNSUPPORTED The Microcode ProcessorSignature or Pr= ocessorFlags is incorrect. @retval EFI_SECURITY_VIOLATION The Microcode image fails to load. @@ -550,7 +550,7 @@ VerifyMicrocode ( } *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION; if (AbortReason !=3D NULL) { - *AbortReason =3D AllocateCopyPool(sizeof(L"UnsupportedProcessSigna= ture/ProcessorFlags"), L"UnsupportedProcessSignature/ProcessorFlags"); + *AbortReason =3D AllocateCopyPool(sizeof(L"UnsupportedProcessorSig= nature/ProcessorFlags"), L"UnsupportedProcessorSignature/ProcessorFlags"); } return EFI_UNSUPPORTED; } @@ -623,6 +623,124 @@ GetNextMicrocode ( } =20 /** + Get next FIT Microcode entrypoint. + + @param[in] MicrocodeFmpPrivate The Microcode driver private data + @param[in] MicrocodeEntryPoint Current Microcode entrypoint + + @return next FIT Microcode entrypoint. +**/ +CPU_MICROCODE_HEADER * +GetNextFitMicrocode ( + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate, + IN CPU_MICROCODE_HEADER *MicrocodeEntryPoint + ) +{ + UINTN Index; + + for (Index =3D 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; I= ndex++) { + if (MicrocodeEntryPoint =3D=3D MicrocodeFmpPrivate->FitMicrocodeInfo[I= ndex].MicrocodeEntryPoint) { + if (Index =3D=3D (UINTN) MicrocodeFmpPrivate->FitMicrocodeEntryCount= - 1) { + // it is last one + return NULL; + } else { + // return next one + return MicrocodeFmpPrivate->FitMicrocodeInfo[Index + 1].MicrocodeE= ntryPoint; + } + } + } + + ASSERT(FALSE); + return NULL; +} + +/** + Find empty FIT Microcode entrypoint. + + @param[in] MicrocodeFmpPrivate The Microcode driver private data + @param[in] ImageSize The size of Microcode image buffe= r in bytes. + @param[out] AvailableSize Available size of the empty FIT M= icrocode entrypoint. + + @return Empty FIT Microcode entrypoint. +**/ +CPU_MICROCODE_HEADER * +FindEmptyFitMicrocode ( + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate, + IN UINTN ImageSize, + OUT UINTN *AvailableSize + ) +{ + UINTN Index; + CPU_MICROCODE_HEADER *MicrocodeEntryPoint; + CPU_MICROCODE_HEADER *NextMicrocodeEntryPoint; + VOID *MicrocodePatchAddress; + UINTN MicrocodePatchRegionSize; + + MicrocodePatchAddress =3D MicrocodeFmpPrivate->MicrocodePatchAddress; + MicrocodePatchRegionSize =3D MicrocodeFmpPrivate->MicrocodePatchRegionSi= ze; + + for (Index =3D 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; I= ndex++) { + if (MicrocodeFmpPrivate->FitMicrocodeInfo[Index].Empty) { + MicrocodeEntryPoint =3D MicrocodeFmpPrivate->FitMicrocodeInfo[Index]= .MicrocodeEntryPoint; + NextMicrocodeEntryPoint =3D GetNextFitMicrocode (MicrocodeFmpPrivate= , MicrocodeEntryPoint); + if (NextMicrocodeEntryPoint !=3D NULL) { + *AvailableSize =3D (UINTN) NextMicrocodeEntryPoint - (UINTN) Micro= codeEntryPoint; + } else { + *AvailableSize =3D (UINTN) MicrocodePatchAddress + MicrocodePatchR= egionSize - (UINTN) MicrocodeEntryPoint; + } + if (*AvailableSize >=3D ImageSize) { + return MicrocodeEntryPoint; + } + } + } + + return NULL; +} + +/** + Find unused FIT Microcode entrypoint. + + @param[in] MicrocodeFmpPrivate The Microcode driver private data + @param[in] ImageSize The size of Microcode image buffe= r in bytes. + @param[out] AvailableSize Available size of the unused FIT = Microcode entrypoint. + + @return Unused FIT Microcode entrypoint. +**/ +CPU_MICROCODE_HEADER * +FindUnusedFitMicrocode ( + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate, + IN UINTN ImageSize, + OUT UINTN *AvailableSize + ) +{ + UINTN Index; + CPU_MICROCODE_HEADER *MicrocodeEntryPoint; + CPU_MICROCODE_HEADER *NextMicrocodeEntryPoint; + VOID *MicrocodePatchAddress; + UINTN MicrocodePatchRegionSize; + + MicrocodePatchAddress =3D MicrocodeFmpPrivate->MicrocodePatchAddress; + MicrocodePatchRegionSize =3D MicrocodeFmpPrivate->MicrocodePatchRegionSi= ze; + + for (Index =3D 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; I= ndex++) { + if (!MicrocodeFmpPrivate->FitMicrocodeInfo[Index].InUse) { + MicrocodeEntryPoint =3D MicrocodeFmpPrivate->FitMicrocodeInfo[Index]= .MicrocodeEntryPoint; + NextMicrocodeEntryPoint =3D GetNextFitMicrocode (MicrocodeFmpPrivate= , MicrocodeEntryPoint); + if (NextMicrocodeEntryPoint !=3D NULL) { + *AvailableSize =3D (UINTN) NextMicrocodeEntryPoint - (UINTN) Micro= codeEntryPoint; + } else { + *AvailableSize =3D (UINTN) MicrocodePatchAddress + MicrocodePatchR= egionSize - (UINTN) MicrocodeEntryPoint; + } + if (*AvailableSize >=3D ImageSize) { + return MicrocodeEntryPoint; + } + } + } + + return NULL; +} + +/** Get current Microcode used region size. =20 @param[in] MicrocodeFmpPrivate The Microcode driver private data @@ -666,7 +784,7 @@ UpdateMicrocode ( =20 DEBUG((DEBUG_INFO, "PlatformUpdate:")); DEBUG((DEBUG_INFO, " Address - 0x%lx,", Address)); - DEBUG((DEBUG_INFO, " Legnth - 0x%x\n", ImageSize)); + DEBUG((DEBUG_INFO, " Length - 0x%x\n", ImageSize)); =20 Status =3D MicrocodeFlashWrite ( Address, @@ -682,6 +800,201 @@ UpdateMicrocode ( } =20 /** + Update Microcode flash region with FIT. + + @param[in] MicrocodeFmpPrivate The Microcode driver private data + @param[in] TargetMicrocodeEntryPoint Target Microcode entrypoint to be= updated + @param[in] Image The Microcode image buffer. + @param[in] ImageSize The size of Microcode image buffe= r in bytes. + @param[out] LastAttemptStatus The last attempt status, which wi= ll be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + + @retval EFI_SUCCESS The Microcode image is written. + @retval EFI_WRITE_PROTECTED The flash device is read only. +**/ +EFI_STATUS +UpdateMicrocodeFlashRegionWithFit ( + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate, + IN CPU_MICROCODE_HEADER *TargetMicrocodeEntryPoint, + IN VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *LastAttemptStatus + ) +{ + VOID *MicrocodePatchAddress; + UINTN MicrocodePatchRegionSize; + UINTN TargetTotalSize; + EFI_STATUS Status; + VOID *MicrocodePatchScratchBuffer; + UINT8 *ScratchBufferPtr; + UINTN ScratchBufferSize; + UINTN RestSize; + UINTN AvailableSize; + VOID *NextMicrocodeEntryPoint; + VOID *EmptyFitMicrocodeEntry; + VOID *UnusedFitMicrocodeEntry; + + DEBUG((DEBUG_INFO, "UpdateMicrocodeFlashRegionWithFit: Image - 0x%x, siz= e - 0x%x\n", Image, ImageSize)); + + MicrocodePatchAddress =3D MicrocodeFmpPrivate->MicrocodePatchAddress; + MicrocodePatchRegionSize =3D MicrocodeFmpPrivate->MicrocodePatchRegionSi= ze; + + MicrocodePatchScratchBuffer =3D AllocateZeroPool (MicrocodePatchRegionSi= ze); + if (MicrocodePatchScratchBuffer =3D=3D NULL) { + DEBUG((DEBUG_ERROR, "Fail to allocate Microcode Scratch buffer\n")); + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCE= S; + return EFI_OUT_OF_RESOURCES; + } + ScratchBufferPtr =3D MicrocodePatchScratchBuffer; + ScratchBufferSize =3D 0; + + // + // Target data collection + // + TargetTotalSize =3D 0; + AvailableSize =3D 0; + if (TargetMicrocodeEntryPoint !=3D NULL) { + if (TargetMicrocodeEntryPoint->DataSize =3D=3D 0) { + TargetTotalSize =3D 2048; + } else { + TargetTotalSize =3D TargetMicrocodeEntryPoint->TotalSize; + } + DEBUG((DEBUG_INFO, " TargetTotalSize - 0x%x\n", TargetTotalSize)); + NextMicrocodeEntryPoint =3D GetNextFitMicrocode (MicrocodeFmpPrivate, = TargetMicrocodeEntryPoint); + DEBUG((DEBUG_INFO, " NextMicrocodeEntryPoint - 0x%x\n", NextMicrocode= EntryPoint)); + if (NextMicrocodeEntryPoint !=3D NULL) { + ASSERT ((UINTN) NextMicrocodeEntryPoint >=3D ((UINTN) TargetMicrocod= eEntryPoint + TargetTotalSize)); + AvailableSize =3D (UINTN) NextMicrocodeEntryPoint - (UINTN) TargetMi= crocodeEntryPoint; + } else { + AvailableSize =3D (UINTN) MicrocodePatchAddress + MicrocodePatchRegi= onSize - (UINTN) TargetMicrocodeEntryPoint; + } + DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize)); + ASSERT (AvailableSize >=3D TargetTotalSize); + } + // + // Total Size means the Microcode size. + // Available Size means the Microcode size plus the pad till (1) next Mi= crocode or (2) the end. + // + // (1) + // +------+-----------+-----+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ + // | MCU1 | Microcode | PAD | MCU2 | Empty | + // +------+-----------+-----+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ + // | TotalSize | + // |<-AvailableSize->| + // + // (2) + // +------+-----------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D+ + // | MCU | Microcode | Empty | + // +------+-----------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D+ + // | TotalSize | + // |<- AvailableSize ->| + // + + // + // Update based on policy + // + + // + // 1. If there is enough space to update old one in situ, replace old mi= crocode in situ. + // + if (AvailableSize >=3D ImageSize) { + DEBUG((DEBUG_INFO, "Replace old microcode in situ\n")); + // + // +------+------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ + // |Other | Old Image | ... | Empty | + // +------+------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ + // + // +------+---------+--+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ + // |Other |New Image|FF| ... | Empty | + // +------+---------+--+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ + // + // 1.1. Copy new image + CopyMem (ScratchBufferPtr, Image, ImageSize); + ScratchBufferSize +=3D ImageSize; + ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + ScratchBuf= ferSize; + // 1.2. Pad 0xFF + RestSize =3D AvailableSize - ImageSize; + if (RestSize > 0) { + SetMem (ScratchBufferPtr, RestSize, 0xFF); + ScratchBufferSize +=3D RestSize; + ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + ScratchB= ufferSize; + } + Status =3D UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint, Microcode= PatchScratchBuffer, ScratchBufferSize, LastAttemptStatus); + return Status; + } + + // + // 2. If there is empty FIT microcode entry with enough space, use it. + // + EmptyFitMicrocodeEntry =3D FindEmptyFitMicrocode (MicrocodeFmpPrivate, I= mageSize, &AvailableSize); + if (EmptyFitMicrocodeEntry !=3D NULL) { + DEBUG((DEBUG_INFO, "Use empty FIT microcode entry\n")); + // 2.1. Copy new image + CopyMem (ScratchBufferPtr, Image, ImageSize); + ScratchBufferSize +=3D ImageSize; + ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + ScratchBuf= ferSize; + // 2.2. Pad 0xFF + RestSize =3D AvailableSize - ImageSize; + if (RestSize > 0) { + SetMem (ScratchBufferPtr, RestSize, 0xFF); + ScratchBufferSize +=3D RestSize; + ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + ScratchB= ufferSize; + } + Status =3D UpdateMicrocode ((UINTN) EmptyFitMicrocodeEntry, MicrocodeP= atchScratchBuffer, ScratchBufferSize, LastAttemptStatus); + if (!EFI_ERROR (Status) && (TargetMicrocodeEntryPoint !=3D NULL)) { + // + // Empty old microcode. + // + ScratchBufferPtr =3D MicrocodePatchScratchBuffer; + SetMem (ScratchBufferPtr, TargetTotalSize, 0xFF); + ScratchBufferSize =3D TargetTotalSize; + ScratchBufferPtr =3D (UINT8 *) MicrocodePatchScratchBuffer + Scratch= BufferSize; + UpdateMicrocode ((UINTN) TargetMicrocodeEntryPoint, MicrocodePatchSc= ratchBuffer, ScratchBufferSize, LastAttemptStatus); + } + return Status; + } + + // + // 3. If there is unused microcode entry with enough space, use it. + // + UnusedFitMicrocodeEntry =3D FindUnusedFitMicrocode (MicrocodeFmpPrivate,= ImageSize, &AvailableSize); + if (UnusedFitMicrocodeEntry !=3D NULL) { + DEBUG((DEBUG_INFO, "Use unused FIT microcode entry\n")); + // 3.1. Copy new image + CopyMem (ScratchBufferPtr, Image, ImageSize); + ScratchBufferSize +=3D ImageSize; + ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + ScratchBuf= ferSize; + // 3.2. Pad 0xFF + RestSize =3D AvailableSize - ImageSize; + if (RestSize > 0) { + SetMem (ScratchBufferPtr, RestSize, 0xFF); + ScratchBufferSize +=3D RestSize; + ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + ScratchB= ufferSize; + } + Status =3D UpdateMicrocode ((UINTN) UnusedFitMicrocodeEntry, Microcode= PatchScratchBuffer, ScratchBufferSize, LastAttemptStatus); + if (!EFI_ERROR (Status) && (TargetMicrocodeEntryPoint !=3D NULL)) { + // + // Empty old microcode. + // + ScratchBufferPtr =3D MicrocodePatchScratchBuffer; + SetMem (ScratchBufferPtr, TargetTotalSize, 0xFF); + ScratchBufferSize =3D TargetTotalSize; + ScratchBufferPtr =3D (UINT8 *) MicrocodePatchScratchBuffer + Scratch= BufferSize; + UpdateMicrocode ((UINTN) TargetMicrocodeEntryPoint, MicrocodePatchSc= ratchBuffer, ScratchBufferSize, LastAttemptStatus); + } + return Status; + } + + // + // 4. No usable FIT microcode entry. + // + DEBUG((DEBUG_ERROR, "No usable FIT microcode entry\n")); + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES; + Status =3D EFI_OUT_OF_RESOURCES; + + return Status; +} + +/** Update Microcode flash region. =20 @param[in] MicrocodeFmpPrivate The Microcode driver private data @@ -753,8 +1066,8 @@ UpdateMicrocodeFlashRegion ( AvailableSize =3D (UINTN)MicrocodePatchAddress + MicrocodePatchRegio= nSize - (UINTN)TargetMicrocodeEntryPoint; } DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize)); + ASSERT (AvailableSize >=3D TargetTotalSize); } - ASSERT (AvailableSize >=3D TargetTotalSize); UsedRegionSize =3D GetCurrentMicrocodeUsedRegionSize(MicrocodeFmpPrivate= ); DEBUG((DEBUG_INFO, " UsedRegionSize - 0x%x\n", UsedRegionSize)); ASSERT (UsedRegionSize >=3D TargetTotalSize); @@ -762,8 +1075,8 @@ UpdateMicrocodeFlashRegion ( ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >=3D ((UINTN)Tar= getMicrocodeEntryPoint + TargetTotalSize)); } // - // Total Size means the Microcode data size. - // Available Size means the Microcode data size plus the pad till (1) ne= xt Microcode or (2) the end. + // Total Size means the Microcode size. + // Available Size means the Microcode size plus the pad till (1) next Mi= crocode or (2) the end. // // (1) // +------+-----------+-----+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ @@ -793,11 +1106,11 @@ UpdateMicrocodeFlashRegion ( DEBUG((DEBUG_INFO, "Replace old microcode in situ\n")); // // +------+------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ - // |Other1| Old Image |Other2| Empty | + // |Other | Old Image | ... | Empty | // +------+------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ // // +------+---------+--+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ - // |Other1|New Image|FF|Other2| Empty | + // |Other |New Image|FF| ... | Empty | // +------+---------+--+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ // // 1.1. Copy new image @@ -835,11 +1148,11 @@ UpdateMicrocodeFlashRegion ( DEBUG((DEBUG_INFO, "Reorg and replace old microcode\n")); // // +------+------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ - // |Other1| Old Image |Other2| Empty | + // |Other | Old Image | ... | Empty | // +------+------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ // // +------+---------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D+ - // |Other1| New Image |Other2| Empty | + // |Other | New Image | ... | Empty | // +------+---------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D+ // // 2.1. Copy new image @@ -849,7 +1162,7 @@ UpdateMicrocodeFlashRegion ( // 2.2. Copy rest images after the old image. if (NextMicrocodeEntryPoint !=3D 0) { RestSize =3D (UINTN)MicrocodePatchAddress + UsedRegionSize - ((UIN= TN)NextMicrocodeEntryPoint); - CopyMem (ScratchBufferPtr, (UINT8 *)TargetMicrocodeEntryPoint + Ta= rgetTotalSize, RestSize); + CopyMem (ScratchBufferPtr, NextMicrocodeEntryPoint, RestSize); ScratchBufferSize +=3D RestSize; ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + Scratc= hBufferSize; } @@ -932,7 +1245,7 @@ UpdateMicrocodeFlashRegion ( call to FreePool(). =20 @retval EFI_SUCCESS The Microcode image is written. - @retval EFI_VOLUME_CORRUPTED The Microcode image is corrupt. + @retval EFI_VOLUME_CORRUPTED The Microcode image is corrupted. @retval EFI_INCOMPATIBLE_VERSION The Microcode image version is incorre= ct. @retval EFI_SECURITY_VIOLATION The Microcode image fails to load. @retval EFI_WRITE_PROTECTED The flash device is read only. @@ -963,7 +1276,6 @@ MicrocodeWrite ( return EFI_OUT_OF_RESOURCES; } =20 - *LastAttemptVersion =3D ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision; TargetCpuIndex =3D (UINTN)-1; Status =3D VerifyMicrocode(MicrocodeFmpPrivate, AlignedImage, ImageSize,= TRUE, LastAttemptStatus, AbortReason, &TargetCpuIndex); if (EFI_ERROR(Status)) { @@ -972,6 +1284,7 @@ MicrocodeWrite ( return Status; } DEBUG((DEBUG_INFO, "Pass VerifyMicrocode\n")); + *LastAttemptVersion =3D ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision; =20 DEBUG((DEBUG_INFO, " TargetCpuIndex - 0x%x\n", TargetCpuIndex)); ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount); @@ -985,13 +1298,23 @@ MicrocodeWrite ( } DEBUG((DEBUG_INFO, " TargetMicrocodeEntryPoint - 0x%x\n", TargetMicroco= deEntryPoint)); =20 - Status =3D UpdateMicrocodeFlashRegion( - MicrocodeFmpPrivate, - TargetMicrocodeEntryPoint, - AlignedImage, - ImageSize, - LastAttemptStatus - ); + if (MicrocodeFmpPrivate->FitMicrocodeInfo !=3D NULL) { + Status =3D UpdateMicrocodeFlashRegionWithFit ( + MicrocodeFmpPrivate, + TargetMicrocodeEntryPoint, + AlignedImage, + ImageSize, + LastAttemptStatus + ); + } else { + Status =3D UpdateMicrocodeFlashRegion ( + MicrocodeFmpPrivate, + TargetMicrocodeEntryPoint, + AlignedImage, + ImageSize, + LastAttemptStatus + ); + } =20 FreePool(AlignedImage); =20 diff --git a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUp= date.h b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate= .h index 9dc306324e62..d16b353eefa2 100644 --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h @@ -20,6 +20,8 @@ #include #include =20 +#include + #include #include =20 @@ -58,6 +60,12 @@ typedef struct { } MICROCODE_INFO; =20 typedef struct { + CPU_MICROCODE_HEADER *MicrocodeEntryPoint; + BOOLEAN Empty; + BOOLEAN InUse; +} FIT_MICROCODE_INFO; + +typedef struct { UINTN CpuIndex; UINT32 ProcessorSignature; UINT8 PlatformId; @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA { UINTN BspIndex; UINTN ProcessorCount; PROCESSOR_INFO *ProcessorInfo; + UINT32 FitMicrocodeEntryCount; + FIT_MICROCODE_INFO *FitMicrocodeInfo; }; =20 typedef struct _MICROCODE_FMP_PRIVATE_DATA MICROCODE_FMP_PRIVATE_DATA; =20 -#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME L"MicrocodeLastAttempVar" +#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME L"MicrocodeLastAttemptVa= r" =20 /** Returns a pointer to the MICROCODE_FMP_PRIVATE_DATA structure from the i= nput a as Fmp. diff --git a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUp= dateDxe.inf b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeU= pdateDxe.inf index dbc90857a0a5..24f06c23d404 100644 --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe= .inf +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe= .inf @@ -3,7 +3,7 @@ # # Produce FMP instance to update Microcode. # -# Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
# This program and the accompanying materials # are licensed and made available under the terms and conditions of the B= SD License # which accompanies this distribution. The full text of the license may = be found at @@ -65,6 +65,7 @@ [Pcd] =20 [Depex] gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid AND gEfiMpServiceProtocolGuid =20 [UserExtensions.TianoCore."ExtraFiles"] --=20 2.7.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel