public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH V2] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
@ 2018-04-27  8:20 Star Zeng
  2018-05-04  6:05 ` Yao, Jiewen
  0 siblings, 1 reply; 2+ messages in thread
From: Star Zeng @ 2018-04-27  8:20 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng, Jiewen Yao

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.inf b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.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.<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



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH V2] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
  2018-04-27  8:20 [PATCH V2] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table Star Zeng
@ 2018-05-04  6:05 ` Yao, Jiewen
  0 siblings, 0 replies; 2+ messages in thread
From: Yao, Jiewen @ 2018-05-04  6:05 UTC (permalink / raw)
  To: Zeng, Star, edk2-devel@lists.01.org

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



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2018-05-04  6:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-04-27  8:20 [PATCH V2] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table Star Zeng
2018-05-04  6:05 ` Yao, Jiewen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox