[edk2] [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table

Star Zeng posted 1 patch 5 years, 11 months ago
Failed in applying to current master (apply log)
There is a newer version of this series
.../Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c      | 184 ++++++++++-
.../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c   | 363 +++++++++++++++++++--
.../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h   |  12 +-
.../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf      |   3 +-
4 files changed, 535 insertions(+), 27 deletions(-)
[edk2] [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
Posted by Star Zeng 5 years, 11 months ago
It is the second step for
https://bugzilla.tianocore.org/show_bug.cgi?id=540.

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      | 184 ++++++++++-
 .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c   | 363 +++++++++++++++++++--
 .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h   |  12 +-
 .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf      |   3 +-
 4 files changed, 535 insertions(+), 27 deletions(-)

diff --git a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
index ebde93a91eb3..8276aaa0279b 100644
--- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
+++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
@@ -272,7 +272,7 @@ FmpSetImage (
   }
 
   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,159 @@ 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.
+
+**/
+VOID
+InitializeFitMicrocodeInfo (
+  IN MICROCODE_FMP_PRIVATE_DATA     *MicrocodeFmpPrivate
+  )
+{
+  UINT64                            FitPointer;
+  FIRMWARE_INTERFACE_TABLE_ENTRY    *FitEntry;
+  UINT32                            EntryNum;
+  UINT32                            MicrocodeEntryNum;
+  UINT32                            Index;
+  UINTN                             Address;
+  VOID                              *MicrocodePatchAddress;
+  UINTN                             MicrocodePatchRegionSize;
+  FIT_MICROCODE_INFO                *FitMicrocodeInfo;
+  UINTN                             FitMicrocodeIndex;
+  MICROCODE_INFO                    *MicrocodeInfo;
+  UINTN                             MicrocodeIndex;
+
+  if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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;
+  }
+  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;
+    //
+    return;
+  }
+
+  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;
+  }
+
+  MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;
+
+  //
+  // Allocate buffer.
+  //
+  MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));
+  ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL);
+
+  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;
+      ASSERT ((Address >= (UINTN) MicrocodePatchAddress) &&
+              (Address < ((UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize)));
+      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->InUse = MicrocodeInfo->InUse;
+        break;
+      }
+    }
+    ASSERT (FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount);
+  }
+
+  SortFitMicrocodeInfo (MicrocodeFmpPrivate);
+}
+
+/**
   Initialize Processor Microcode Index.
 
   @param[in] MicrocodeFmpPrivate private data structure to be initialized.
@@ -496,6 +649,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 +659,8 @@ InitializeMicrocodeDescriptor (
 
   InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
 
+  InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);
+
   return EFI_SUCCESS;
 }
 
@@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor (
 
   @param[in] MicrocodeFmpPrivate private data structure to be initialized.
 
-  @return EFI_SUCCESS private data is initialized.
+  @return EFI_SUCCESS Processor information is initialized.
 **/
 EFI_STATUS
 InitializeProcessorInfo (
@@ -583,6 +739,7 @@ DumpPrivateInfo (
   PROCESSOR_INFO                       *ProcessorInfo;
   MICROCODE_INFO                       *MicrocodeInfo;
   EFI_FIRMWARE_IMAGE_DESCRIPTOR        *ImageDescriptor;
+  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;
 
   DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
   DEBUG ((DEBUG_INFO, "  ProcessorCount - 0x%x\n", MicrocodeFmpPrivate->ProcessorCount));
@@ -635,6 +792,22 @@ 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%x, 0x%x)\n",
+        Index,
+        FitMicrocodeInfo[Index].MicrocodeEntryPoint,
+        FitMicrocodeInfo[Index].InUse,
+        FitMicrocodeInfo[Index].Empty
+        ));
+    }
+  }
 }
 
 /**
@@ -671,8 +844,8 @@ InitializePrivateData (
                      &VarSize,
                      &MicrocodeFmpPrivate->LastAttempt
                      );
-  DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus));
-  DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", 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 +861,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 9dc306324e62..d16b353eefa2 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,12 @@ typedef struct {
 } MICROCODE_INFO;
 
 typedef struct {
+  CPU_MICROCODE_HEADER   *MicrocodeEntryPoint;
+  BOOLEAN                Empty;
+  BOOLEAN                InUse;
+} FIT_MICROCODE_INFO;
+
+typedef struct {
   UINTN                  CpuIndex;
   UINT32                 ProcessorSignature;
   UINT8                  PlatformId;
@@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
   UINTN                                BspIndex;
   UINTN                                ProcessorCount;
   PROCESSOR_INFO                       *ProcessorInfo;
+  UINT32                               FitMicrocodeEntryCount;
+  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;
 };
 
 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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
Posted by Yao, Jiewen 5 years, 11 months ago
Thanks for the update.

Would you please share what unit test has been done for this patch?


Thank you
Yao Jiewen

> -----Original Message-----
> From: Zeng, Star
> Sent: Monday, April 23, 2018 2:57 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
> Subject: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
> 
> It is the second step for
> https://bugzilla.tianocore.org/show_bug.cgi?id=540.
> 
> 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      | 184 ++++++++++-
>  .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c   | 363
> +++++++++++++++++++--
>  .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h   |  12 +-
>  .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf      |   3 +-
>  4 files changed, 535 insertions(+), 27 deletions(-)
> 
> diff --git
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> index ebde93a91eb3..8276aaa0279b 100644
> --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> @@ -272,7 +272,7 @@ FmpSetImage (
>    }
> 
>    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,159 @@ 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.
> +
> +**/
> +VOID
> +InitializeFitMicrocodeInfo (
> +  IN MICROCODE_FMP_PRIVATE_DATA     *MicrocodeFmpPrivate
> +  )
> +{
> +  UINT64                            FitPointer;
> +  FIRMWARE_INTERFACE_TABLE_ENTRY    *FitEntry;
> +  UINT32                            EntryNum;
> +  UINT32                            MicrocodeEntryNum;
> +  UINT32                            Index;
> +  UINTN                             Address;
> +  VOID                              *MicrocodePatchAddress;
> +  UINTN                             MicrocodePatchRegionSize;
> +  FIT_MICROCODE_INFO                *FitMicrocodeInfo;
> +  UINTN                             FitMicrocodeIndex;
> +  MICROCODE_INFO                    *MicrocodeInfo;
> +  UINTN                             MicrocodeIndex;
> +
> +  if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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;
> +  }
> +  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;
> +    //
> +    return;
> +  }
> +
> +  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;
> +  }
> +
> +  MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;
> +
> +  //
> +  // Allocate buffer.
> +  //
> +  MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool
> (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));
> +  ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL);
> +
> +  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;
> +      ASSERT ((Address >= (UINTN) MicrocodePatchAddress) &&
> +              (Address < ((UINTN) MicrocodePatchAddress +
> MicrocodePatchRegionSize)));
> +      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->InUse = MicrocodeInfo->InUse;
> +        break;
> +      }
> +    }
> +    ASSERT (FitMicrocodeIndex <
> MicrocodeFmpPrivate->FitMicrocodeEntryCount);
> +  }
> +
> +  SortFitMicrocodeInfo (MicrocodeFmpPrivate);
> +}
> +
> +/**
>    Initialize Processor Microcode Index.
> 
>    @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> @@ -496,6 +649,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 +659,8 @@ InitializeMicrocodeDescriptor (
> 
>    InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
> 
> +  InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);
> +
>    return EFI_SUCCESS;
>  }
> 
> @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor (
> 
>    @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> 
> -  @return EFI_SUCCESS private data is initialized.
> +  @return EFI_SUCCESS Processor information is initialized.
>  **/
>  EFI_STATUS
>  InitializeProcessorInfo (
> @@ -583,6 +739,7 @@ DumpPrivateInfo (
>    PROCESSOR_INFO                       *ProcessorInfo;
>    MICROCODE_INFO                       *MicrocodeInfo;
>    EFI_FIRMWARE_IMAGE_DESCRIPTOR        *ImageDescriptor;
> +  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;
> 
>    DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
>    DEBUG ((DEBUG_INFO, "  ProcessorCount - 0x%x\n",
> MicrocodeFmpPrivate->ProcessorCount));
> @@ -635,6 +792,22 @@ 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%x, 0x%x)\n",
> +        Index,
> +        FitMicrocodeInfo[Index].MicrocodeEntryPoint,
> +        FitMicrocodeInfo[Index].InUse,
> +        FitMicrocodeInfo[Index].Empty
> +        ));
> +    }
> +  }
>  }
> 
>  /**
> @@ -671,8 +844,8 @@ InitializePrivateData (
>                       &VarSize,
>                       &MicrocodeFmpPrivate->LastAttempt
>                       );
> -  DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus));
> -  DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n",
> 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 +861,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 9dc306324e62..d16b353eefa2 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,12 @@ typedef struct {
>  } MICROCODE_INFO;
> 
>  typedef struct {
> +  CPU_MICROCODE_HEADER   *MicrocodeEntryPoint;
> +  BOOLEAN                Empty;
> +  BOOLEAN                InUse;
> +} FIT_MICROCODE_INFO;
> +
> +typedef struct {
>    UINTN                  CpuIndex;
>    UINT32                 ProcessorSignature;
>    UINT8                  PlatformId;
> @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
>    UINTN                                BspIndex;
>    UINTN                                ProcessorCount;
>    PROCESSOR_INFO                       *ProcessorInfo;
> +  UINT32                               FitMicrocodeEntryCount;
> +  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;
>  };
> 
>  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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
Posted by Zeng, Star 5 years, 11 months ago
Yonghong helped run regression test for the cases without FIT table.
I created below cases with FIT table, checked the boot log and confirmed the signature is correct after microcode update.
1. Update in situ.
2. Empty FIT microcode entry with enough space.
3. Unused FIT microcode entry with enough space.


Thanks,
Star
-----Original Message-----
From: Yao, Jiewen 
Sent: Monday, April 23, 2018 4:49 PM
To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org
Cc: Yao, Jiewen <jiewen.yao@intel.com>
Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table

Thanks for the update.

Would you please share what unit test has been done for this patch?


Thank you
Yao Jiewen

> -----Original Message-----
> From: Zeng, Star
> Sent: Monday, April 23, 2018 2:57 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen 
> <jiewen.yao@intel.com>
> Subject: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
> 
> It is the second step for
> https://bugzilla.tianocore.org/show_bug.cgi?id=540.
> 
> 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      | 184 ++++++++++-
>  .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c   | 363
> +++++++++++++++++++--
>  .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h   |  12 +-
>  .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf      |   3 +-
>  4 files changed, 535 insertions(+), 27 deletions(-)
> 
> diff --git
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> index ebde93a91eb3..8276aaa0279b 100644
> --- 
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.
> +++ c
> @@ -272,7 +272,7 @@ FmpSetImage (
>    }
> 
>    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,159 @@ 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.
> +
> +**/
> +VOID
> +InitializeFitMicrocodeInfo (
> +  IN MICROCODE_FMP_PRIVATE_DATA     *MicrocodeFmpPrivate
> +  )
> +{
> +  UINT64                            FitPointer;
> +  FIRMWARE_INTERFACE_TABLE_ENTRY    *FitEntry;
> +  UINT32                            EntryNum;
> +  UINT32                            MicrocodeEntryNum;
> +  UINT32                            Index;
> +  UINTN                             Address;
> +  VOID                              *MicrocodePatchAddress;
> +  UINTN                             MicrocodePatchRegionSize;
> +  FIT_MICROCODE_INFO                *FitMicrocodeInfo;
> +  UINTN                             FitMicrocodeIndex;
> +  MICROCODE_INFO                    *MicrocodeInfo;
> +  UINTN                             MicrocodeIndex;
> +
> +  if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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;
> +  }
> +  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;
> +    //
> +    return;
> +  }
> +
> +  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;
> +  }
> +
> +  MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;
> +
> +  //
> +  // Allocate buffer.
> +  //
> +  MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool
> (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));
> +  ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL);
> +
> +  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;
> +      ASSERT ((Address >= (UINTN) MicrocodePatchAddress) &&
> +              (Address < ((UINTN) MicrocodePatchAddress +
> MicrocodePatchRegionSize)));
> +      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->InUse = MicrocodeInfo->InUse;
> +        break;
> +      }
> +    }
> +    ASSERT (FitMicrocodeIndex <
> MicrocodeFmpPrivate->FitMicrocodeEntryCount);
> +  }
> +
> +  SortFitMicrocodeInfo (MicrocodeFmpPrivate); }
> +
> +/**
>    Initialize Processor Microcode Index.
> 
>    @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> @@ -496,6 +649,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 +659,8 @@ InitializeMicrocodeDescriptor (
> 
>    InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
> 
> +  InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);
> +
>    return EFI_SUCCESS;
>  }
> 
> @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor (
> 
>    @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> 
> -  @return EFI_SUCCESS private data is initialized.
> +  @return EFI_SUCCESS Processor information is initialized.
>  **/
>  EFI_STATUS
>  InitializeProcessorInfo (
> @@ -583,6 +739,7 @@ DumpPrivateInfo (
>    PROCESSOR_INFO                       *ProcessorInfo;
>    MICROCODE_INFO                       *MicrocodeInfo;
>    EFI_FIRMWARE_IMAGE_DESCRIPTOR        *ImageDescriptor;
> +  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;
> 
>    DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
>    DEBUG ((DEBUG_INFO, "  ProcessorCount - 0x%x\n",
> MicrocodeFmpPrivate->ProcessorCount));
> @@ -635,6 +792,22 @@ 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%x, 0x%x)\n",
> +        Index,
> +        FitMicrocodeInfo[Index].MicrocodeEntryPoint,
> +        FitMicrocodeInfo[Index].InUse,
> +        FitMicrocodeInfo[Index].Empty
> +        ));
> +    }
> +  }
>  }
> 
>  /**
> @@ -671,8 +844,8 @@ InitializePrivateData (
>                       &VarSize,
>                       &MicrocodeFmpPrivate->LastAttempt
>                       );
> -  DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus));
> -  DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n",
> 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 +861,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 9dc306324e62..d16b353eefa2 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,12 @@ typedef struct {
>  } MICROCODE_INFO;
> 
>  typedef struct {
> +  CPU_MICROCODE_HEADER   *MicrocodeEntryPoint;
> +  BOOLEAN                Empty;
> +  BOOLEAN                InUse;
> +} FIT_MICROCODE_INFO;
> +
> +typedef struct {
>    UINTN                  CpuIndex;
>    UINT32                 ProcessorSignature;
>    UINT8                  PlatformId;
> @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
>    UINTN                                BspIndex;
>    UINTN                                ProcessorCount;
>    PROCESSOR_INFO                       *ProcessorInfo;
> +  UINT32                               FitMicrocodeEntryCount;
> +  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;
>  };
> 
>  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/MicrocodeUpdateDx
> e.i
> nf
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx
> e.i
> nf
> index dbc90857a0a5..24f06c23d404 100644
> ---
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx
> e.i
> nf
> +++
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx
> e.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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
Posted by Zeng, Star 5 years, 11 months ago
I also built VS2015/GCC49 (tool chain in my local), and checked ecc result.


Thanks,
Star
-----Original Message-----
From: Zeng, Star 
Sent: Monday, April 23, 2018 4:55 PM
To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
Cc: Zhu, Yonghong <yonghong.zhu@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table

Yonghong helped run regression test for the cases without FIT table.
I created below cases with FIT table, checked the boot log and confirmed the signature is correct after microcode update.
1. Update in situ.
2. Empty FIT microcode entry with enough space.
3. Unused FIT microcode entry with enough space.


Thanks,
Star
-----Original Message-----
From: Yao, Jiewen
Sent: Monday, April 23, 2018 4:49 PM
To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org
Cc: Yao, Jiewen <jiewen.yao@intel.com>
Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table

Thanks for the update.

Would you please share what unit test has been done for this patch?


Thank you
Yao Jiewen

> -----Original Message-----
> From: Zeng, Star
> Sent: Monday, April 23, 2018 2:57 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen 
> <jiewen.yao@intel.com>
> Subject: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
> 
> It is the second step for
> https://bugzilla.tianocore.org/show_bug.cgi?id=540.
> 
> 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      | 184 ++++++++++-
>  .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c   | 363
> +++++++++++++++++++--
>  .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h   |  12 +-
>  .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf      |   3 +-
>  4 files changed, 535 insertions(+), 27 deletions(-)
> 
> diff --git
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> index ebde93a91eb3..8276aaa0279b 100644
> ---
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.
> +++ c
> @@ -272,7 +272,7 @@ FmpSetImage (
>    }
> 
>    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,159 @@ 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.
> +
> +**/
> +VOID
> +InitializeFitMicrocodeInfo (
> +  IN MICROCODE_FMP_PRIVATE_DATA     *MicrocodeFmpPrivate
> +  )
> +{
> +  UINT64                            FitPointer;
> +  FIRMWARE_INTERFACE_TABLE_ENTRY    *FitEntry;
> +  UINT32                            EntryNum;
> +  UINT32                            MicrocodeEntryNum;
> +  UINT32                            Index;
> +  UINTN                             Address;
> +  VOID                              *MicrocodePatchAddress;
> +  UINTN                             MicrocodePatchRegionSize;
> +  FIT_MICROCODE_INFO                *FitMicrocodeInfo;
> +  UINTN                             FitMicrocodeIndex;
> +  MICROCODE_INFO                    *MicrocodeInfo;
> +  UINTN                             MicrocodeIndex;
> +
> +  if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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;
> +  }
> +  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;
> +    //
> +    return;
> +  }
> +
> +  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;
> +  }
> +
> +  MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;
> +
> +  //
> +  // Allocate buffer.
> +  //
> +  MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool
> (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));
> +  ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL);
> +
> +  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;
> +      ASSERT ((Address >= (UINTN) MicrocodePatchAddress) &&
> +              (Address < ((UINTN) MicrocodePatchAddress +
> MicrocodePatchRegionSize)));
> +      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->InUse = MicrocodeInfo->InUse;
> +        break;
> +      }
> +    }
> +    ASSERT (FitMicrocodeIndex <
> MicrocodeFmpPrivate->FitMicrocodeEntryCount);
> +  }
> +
> +  SortFitMicrocodeInfo (MicrocodeFmpPrivate); }
> +
> +/**
>    Initialize Processor Microcode Index.
> 
>    @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> @@ -496,6 +649,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 +659,8 @@ InitializeMicrocodeDescriptor (
> 
>    InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
> 
> +  InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);
> +
>    return EFI_SUCCESS;
>  }
> 
> @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor (
> 
>    @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> 
> -  @return EFI_SUCCESS private data is initialized.
> +  @return EFI_SUCCESS Processor information is initialized.
>  **/
>  EFI_STATUS
>  InitializeProcessorInfo (
> @@ -583,6 +739,7 @@ DumpPrivateInfo (
>    PROCESSOR_INFO                       *ProcessorInfo;
>    MICROCODE_INFO                       *MicrocodeInfo;
>    EFI_FIRMWARE_IMAGE_DESCRIPTOR        *ImageDescriptor;
> +  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;
> 
>    DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
>    DEBUG ((DEBUG_INFO, "  ProcessorCount - 0x%x\n",
> MicrocodeFmpPrivate->ProcessorCount));
> @@ -635,6 +792,22 @@ 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%x, 0x%x)\n",
> +        Index,
> +        FitMicrocodeInfo[Index].MicrocodeEntryPoint,
> +        FitMicrocodeInfo[Index].InUse,
> +        FitMicrocodeInfo[Index].Empty
> +        ));
> +    }
> +  }
>  }
> 
>  /**
> @@ -671,8 +844,8 @@ InitializePrivateData (
>                       &VarSize,
>                       &MicrocodeFmpPrivate->LastAttempt
>                       );
> -  DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus));
> -  DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n",
> 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 +861,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 9dc306324e62..d16b353eefa2 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,12 @@ typedef struct {
>  } MICROCODE_INFO;
> 
>  typedef struct {
> +  CPU_MICROCODE_HEADER   *MicrocodeEntryPoint;
> +  BOOLEAN                Empty;
> +  BOOLEAN                InUse;
> +} FIT_MICROCODE_INFO;
> +
> +typedef struct {
>    UINTN                  CpuIndex;
>    UINT32                 ProcessorSignature;
>    UINT8                  PlatformId;
> @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
>    UINTN                                BspIndex;
>    UINTN                                ProcessorCount;
>    PROCESSOR_INFO                       *ProcessorInfo;
> +  UINT32                               FitMicrocodeEntryCount;
> +  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;
>  };
> 
>  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/MicrocodeUpdateDx
> e.i
> nf
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx
> e.i
> nf
> index dbc90857a0a5..24f06c23d404 100644
> ---
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx
> e.i
> nf
> +++
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx
> e.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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
Posted by Yao, Jiewen 5 years, 11 months ago
Thanks.

Maybe we should also do more test on different FIT table (correct format, or wrong format), to check the robustness of the code.

For example, don't use ASSERT to check FIT table content, because it might not in Initial Boot Block (IBB) region.

Thank you
Yao Jiewen

> -----Original Message-----
> From: Zeng, Star
> Sent: Monday, April 23, 2018 1:55 AM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Zhu, Yonghong <yonghong.zhu@intel.com>; Zeng, Star
> <star.zeng@intel.com>
> Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
> 
> Yonghong helped run regression test for the cases without FIT table.
> I created below cases with FIT table, checked the boot log and confirmed the
> signature is correct after microcode update.
> 1. Update in situ.
> 2. Empty FIT microcode entry with enough space.
> 3. Unused FIT microcode entry with enough space.
> 
> 
> Thanks,
> Star
> -----Original Message-----
> From: Yao, Jiewen
> Sent: Monday, April 23, 2018 4:49 PM
> To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org
> Cc: Yao, Jiewen <jiewen.yao@intel.com>
> Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
> 
> Thanks for the update.
> 
> Would you please share what unit test has been done for this patch?
> 
> 
> Thank you
> Yao Jiewen
> 
> > -----Original Message-----
> > From: Zeng, Star
> > Sent: Monday, April 23, 2018 2:57 PM
> > To: edk2-devel@lists.01.org
> > Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen
> > <jiewen.yao@intel.com>
> > Subject: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
> >
> > It is the second step for
> > https://bugzilla.tianocore.org/show_bug.cgi?id=540.
> >
> > 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      | 184
> ++++++++++-
> >  .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c   | 363
> > +++++++++++++++++++--
> >  .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h   |  12 +-
> >  .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf      |   3 +-
> >  4 files changed, 535 insertions(+), 27 deletions(-)
> >
> > diff --git
> > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> > index ebde93a91eb3..8276aaa0279b 100644
> > ---
> > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> > +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.
> > +++ c
> > @@ -272,7 +272,7 @@ FmpSetImage (
> >    }
> >
> >    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,159 @@ 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.
> > +
> > +**/
> > +VOID
> > +InitializeFitMicrocodeInfo (
> > +  IN MICROCODE_FMP_PRIVATE_DATA     *MicrocodeFmpPrivate
> > +  )
> > +{
> > +  UINT64                            FitPointer;
> > +  FIRMWARE_INTERFACE_TABLE_ENTRY    *FitEntry;
> > +  UINT32                            EntryNum;
> > +  UINT32                            MicrocodeEntryNum;
> > +  UINT32                            Index;
> > +  UINTN                             Address;
> > +  VOID                              *MicrocodePatchAddress;
> > +  UINTN                             MicrocodePatchRegionSize;
> > +  FIT_MICROCODE_INFO                *FitMicrocodeInfo;
> > +  UINTN                             FitMicrocodeIndex;
> > +  MICROCODE_INFO                    *MicrocodeInfo;
> > +  UINTN                             MicrocodeIndex;
> > +
> > +  if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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;
> > +  }
> > +  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;
> > +    //
> > +    return;
> > +  }
> > +
> > +  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;
> > +  }
> > +
> > +  MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;
> > +
> > +  //
> > +  // Allocate buffer.
> > +  //
> > +  MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool
> > (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));
> > +  ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL);
> > +
> > +  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;
> > +      ASSERT ((Address >= (UINTN) MicrocodePatchAddress) &&
> > +              (Address < ((UINTN) MicrocodePatchAddress +
> > MicrocodePatchRegionSize)));
> > +      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->InUse = MicrocodeInfo->InUse;
> > +        break;
> > +      }
> > +    }
> > +    ASSERT (FitMicrocodeIndex <
> > MicrocodeFmpPrivate->FitMicrocodeEntryCount);
> > +  }
> > +
> > +  SortFitMicrocodeInfo (MicrocodeFmpPrivate); }
> > +
> > +/**
> >    Initialize Processor Microcode Index.
> >
> >    @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> > @@ -496,6 +649,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 +659,8 @@ InitializeMicrocodeDescriptor (
> >
> >    InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
> >
> > +  InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);
> > +
> >    return EFI_SUCCESS;
> >  }
> >
> > @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor (
> >
> >    @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> >
> > -  @return EFI_SUCCESS private data is initialized.
> > +  @return EFI_SUCCESS Processor information is initialized.
> >  **/
> >  EFI_STATUS
> >  InitializeProcessorInfo (
> > @@ -583,6 +739,7 @@ DumpPrivateInfo (
> >    PROCESSOR_INFO                       *ProcessorInfo;
> >    MICROCODE_INFO                       *MicrocodeInfo;
> >    EFI_FIRMWARE_IMAGE_DESCRIPTOR        *ImageDescriptor;
> > +  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;
> >
> >    DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
> >    DEBUG ((DEBUG_INFO, "  ProcessorCount - 0x%x\n",
> > MicrocodeFmpPrivate->ProcessorCount));
> > @@ -635,6 +792,22 @@ 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%x, 0x%x)\n",
> > +        Index,
> > +        FitMicrocodeInfo[Index].MicrocodeEntryPoint,
> > +        FitMicrocodeInfo[Index].InUse,
> > +        FitMicrocodeInfo[Index].Empty
> > +        ));
> > +    }
> > +  }
> >  }
> >
> >  /**
> > @@ -671,8 +844,8 @@ InitializePrivateData (
> >                       &VarSize,
> >                       &MicrocodeFmpPrivate->LastAttempt
> >                       );
> > -  DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus));
> > -  DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n",
> > 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 +861,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 9dc306324e62..d16b353eefa2 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,12 @@ typedef struct {
> >  } MICROCODE_INFO;
> >
> >  typedef struct {
> > +  CPU_MICROCODE_HEADER   *MicrocodeEntryPoint;
> > +  BOOLEAN                Empty;
> > +  BOOLEAN                InUse;
> > +} FIT_MICROCODE_INFO;
> > +
> > +typedef struct {
> >    UINTN                  CpuIndex;
> >    UINT32                 ProcessorSignature;
> >    UINT8                  PlatformId;
> > @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
> >    UINTN                                BspIndex;
> >    UINTN                                ProcessorCount;
> >    PROCESSOR_INFO                       *ProcessorInfo;
> > +  UINT32                               FitMicrocodeEntryCount;
> > +  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;
> >  };
> >
> >  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/MicrocodeUpdateDx
> > e.i
> > nf
> > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx
> > e.i
> > nf
> > index dbc90857a0a5..24f06c23d404 100644
> > ---
> > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx
> > e.i
> > nf
> > +++
> > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx
> > e.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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
Posted by Zeng, Star 5 years, 11 months ago
Great comment.
Follow your suggestion, I just sent the V2 patch at https://lists.01.org/pipermail/edk2-devel/2018-April/024270.html.
I created and verified some cases for the error path in InitializeFitMicrocodeInfo().


Thanks,
Star
-----Original Message-----
From: Yao, Jiewen 
Sent: Thursday, April 26, 2018 11:15 PM
To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org
Cc: Zhu, Yonghong <yonghong.zhu@intel.com>
Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table

Thanks.

Maybe we should also do more test on different FIT table (correct format, or wrong format), to check the robustness of the code.

For example, don't use ASSERT to check FIT table content, because it might not in Initial Boot Block (IBB) region.

Thank you
Yao Jiewen

> -----Original Message-----
> From: Zeng, Star
> Sent: Monday, April 23, 2018 1:55 AM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Zhu, Yonghong <yonghong.zhu@intel.com>; Zeng, Star 
> <star.zeng@intel.com>
> Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT 
> table
> 
> Yonghong helped run regression test for the cases without FIT table.
> I created below cases with FIT table, checked the boot log and 
> confirmed the signature is correct after microcode update.
> 1. Update in situ.
> 2. Empty FIT microcode entry with enough space.
> 3. Unused FIT microcode entry with enough space.
> 
> 
> Thanks,
> Star
> -----Original Message-----
> From: Yao, Jiewen
> Sent: Monday, April 23, 2018 4:49 PM
> To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org
> Cc: Yao, Jiewen <jiewen.yao@intel.com>
> Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT 
> table
> 
> Thanks for the update.
> 
> Would you please share what unit test has been done for this patch?
> 
> 
> Thank you
> Yao Jiewen
> 
> > -----Original Message-----
> > From: Zeng, Star
> > Sent: Monday, April 23, 2018 2:57 PM
> > To: edk2-devel@lists.01.org
> > Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen 
> > <jiewen.yao@intel.com>
> > Subject: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
> >
> > It is the second step for
> > https://bugzilla.tianocore.org/show_bug.cgi?id=540.
> >
> > 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      | 184
> ++++++++++-
> >  .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c   | 363
> > +++++++++++++++++++--
> >  .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h   |  12 +-
> >  .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf      |   3 +-
> >  4 files changed, 535 insertions(+), 27 deletions(-)
> >
> > diff --git
> > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> > index ebde93a91eb3..8276aaa0279b 100644
> > ---
> > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> > +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.
> > +++ c
> > @@ -272,7 +272,7 @@ FmpSetImage (
> >    }
> >
> >    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,159 @@ 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.
> > +
> > +**/
> > +VOID
> > +InitializeFitMicrocodeInfo (
> > +  IN MICROCODE_FMP_PRIVATE_DATA     *MicrocodeFmpPrivate
> > +  )
> > +{
> > +  UINT64                            FitPointer;
> > +  FIRMWARE_INTERFACE_TABLE_ENTRY    *FitEntry;
> > +  UINT32                            EntryNum;
> > +  UINT32                            MicrocodeEntryNum;
> > +  UINT32                            Index;
> > +  UINTN                             Address;
> > +  VOID                              *MicrocodePatchAddress;
> > +  UINTN                             MicrocodePatchRegionSize;
> > +  FIT_MICROCODE_INFO                *FitMicrocodeInfo;
> > +  UINTN                             FitMicrocodeIndex;
> > +  MICROCODE_INFO                    *MicrocodeInfo;
> > +  UINTN                             MicrocodeIndex;
> > +
> > +  if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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;
> > +  }
> > +  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;
> > +    //
> > +    return;
> > +  }
> > +
> > +  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;
> > +  }
> > +
> > +  MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;
> > +
> > +  //
> > +  // Allocate buffer.
> > +  //
> > +  MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool
> > (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));
> > +  ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL);
> > +
> > +  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;
> > +      ASSERT ((Address >= (UINTN) MicrocodePatchAddress) &&
> > +              (Address < ((UINTN) MicrocodePatchAddress +
> > MicrocodePatchRegionSize)));
> > +      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->InUse = MicrocodeInfo->InUse;
> > +        break;
> > +      }
> > +    }
> > +    ASSERT (FitMicrocodeIndex <
> > MicrocodeFmpPrivate->FitMicrocodeEntryCount);
> > +  }
> > +
> > +  SortFitMicrocodeInfo (MicrocodeFmpPrivate); }
> > +
> > +/**
> >    Initialize Processor Microcode Index.
> >
> >    @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> > @@ -496,6 +649,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 +659,8 @@ InitializeMicrocodeDescriptor (
> >
> >    InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
> >
> > +  InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);
> > +
> >    return EFI_SUCCESS;
> >  }
> >
> > @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor (
> >
> >    @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> >
> > -  @return EFI_SUCCESS private data is initialized.
> > +  @return EFI_SUCCESS Processor information is initialized.
> >  **/
> >  EFI_STATUS
> >  InitializeProcessorInfo (
> > @@ -583,6 +739,7 @@ DumpPrivateInfo (
> >    PROCESSOR_INFO                       *ProcessorInfo;
> >    MICROCODE_INFO                       *MicrocodeInfo;
> >    EFI_FIRMWARE_IMAGE_DESCRIPTOR        *ImageDescriptor;
> > +  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;
> >
> >    DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
> >    DEBUG ((DEBUG_INFO, "  ProcessorCount - 0x%x\n",
> > MicrocodeFmpPrivate->ProcessorCount));
> > @@ -635,6 +792,22 @@ 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%x, 0x%x)\n",
> > +        Index,
> > +        FitMicrocodeInfo[Index].MicrocodeEntryPoint,
> > +        FitMicrocodeInfo[Index].InUse,
> > +        FitMicrocodeInfo[Index].Empty
> > +        ));
> > +    }
> > +  }
> >  }
> >
> >  /**
> > @@ -671,8 +844,8 @@ InitializePrivateData (
> >                       &VarSize,
> >                       &MicrocodeFmpPrivate->LastAttempt
> >                       );
> > -  DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus));
> > -  DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 
> > 0x%x\n",
> > 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 +861,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/ProcessorFla
> > gs "), 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 9dc306324e62..d16b353eefa2 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,12 @@ typedef struct {
> >  } MICROCODE_INFO;
> >
> >  typedef struct {
> > +  CPU_MICROCODE_HEADER   *MicrocodeEntryPoint;
> > +  BOOLEAN                Empty;
> > +  BOOLEAN                InUse;
> > +} FIT_MICROCODE_INFO;
> > +
> > +typedef struct {
> >    UINTN                  CpuIndex;
> >    UINT32                 ProcessorSignature;
> >    UINT8                  PlatformId;
> > @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
> >    UINTN                                BspIndex;
> >    UINTN                                ProcessorCount;
> >    PROCESSOR_INFO                       *ProcessorInfo;
> > +  UINT32                               FitMicrocodeEntryCount;
> > +  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;
> >  };
> >
> >  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/MicrocodeUpdate
> > Dx
> > e.i
> > nf
> > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate
> > Dx
> > e.i
> > nf
> > index dbc90857a0a5..24f06c23d404 100644
> > ---
> > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate
> > Dx
> > e.i
> > nf
> > +++
> > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate
> > Dx
> > e.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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel