From: "Yao, Jiewen" <jiewen.yao@intel.com>
To: "Zeng, Star" <star.zeng@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Subject: Re: [PATCH V2] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
Date: Fri, 4 May 2018 06:05:36 +0000 [thread overview]
Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503AB8D821@shsmsx102.ccr.corp.intel.com> (raw)
In-Reply-To: <1524817211-46772-1-git-send-email-star.zeng@intel.com>
Reviewed-by: Jiewen.yao@intel.com
> -----Original Message-----
> From: Zeng, Star
> Sent: Friday, April 27, 2018 1:20 AM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
> Subject: [PATCH V2] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
>
> It is the second step for
> https://bugzilla.tianocore.org/show_bug.cgi?id=540.
>
> V2: Use error handling instead of ASSERT for FIT table checking result.
>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Star Zeng <star.zeng@intel.com>
> ---
> .../Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c | 251
> +++++++++++++-
> .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c | 363
> +++++++++++++++++++--
> .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h | 13 +-
> .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf | 3 +-
> 4 files changed, 601 insertions(+), 29 deletions(-)
>
> diff --git
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> index ef5e630caf01..bc1387b3dddd 100644
> --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> @@ -272,7 +272,7 @@ FmpSetImage (
> }
>
> Status = 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,
> MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));
> VarStatus = 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));
>
> if (!EFI_ERROR(Status)) {
> InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
> @@ -415,6 +415,212 @@ FmpSetPackageInfo (
> }
>
> /**
> + Sort FIT microcode entries based upon MicrocodeEntryPoint, from low to
> high.
> +
> + @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 = MicrocodeFmpPrivate->FitMicrocodeInfo;
> + NextFitMicrocodeEntry = FitMicrocodeEntry + 1;
> + FitMicrocodeEntryEnd = MicrocodeFmpPrivate->FitMicrocodeInfo +
> MicrocodeFmpPrivate->FitMicrocodeEntryCount;
> + while (FitMicrocodeEntry < FitMicrocodeEntryEnd) {
> + while (NextFitMicrocodeEntry < FitMicrocodeEntryEnd) {
> + if (FitMicrocodeEntry->MicrocodeEntryPoint >
> NextFitMicrocodeEntry->MicrocodeEntryPoint) {
> + CopyMem (&TempFitMicrocodeEntry, FitMicrocodeEntry, sizeof
> (FIT_MICROCODE_INFO));
> + CopyMem (FitMicrocodeEntry, NextFitMicrocodeEntry, sizeof
> (FIT_MICROCODE_INFO));
> + CopyMem (NextFitMicrocodeEntry, &TempFitMicrocodeEntry, sizeof
> (FIT_MICROCODE_INFO));
> + }
> +
> + NextFitMicrocodeEntry = NextFitMicrocodeEntry + 1;
> + }
> +
> + FitMicrocodeEntry = FitMicrocodeEntry + 1;
> + NextFitMicrocodeEntry = FitMicrocodeEntry + 1;
> + }
> +}
> +
> +/**
> + Initialize FIT microcode information.
> +
> + @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> +
> + @return EFI_SUCCESS FIT microcode information is initialized.
> + @return EFI_OUT_OF_RESOURCES No enough resource for the
> initialization.
> + @return EFI_DEVICE_ERROR There is something wrong in FIT
> microcode entry.
> +**/
> +EFI_STATUS
> +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;
> + FIT_MICROCODE_INFO *FitMicrocodeInfoNext;
> + CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
> + CPU_MICROCODE_HEADER *MicrocodeEntryPointNext;
> + UINTN FitMicrocodeIndex;
> + MICROCODE_INFO *MicrocodeInfo;
> + UINTN MicrocodeIndex;
> +
> + if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
> + FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);
> + MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;
> + MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;
> + }
> +
> + FitPointer = *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS;
> + if ((FitPointer == 0) ||
> + (FitPointer == 0xFFFFFFFFFFFFFFFF) ||
> + (FitPointer == 0xEEEEEEEEEEEEEEEE)) {
> + //
> + // No FIT table.
> + //
> + return EFI_SUCCESS;
> + }
> + FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;
> + if ((FitEntry[0].Type != FIT_TYPE_00_HEADER) ||
> + (FitEntry[0].Address != FIT_TYPE_00_SIGNATURE)) {
> + //
> + // Invalid FIT table, treat it as no FIT table.
> + //
> + return EFI_SUCCESS;
> + }
> +
> + EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
> +
> + //
> + // Calculate microcode entry number.
> + //
> + MicrocodeEntryNum = 0;
> + for (Index = 0; Index < EntryNum; Index++) {
> + if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
> + MicrocodeEntryNum++;
> + }
> + }
> + if (MicrocodeEntryNum == 0) {
> + //
> + // No FIT microcode entry.
> + //
> + return EFI_SUCCESS;
> + }
> +
> + //
> + // Allocate buffer.
> + //
> + MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool
> (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));
> + if (MicrocodeFmpPrivate->FitMicrocodeInfo == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;
> +
> + MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;
> + MicrocodePatchRegionSize =
> MicrocodeFmpPrivate->MicrocodePatchRegionSize;
> +
> + //
> + // Collect microcode entry info.
> + //
> + MicrocodeEntryNum = 0;
> + for (Index = 0; Index < EntryNum; Index++) {
> + if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
> + Address = (UINTN) FitEntry[Index].Address;
> + if ((Address < (UINTN) MicrocodePatchAddress) ||
> + (Address >= ((UINTN) MicrocodePatchAddress +
> MicrocodePatchRegionSize))) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "InitializeFitMicrocodeInfo - Address (0x%x) is not in Microcode
> Region\n",
> + Address
> + ));
> + goto ErrorExit;
> + }
> + FitMicrocodeInfo =
> &MicrocodeFmpPrivate->FitMicrocodeInfo[MicrocodeEntryNum];
> + FitMicrocodeInfo->MicrocodeEntryPoint = (CPU_MICROCODE_HEADER
> *) Address;
> + if ((*(UINT32 *) Address) == 0xFFFFFFFF) {
> + //
> + // It is the empty slot as long as the first dword is 0xFFFF_FFFF.
> + //
> + FitMicrocodeInfo->Empty = TRUE;
> + } else {
> + FitMicrocodeInfo->Empty = FALSE;
> + }
> + MicrocodeEntryNum++;
> + }
> + }
> +
> + //
> + // Every microcode should have a FIT microcode entry.
> + //
> + for (MicrocodeIndex = 0; MicrocodeIndex <
> MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) {
> + MicrocodeInfo =
> &MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex];
> + for (FitMicrocodeIndex = 0; FitMicrocodeIndex <
> MicrocodeFmpPrivate->FitMicrocodeEntryCount; FitMicrocodeIndex++) {
> + FitMicrocodeInfo =
> &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];
> + if (MicrocodeInfo->MicrocodeEntryPoint ==
> FitMicrocodeInfo->MicrocodeEntryPoint) {
> + FitMicrocodeInfo->TotalSize = MicrocodeInfo->TotalSize;
> + FitMicrocodeInfo->InUse = MicrocodeInfo->InUse;
> + break;
> + }
> + }
> + if (FitMicrocodeIndex >= MicrocodeFmpPrivate->FitMicrocodeEntryCount)
> {
> + DEBUG ((
> + DEBUG_ERROR,
> + "InitializeFitMicrocodeInfo - There is no FIT microcode entry for
> Microcode (0x%x)\n",
> + MicrocodeInfo->MicrocodeEntryPoint
> + ));
> + goto ErrorExit;
> + }
> + }
> +
> + SortFitMicrocodeInfo (MicrocodeFmpPrivate);
> +
> + //
> + // Check overlap.
> + //
> + for (FitMicrocodeIndex = 0; FitMicrocodeIndex <
> MicrocodeFmpPrivate->FitMicrocodeEntryCount - 1; FitMicrocodeIndex++) {
> + FitMicrocodeInfo =
> &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];
> + MicrocodeEntryPoint = FitMicrocodeInfo->MicrocodeEntryPoint;
> + FitMicrocodeInfoNext =
> &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex + 1];
> + MicrocodeEntryPointNext = FitMicrocodeInfoNext->MicrocodeEntryPoint;
> + if ((MicrocodeEntryPoint >= MicrocodeEntryPointNext) ||
> + ((FitMicrocodeInfo->TotalSize != 0) &&
> + ((UINTN) MicrocodeEntryPoint + FitMicrocodeInfo->TotalSize) >
> + (UINTN) MicrocodeEntryPointNext)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "InitializeFitMicrocodeInfo - There is overlap between FIT microcode
> entries (0x%x 0x%x)\n",
> + MicrocodeEntryPoint,
> + MicrocodeEntryPointNext
> + ));
> + goto ErrorExit;
> + }
> + }
> +
> + return EFI_SUCCESS;
> +
> +ErrorExit:
> + FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);
> + MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;
> + MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;
> + return EFI_DEVICE_ERROR;
> +}
> +
> +/**
> Initialize Processor Microcode Index.
>
> @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> @@ -460,14 +666,16 @@ InitializedProcessorMicrocodeIndex (
>
> @param[in] MicrocodeFmpPrivate private data structure to be initialized.
>
> - @return EFI_SUCCESS Microcode Descriptor is initialized.
> + @return EFI_SUCCESS Microcode Descriptor is initialized.
> + @return EFI_OUT_OF_RESOURCES No enough resource for the
> initialization.
> **/
> EFI_STATUS
> InitializeMicrocodeDescriptor (
> IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
> )
> {
> - UINT8 CurrentMicrocodeCount;
> + EFI_STATUS Status;
> + UINT8 CurrentMicrocodeCount;
>
> CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate,
> 0, NULL, NULL);
>
> @@ -496,6 +704,7 @@ InitializeMicrocodeDescriptor (
> if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {
> MicrocodeFmpPrivate->MicrocodeInfo =
> AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount *
> sizeof(MICROCODE_INFO));
> if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {
> + FreePool (MicrocodeFmpPrivate->ImageDescriptor);
> return EFI_OUT_OF_RESOURCES;
> }
> }
> @@ -505,6 +714,14 @@ InitializeMicrocodeDescriptor (
>
> InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
>
> + Status = InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);
> + if (EFI_ERROR(Status)) {
> + FreePool (MicrocodeFmpPrivate->ImageDescriptor);
> + FreePool (MicrocodeFmpPrivate->MicrocodeInfo);
> + DEBUG((DEBUG_ERROR, "InitializeFitMicrocodeInfo - %r\n", Status));
> + return Status;
> + }
> +
> return EFI_SUCCESS;
> }
>
> @@ -513,7 +730,8 @@ InitializeMicrocodeDescriptor (
>
> @param[in] MicrocodeFmpPrivate private data structure to be initialized.
>
> - @return EFI_SUCCESS private data is initialized.
> + @return EFI_SUCCESS Processor information is initialized.
> + @return EFI_OUT_OF_RESOURCES No enough resource for the
> initialization.
> **/
> EFI_STATUS
> InitializeProcessorInfo (
> @@ -583,6 +801,7 @@ DumpPrivateInfo (
> PROCESSOR_INFO *ProcessorInfo;
> MICROCODE_INFO *MicrocodeInfo;
> EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
> + FIT_MICROCODE_INFO *FitMicrocodeInfo;
>
> DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
> DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n",
> MicrocodeFmpPrivate->ProcessorCount));
> @@ -635,6 +854,23 @@ DumpPrivateInfo (
> DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n",
> ImageDescriptor[Index].LastAttemptStatus));
> DEBUG((DEBUG_VERBOSE, " HardwareInstance -
> 0x%lx\n", ImageDescriptor[Index].HardwareInstance));
> }
> +
> + if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
> + DEBUG ((DEBUG_INFO, "FitMicrocodeInfo:\n"));
> + FitMicrocodeInfo = MicrocodeFmpPrivate->FitMicrocodeInfo;
> + DEBUG ((DEBUG_INFO, " FitMicrocodeEntryCount - 0x%x\n",
> MicrocodeFmpPrivate->FitMicrocodeEntryCount));
> + for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount;
> Index++) {
> + DEBUG ((
> + DEBUG_INFO,
> + " FitMicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x, 0x%x)\n",
> + Index,
> + FitMicrocodeInfo[Index].MicrocodeEntryPoint,
> + FitMicrocodeInfo[Index].TotalSize,
> + FitMicrocodeInfo[Index].InUse,
> + FitMicrocodeInfo[Index].Empty
> + ));
> + }
> + }
> }
>
> /**
> @@ -671,8 +907,8 @@ InitializePrivateData (
> &VarSize,
> &MicrocodeFmpPrivate->LastAttempt
> );
> - DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus));
> - DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n",
> MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion,
> MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));
> + DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus));
> + DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n",
> MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion,
> MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));
>
> Result =
> GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress,
> &MicrocodeFmpPrivate->MicrocodePatchRegionSize);
> if (!Result) {
> @@ -688,6 +924,7 @@ InitializePrivateData (
>
> Status = 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/MicrocodeUpdate.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
> CPU which matches the Microcode.
>
> @retval EFI_SUCCESS The Microcode image passes
> verification.
> - @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
> incorrect.
> @retval EFI_UNSUPPORTED The Microcode ProcessorSignature
> or ProcessorFlags is incorrect.
> @retval EFI_SECURITY_VIOLATION The Microcode image fails to load.
> @@ -550,7 +550,7 @@ VerifyMicrocode (
> }
> *LastAttemptStatus =
> LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
> if (AbortReason != NULL) {
> - *AbortReason =
> AllocateCopyPool(sizeof(L"UnsupportedProcessSignature/ProcessorFlags"),
> L"UnsupportedProcessSignature/ProcessorFlags");
> + *AbortReason =
> AllocateCopyPool(sizeof(L"UnsupportedProcessorSignature/ProcessorFlags"),
> L"UnsupportedProcessorSignature/ProcessorFlags");
> }
> return EFI_UNSUPPORTED;
> }
> @@ -623,6 +623,124 @@ GetNextMicrocode (
> }
>
> /**
> + 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 = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount;
> Index++) {
> + if (MicrocodeEntryPoint ==
> MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint) {
> + if (Index == (UINTN) MicrocodeFmpPrivate->FitMicrocodeEntryCount -
> 1) {
> + // it is last one
> + return NULL;
> + } else {
> + // return next one
> + return MicrocodeFmpPrivate->FitMicrocodeInfo[Index +
> 1].MicrocodeEntryPoint;
> + }
> + }
> + }
> +
> + 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
> buffer in bytes.
> + @param[out] AvailableSize Available size of the empty FIT
> Microcode 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 = MicrocodeFmpPrivate->MicrocodePatchAddress;
> + MicrocodePatchRegionSize =
> MicrocodeFmpPrivate->MicrocodePatchRegionSize;
> +
> + for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount;
> Index++) {
> + if (MicrocodeFmpPrivate->FitMicrocodeInfo[Index].Empty) {
> + MicrocodeEntryPoint =
> MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint;
> + NextMicrocodeEntryPoint = GetNextFitMicrocode
> (MicrocodeFmpPrivate, MicrocodeEntryPoint);
> + if (NextMicrocodeEntryPoint != NULL) {
> + *AvailableSize = (UINTN) NextMicrocodeEntryPoint - (UINTN)
> MicrocodeEntryPoint;
> + } else {
> + *AvailableSize = (UINTN) MicrocodePatchAddress +
> MicrocodePatchRegionSize - (UINTN) MicrocodeEntryPoint;
> + }
> + if (*AvailableSize >= 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
> buffer 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 = MicrocodeFmpPrivate->MicrocodePatchAddress;
> + MicrocodePatchRegionSize =
> MicrocodeFmpPrivate->MicrocodePatchRegionSize;
> +
> + for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount;
> Index++) {
> + if (!MicrocodeFmpPrivate->FitMicrocodeInfo[Index].InUse) {
> + MicrocodeEntryPoint =
> MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint;
> + NextMicrocodeEntryPoint = GetNextFitMicrocode
> (MicrocodeFmpPrivate, MicrocodeEntryPoint);
> + if (NextMicrocodeEntryPoint != NULL) {
> + *AvailableSize = (UINTN) NextMicrocodeEntryPoint - (UINTN)
> MicrocodeEntryPoint;
> + } else {
> + *AvailableSize = (UINTN) MicrocodePatchAddress +
> MicrocodePatchRegionSize - (UINTN) MicrocodeEntryPoint;
> + }
> + if (*AvailableSize >= ImageSize) {
> + return MicrocodeEntryPoint;
> + }
> + }
> + }
> +
> + return NULL;
> +}
> +
> +/**
> Get current Microcode used region size.
>
> @param[in] MicrocodeFmpPrivate The Microcode driver private
> data
> @@ -666,7 +784,7 @@ UpdateMicrocode (
>
> 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));
>
> Status = MicrocodeFlashWrite (
> Address,
> @@ -682,6 +800,201 @@ UpdateMicrocode (
> }
>
> /**
> + 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
> buffer in bytes.
> + @param[out] LastAttemptStatus The last attempt status, which
> will 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,
> size - 0x%x\n", Image, ImageSize));
> +
> + MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;
> + MicrocodePatchRegionSize =
> MicrocodeFmpPrivate->MicrocodePatchRegionSize;
> +
> + MicrocodePatchScratchBuffer = AllocateZeroPool
> (MicrocodePatchRegionSize);
> + if (MicrocodePatchScratchBuffer == NULL) {
> + DEBUG((DEBUG_ERROR, "Fail to allocate Microcode Scratch buffer\n"));
> + *LastAttemptStatus =
> LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
> + return EFI_OUT_OF_RESOURCES;
> + }
> + ScratchBufferPtr = MicrocodePatchScratchBuffer;
> + ScratchBufferSize = 0;
> +
> + //
> + // Target data collection
> + //
> + TargetTotalSize = 0;
> + AvailableSize = 0;
> + if (TargetMicrocodeEntryPoint != NULL) {
> + if (TargetMicrocodeEntryPoint->DataSize == 0) {
> + TargetTotalSize = 2048;
> + } else {
> + TargetTotalSize = TargetMicrocodeEntryPoint->TotalSize;
> + }
> + DEBUG((DEBUG_INFO, " TargetTotalSize - 0x%x\n", TargetTotalSize));
> + NextMicrocodeEntryPoint = GetNextFitMicrocode (MicrocodeFmpPrivate,
> TargetMicrocodeEntryPoint);
> + DEBUG((DEBUG_INFO, " NextMicrocodeEntryPoint - 0x%x\n",
> NextMicrocodeEntryPoint));
> + if (NextMicrocodeEntryPoint != NULL) {
> + ASSERT ((UINTN) NextMicrocodeEntryPoint >= ((UINTN)
> TargetMicrocodeEntryPoint + TargetTotalSize));
> + AvailableSize = (UINTN) NextMicrocodeEntryPoint - (UINTN)
> TargetMicrocodeEntryPoint;
> + } else {
> + AvailableSize = (UINTN) MicrocodePatchAddress +
> MicrocodePatchRegionSize - (UINTN) TargetMicrocodeEntryPoint;
> + }
> + DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize));
> + ASSERT (AvailableSize >= TargetTotalSize);
> + }
> + //
> + // Total Size means the Microcode size.
> + // Available Size means the Microcode size plus the pad till (1) next
> Microcode or (2) the end.
> + //
> + // (1)
> + // +------+-----------+-----+------+===================+
> + // | MCU1 | Microcode | PAD | MCU2 | Empty |
> + // +------+-----------+-----+------+===================+
> + // | TotalSize |
> + // |<-AvailableSize->|
> + //
> + // (2)
> + // +------+-----------+===================+
> + // | MCU | Microcode | Empty |
> + // +------+-----------+===================+
> + // | TotalSize |
> + // |<- AvailableSize ->|
> + //
> +
> + //
> + // Update based on policy
> + //
> +
> + //
> + // 1. If there is enough space to update old one in situ, replace old microcode
> in situ.
> + //
> + if (AvailableSize >= ImageSize) {
> + DEBUG((DEBUG_INFO, "Replace old microcode in situ\n"));
> + //
> + // +------+------------+------+===================+
> + // |Other | Old Image | ... | Empty |
> + // +------+------------+------+===================+
> + //
> + // +------+---------+--+------+===================+
> + // |Other |New Image|FF| ... | Empty |
> + // +------+---------+--+------+===================+
> + //
> + // 1.1. Copy new image
> + CopyMem (ScratchBufferPtr, Image, ImageSize);
> + ScratchBufferSize += ImageSize;
> + ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + // 1.2. Pad 0xFF
> + RestSize = AvailableSize - ImageSize;
> + if (RestSize > 0) {
> + SetMem (ScratchBufferPtr, RestSize, 0xFF);
> + ScratchBufferSize += RestSize;
> + ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + }
> + Status = UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint,
> MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
> + return Status;
> + }
> +
> + //
> + // 2. If there is empty FIT microcode entry with enough space, use it.
> + //
> + EmptyFitMicrocodeEntry = FindEmptyFitMicrocode (MicrocodeFmpPrivate,
> ImageSize, &AvailableSize);
> + if (EmptyFitMicrocodeEntry != NULL) {
> + DEBUG((DEBUG_INFO, "Use empty FIT microcode entry\n"));
> + // 2.1. Copy new image
> + CopyMem (ScratchBufferPtr, Image, ImageSize);
> + ScratchBufferSize += ImageSize;
> + ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + // 2.2. Pad 0xFF
> + RestSize = AvailableSize - ImageSize;
> + if (RestSize > 0) {
> + SetMem (ScratchBufferPtr, RestSize, 0xFF);
> + ScratchBufferSize += RestSize;
> + ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + }
> + Status = UpdateMicrocode ((UINTN) EmptyFitMicrocodeEntry,
> MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
> + if (!EFI_ERROR (Status) && (TargetMicrocodeEntryPoint != NULL)) {
> + //
> + // Empty old microcode.
> + //
> + ScratchBufferPtr = MicrocodePatchScratchBuffer;
> + SetMem (ScratchBufferPtr, TargetTotalSize, 0xFF);
> + ScratchBufferSize = TargetTotalSize;
> + ScratchBufferPtr = (UINT8 *) MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + UpdateMicrocode ((UINTN) TargetMicrocodeEntryPoint,
> MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
> + }
> + return Status;
> + }
> +
> + //
> + // 3. If there is unused microcode entry with enough space, use it.
> + //
> + UnusedFitMicrocodeEntry = FindUnusedFitMicrocode
> (MicrocodeFmpPrivate, ImageSize, &AvailableSize);
> + if (UnusedFitMicrocodeEntry != NULL) {
> + DEBUG((DEBUG_INFO, "Use unused FIT microcode entry\n"));
> + // 3.1. Copy new image
> + CopyMem (ScratchBufferPtr, Image, ImageSize);
> + ScratchBufferSize += ImageSize;
> + ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + // 3.2. Pad 0xFF
> + RestSize = AvailableSize - ImageSize;
> + if (RestSize > 0) {
> + SetMem (ScratchBufferPtr, RestSize, 0xFF);
> + ScratchBufferSize += RestSize;
> + ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + }
> + Status = UpdateMicrocode ((UINTN) UnusedFitMicrocodeEntry,
> MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
> + if (!EFI_ERROR (Status) && (TargetMicrocodeEntryPoint != NULL)) {
> + //
> + // Empty old microcode.
> + //
> + ScratchBufferPtr = MicrocodePatchScratchBuffer;
> + SetMem (ScratchBufferPtr, TargetTotalSize, 0xFF);
> + ScratchBufferSize = TargetTotalSize;
> + ScratchBufferPtr = (UINT8 *) MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + UpdateMicrocode ((UINTN) TargetMicrocodeEntryPoint,
> MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
> + }
> + return Status;
> + }
> +
> + //
> + // 4. No usable FIT microcode entry.
> + //
> + DEBUG((DEBUG_ERROR, "No usable FIT microcode entry\n"));
> + *LastAttemptStatus =
> LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
> + Status = EFI_OUT_OF_RESOURCES;
> +
> + return Status;
> +}
> +
> +/**
> Update Microcode flash region.
>
> @param[in] MicrocodeFmpPrivate The Microcode driver private
> data
> @@ -753,8 +1066,8 @@ UpdateMicrocodeFlashRegion (
> AvailableSize = (UINTN)MicrocodePatchAddress +
> MicrocodePatchRegionSize - (UINTN)TargetMicrocodeEntryPoint;
> }
> DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize));
> + ASSERT (AvailableSize >= TargetTotalSize);
> }
> - ASSERT (AvailableSize >= TargetTotalSize);
> UsedRegionSize =
> GetCurrentMicrocodeUsedRegionSize(MicrocodeFmpPrivate);
> DEBUG((DEBUG_INFO, " UsedRegionSize - 0x%x\n", UsedRegionSize));
> ASSERT (UsedRegionSize >= TargetTotalSize);
> @@ -762,8 +1075,8 @@ UpdateMicrocodeFlashRegion (
> ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >=
> ((UINTN)TargetMicrocodeEntryPoint + TargetTotalSize));
> }
> //
> - // Total Size means the Microcode data size.
> - // Available Size means the Microcode data size plus the pad till (1) next
> Microcode or (2) the end.
> + // Total Size means the Microcode size.
> + // Available Size means the Microcode size plus the pad till (1) next
> Microcode or (2) the end.
> //
> // (1)
> // +------+-----------+-----+------+===================+
> @@ -793,11 +1106,11 @@ UpdateMicrocodeFlashRegion (
> DEBUG((DEBUG_INFO, "Replace old microcode in situ\n"));
> //
> // +------+------------+------+===================+
> - // |Other1| Old Image |Other2| Empty |
> + // |Other | Old Image | ... | Empty |
> // +------+------------+------+===================+
> //
> // +------+---------+--+------+===================+
> - // |Other1|New Image|FF|Other2| Empty |
> + // |Other |New Image|FF| ... | Empty |
> // +------+---------+--+------+===================+
> //
> // 1.1. Copy new image
> @@ -835,11 +1148,11 @@ UpdateMicrocodeFlashRegion (
> DEBUG((DEBUG_INFO, "Reorg and replace old microcode\n"));
> //
> // +------+------------+------+===================+
> - // |Other1| Old Image |Other2| Empty |
> + // |Other | Old Image | ... | Empty |
> // +------+------------+------+===================+
> //
> // +------+---------------+------+================+
> - // |Other1| New Image |Other2| Empty |
> + // |Other | New Image | ... | Empty |
> // +------+---------------+------+================+
> //
> // 2.1. Copy new image
> @@ -849,7 +1162,7 @@ UpdateMicrocodeFlashRegion (
> // 2.2. Copy rest images after the old image.
> if (NextMicrocodeEntryPoint != 0) {
> RestSize = (UINTN)MicrocodePatchAddress + UsedRegionSize -
> ((UINTN)NextMicrocodeEntryPoint);
> - CopyMem (ScratchBufferPtr, (UINT8 *)TargetMicrocodeEntryPoint +
> TargetTotalSize, RestSize);
> + CopyMem (ScratchBufferPtr, NextMicrocodeEntryPoint, RestSize);
> ScratchBufferSize += RestSize;
> ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> }
> @@ -932,7 +1245,7 @@ UpdateMicrocodeFlashRegion (
> call to FreePool().
>
> @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
> incorrect.
> @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;
> }
>
> - *LastAttemptVersion = ((CPU_MICROCODE_HEADER
> *)Image)->UpdateRevision;
> TargetCpuIndex = (UINTN)-1;
> Status = 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 = ((CPU_MICROCODE_HEADER
> *)Image)->UpdateRevision;
>
> DEBUG((DEBUG_INFO, " TargetCpuIndex - 0x%x\n", TargetCpuIndex));
> ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount);
> @@ -985,13 +1298,23 @@ MicrocodeWrite (
> }
> DEBUG((DEBUG_INFO, " TargetMicrocodeEntryPoint - 0x%x\n",
> TargetMicrocodeEntryPoint));
>
> - Status = UpdateMicrocodeFlashRegion(
> - MicrocodeFmpPrivate,
> - TargetMicrocodeEntryPoint,
> - AlignedImage,
> - ImageSize,
> - LastAttemptStatus
> - );
> + if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
> + Status = UpdateMicrocodeFlashRegionWithFit (
> + MicrocodeFmpPrivate,
> + TargetMicrocodeEntryPoint,
> + AlignedImage,
> + ImageSize,
> + LastAttemptStatus
> + );
> + } else {
> + Status = UpdateMicrocodeFlashRegion (
> + MicrocodeFmpPrivate,
> + TargetMicrocodeEntryPoint,
> + AlignedImage,
> + ImageSize,
> + LastAttemptStatus
> + );
> + }
>
> FreePool(AlignedImage);
>
> diff --git
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
> index 4442032eb6b6..3f92c517a91c 100644
> --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
> +++
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
> @@ -20,6 +20,8 @@
> #include <Guid/SystemResourceTable.h>
> #include <Guid/MicrocodeFmp.h>
>
> +#include <IndustryStandard/FirmwareInterfaceTable.h>
> +
> #include <Protocol/FirmwareManagement.h>
> #include <Protocol/MpService.h>
>
> @@ -58,6 +60,13 @@ typedef struct {
> } MICROCODE_INFO;
>
> typedef struct {
> + CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
> + UINTN TotalSize;
> + BOOLEAN InUse;
> + BOOLEAN Empty;
> +} FIT_MICROCODE_INFO;
> +
> +typedef struct {
> UINTN CpuIndex;
> UINT32 ProcessorSignature;
> UINT8 PlatformId;
> @@ -86,11 +95,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
> UINTN BspIndex;
> UINTN ProcessorCount;
> PROCESSOR_INFO *ProcessorInfo;
> + UINT32 FitMicrocodeEntryCount;
> + FIT_MICROCODE_INFO *FitMicrocodeInfo;
> };
>
> typedef struct _MICROCODE_FMP_PRIVATE_DATA
> MICROCODE_FMP_PRIVATE_DATA;
>
> -#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME
> L"MicrocodeLastAttempVar"
> +#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME
> L"MicrocodeLastAttemptVar"
>
> /**
> Returns a pointer to the MICROCODE_FMP_PRIVATE_DATA structure from
> the input a as Fmp.
> diff --git
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.i
> nf
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.i
> nf
> index dbc90857a0a5..24f06c23d404 100644
> ---
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.i
> nf
> +++
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.i
> nf
> @@ -3,7 +3,7 @@
> #
> # Produce FMP instance to update Microcode.
> #
> -# Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> # This program and the accompanying materials
> # are licensed and made available under the terms and conditions of the BSD
> License
> # which accompanies this distribution. The full text of the license may be
> found at
> @@ -65,6 +65,7 @@ [Pcd]
>
> [Depex]
> gEfiVariableArchProtocolGuid AND
> + gEfiVariableWriteArchProtocolGuid AND
> gEfiMpServiceProtocolGuid
>
> [UserExtensions.TianoCore."ExtraFiles"]
> --
> 2.7.0.windows.1
prev parent reply other threads:[~2018-05-04 6:05 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-27 8:20 [PATCH V2] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table Star Zeng
2018-05-04 6:05 ` Yao, Jiewen [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=74D8A39837DF1E4DA445A8C0B3885C503AB8D821@shsmsx102.ccr.corp.intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox