]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c
IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
[mirror_edk2.git] / IntelSiliconPkg / Feature / Capsule / MicrocodeUpdateDxe / MicrocodeUpdate.c
index 2cb0adbc44d5e8d73a73e73b6db8b989a51f0638..9098712c2fc84a4821fa12daa4d1d42e1335cc42 100644 (file)
@@ -368,7 +368,7 @@ GetMatchedProcessor (
                                          On output, the index of target CPU which matches the Microcode.\r
 \r
   @retval EFI_SUCCESS               The Microcode image passes verification.\r
-  @retval EFI_VOLUME_CORRUPTED      The Microcode image is corrupt.\r
+  @retval EFI_VOLUME_CORRUPTED      The Microcode image is corrupted.\r
   @retval EFI_INCOMPATIBLE_VERSION  The Microcode image version is incorrect.\r
   @retval EFI_UNSUPPORTED           The Microcode ProcessorSignature or ProcessorFlags is incorrect.\r
   @retval EFI_SECURITY_VIOLATION    The Microcode image fails to load.\r
@@ -550,7 +550,7 @@ VerifyMicrocode (
       }\r
       *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;\r
       if (AbortReason != NULL) {\r
-        *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessSignature/ProcessorFlags"), L"UnsupportedProcessSignature/ProcessorFlags");\r
+        *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessorSignature/ProcessorFlags"), L"UnsupportedProcessorSignature/ProcessorFlags");\r
       }\r
       return EFI_UNSUPPORTED;\r
     }\r
@@ -622,6 +622,124 @@ GetNextMicrocode (
   return NULL;\r
 }\r
 \r
+/**\r
+  Get next FIT Microcode entrypoint.\r
+\r
+  @param[in]  MicrocodeFmpPrivate        The Microcode driver private data\r
+  @param[in]  MicrocodeEntryPoint        Current Microcode entrypoint\r
+\r
+  @return next FIT Microcode entrypoint.\r
+**/\r
+CPU_MICROCODE_HEADER *\r
+GetNextFitMicrocode (\r
+  IN MICROCODE_FMP_PRIVATE_DATA              *MicrocodeFmpPrivate,\r
+  IN CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint\r
+  )\r
+{\r
+  UINTN                                   Index;\r
+\r
+  for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; Index++) {\r
+    if (MicrocodeEntryPoint == MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint) {\r
+      if (Index == (UINTN) MicrocodeFmpPrivate->FitMicrocodeEntryCount - 1) {\r
+        // it is last one\r
+        return NULL;\r
+      } else {\r
+        // return next one\r
+        return MicrocodeFmpPrivate->FitMicrocodeInfo[Index + 1].MicrocodeEntryPoint;\r
+      }\r
+    }\r
+  }\r
+\r
+  ASSERT(FALSE);\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Find empty FIT Microcode entrypoint.\r
+\r
+  @param[in]  MicrocodeFmpPrivate        The Microcode driver private data\r
+  @param[in]  ImageSize                  The size of Microcode image buffer in bytes.\r
+  @param[out] AvailableSize              Available size of the empty FIT Microcode entrypoint.\r
+\r
+  @return Empty FIT Microcode entrypoint.\r
+**/\r
+CPU_MICROCODE_HEADER *\r
+FindEmptyFitMicrocode (\r
+  IN MICROCODE_FMP_PRIVATE_DATA              *MicrocodeFmpPrivate,\r
+  IN UINTN                                   ImageSize,\r
+  OUT UINTN                                  *AvailableSize\r
+  )\r
+{\r
+  UINTN                                   Index;\r
+  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;\r
+  CPU_MICROCODE_HEADER                    *NextMicrocodeEntryPoint;\r
+  VOID                                    *MicrocodePatchAddress;\r
+  UINTN                                   MicrocodePatchRegionSize;\r
+\r
+  MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;\r
+  MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;\r
+\r
+  for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; Index++) {\r
+    if (MicrocodeFmpPrivate->FitMicrocodeInfo[Index].Empty) {\r
+      MicrocodeEntryPoint = MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint;\r
+      NextMicrocodeEntryPoint = GetNextFitMicrocode (MicrocodeFmpPrivate, MicrocodeEntryPoint);\r
+      if (NextMicrocodeEntryPoint != NULL) {\r
+        *AvailableSize = (UINTN) NextMicrocodeEntryPoint - (UINTN) MicrocodeEntryPoint;\r
+      } else {\r
+        *AvailableSize = (UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN) MicrocodeEntryPoint;\r
+      }\r
+      if (*AvailableSize >= ImageSize) {\r
+        return MicrocodeEntryPoint;\r
+      }\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Find unused FIT Microcode entrypoint.\r
+\r
+  @param[in]  MicrocodeFmpPrivate        The Microcode driver private data\r
+  @param[in]  ImageSize                  The size of Microcode image buffer in bytes.\r
+  @param[out] AvailableSize              Available size of the unused FIT Microcode entrypoint.\r
+\r
+  @return Unused FIT Microcode entrypoint.\r
+**/\r
+CPU_MICROCODE_HEADER *\r
+FindUnusedFitMicrocode (\r
+  IN MICROCODE_FMP_PRIVATE_DATA              *MicrocodeFmpPrivate,\r
+  IN UINTN                                   ImageSize,\r
+  OUT UINTN                                  *AvailableSize\r
+  )\r
+{\r
+  UINTN                                   Index;\r
+  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;\r
+  CPU_MICROCODE_HEADER                    *NextMicrocodeEntryPoint;\r
+  VOID                                    *MicrocodePatchAddress;\r
+  UINTN                                   MicrocodePatchRegionSize;\r
+\r
+  MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;\r
+  MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;\r
+\r
+  for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; Index++) {\r
+    if (!MicrocodeFmpPrivate->FitMicrocodeInfo[Index].InUse) {\r
+      MicrocodeEntryPoint = MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint;\r
+      NextMicrocodeEntryPoint = GetNextFitMicrocode (MicrocodeFmpPrivate, MicrocodeEntryPoint);\r
+      if (NextMicrocodeEntryPoint != NULL) {\r
+        *AvailableSize = (UINTN) NextMicrocodeEntryPoint - (UINTN) MicrocodeEntryPoint;\r
+      } else {\r
+        *AvailableSize = (UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN) MicrocodeEntryPoint;\r
+      }\r
+      if (*AvailableSize >= ImageSize) {\r
+        return MicrocodeEntryPoint;\r
+      }\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
 /**\r
   Get current Microcode used region size.\r
 \r
@@ -666,7 +784,7 @@ UpdateMicrocode (
 \r
   DEBUG((DEBUG_INFO, "PlatformUpdate:"));\r
   DEBUG((DEBUG_INFO, "  Address - 0x%lx,", Address));\r
-  DEBUG((DEBUG_INFO, "  Legnth - 0x%x\n", ImageSize));\r
+  DEBUG((DEBUG_INFO, "  Length - 0x%x\n", ImageSize));\r
 \r
   Status = MicrocodeFlashWrite (\r
              Address,\r
@@ -681,6 +799,201 @@ UpdateMicrocode (
   return Status;\r
 }\r
 \r
+/**\r
+  Update Microcode flash region with FIT.\r
+\r
+  @param[in]  MicrocodeFmpPrivate        The Microcode driver private data\r
+  @param[in]  TargetMicrocodeEntryPoint  Target Microcode entrypoint to be updated\r
+  @param[in]  Image                      The Microcode image buffer.\r
+  @param[in]  ImageSize                  The size of Microcode image buffer in bytes.\r
+  @param[out] LastAttemptStatus          The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+\r
+  @retval EFI_SUCCESS             The Microcode image is written.\r
+  @retval EFI_WRITE_PROTECTED     The flash device is read only.\r
+**/\r
+EFI_STATUS\r
+UpdateMicrocodeFlashRegionWithFit (\r
+  IN  MICROCODE_FMP_PRIVATE_DATA              *MicrocodeFmpPrivate,\r
+  IN  CPU_MICROCODE_HEADER                    *TargetMicrocodeEntryPoint,\r
+  IN  VOID                                    *Image,\r
+  IN  UINTN                                   ImageSize,\r
+  OUT UINT32                                  *LastAttemptStatus\r
+  )\r
+{\r
+  VOID                                    *MicrocodePatchAddress;\r
+  UINTN                                   MicrocodePatchRegionSize;\r
+  UINTN                                   TargetTotalSize;\r
+  EFI_STATUS                              Status;\r
+  VOID                                    *MicrocodePatchScratchBuffer;\r
+  UINT8                                   *ScratchBufferPtr;\r
+  UINTN                                   ScratchBufferSize;\r
+  UINTN                                   RestSize;\r
+  UINTN                                   AvailableSize;\r
+  VOID                                    *NextMicrocodeEntryPoint;\r
+  VOID                                    *EmptyFitMicrocodeEntry;\r
+  VOID                                    *UnusedFitMicrocodeEntry;\r
+\r
+  DEBUG((DEBUG_INFO, "UpdateMicrocodeFlashRegionWithFit: Image - 0x%x, size - 0x%x\n", Image, ImageSize));\r
+\r
+  MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;\r
+  MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;\r
+\r
+  MicrocodePatchScratchBuffer = AllocateZeroPool (MicrocodePatchRegionSize);\r
+  if (MicrocodePatchScratchBuffer == NULL) {\r
+    DEBUG((DEBUG_ERROR, "Fail to allocate Microcode Scratch buffer\n"));\r
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  ScratchBufferPtr = MicrocodePatchScratchBuffer;\r
+  ScratchBufferSize = 0;\r
+\r
+  //\r
+  // Target data collection\r
+  //\r
+  TargetTotalSize = 0;\r
+  AvailableSize = 0;\r
+  if (TargetMicrocodeEntryPoint != NULL) {\r
+    if (TargetMicrocodeEntryPoint->DataSize == 0) {\r
+      TargetTotalSize = 2048;\r
+    } else {\r
+      TargetTotalSize = TargetMicrocodeEntryPoint->TotalSize;\r
+    }\r
+    DEBUG((DEBUG_INFO, "  TargetTotalSize - 0x%x\n", TargetTotalSize));\r
+    NextMicrocodeEntryPoint = GetNextFitMicrocode (MicrocodeFmpPrivate, TargetMicrocodeEntryPoint);\r
+    DEBUG((DEBUG_INFO, "  NextMicrocodeEntryPoint - 0x%x\n", NextMicrocodeEntryPoint));\r
+    if (NextMicrocodeEntryPoint != NULL) {\r
+      ASSERT ((UINTN) NextMicrocodeEntryPoint >= ((UINTN) TargetMicrocodeEntryPoint + TargetTotalSize));\r
+      AvailableSize = (UINTN) NextMicrocodeEntryPoint - (UINTN) TargetMicrocodeEntryPoint;\r
+    } else {\r
+      AvailableSize = (UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN) TargetMicrocodeEntryPoint;\r
+    }\r
+    DEBUG((DEBUG_INFO, "  AvailableSize - 0x%x\n", AvailableSize));\r
+    ASSERT (AvailableSize >= TargetTotalSize);\r
+  }\r
+  //\r
+  // Total Size means the Microcode size.\r
+  // Available Size means the Microcode size plus the pad till (1) next Microcode or (2) the end.\r
+  //\r
+  // (1)\r
+  // +------+-----------+-----+------+===================+\r
+  // | MCU1 | Microcode | PAD | MCU2 |      Empty        |\r
+  // +------+-----------+-----+------+===================+\r
+  //        | TotalSize |\r
+  //        |<-AvailableSize->|\r
+  //\r
+  // (2)\r
+  // +------+-----------+===================+\r
+  // | MCU  | Microcode |      Empty        |\r
+  // +------+-----------+===================+\r
+  //        | TotalSize |\r
+  //        |<-      AvailableSize        ->|\r
+  //\r
+\r
+  //\r
+  // Update based on policy\r
+  //\r
+\r
+  //\r
+  // 1. If there is enough space to update old one in situ, replace old microcode in situ.\r
+  //\r
+  if (AvailableSize >= ImageSize) {\r
+    DEBUG((DEBUG_INFO, "Replace old microcode in situ\n"));\r
+    //\r
+    // +------+------------+------+===================+\r
+    // |Other | Old Image  | ...  |      Empty        |\r
+    // +------+------------+------+===================+\r
+    //\r
+    // +------+---------+--+------+===================+\r
+    // |Other |New Image|FF| ...  |      Empty        |\r
+    // +------+---------+--+------+===================+\r
+    //\r
+    // 1.1. Copy new image\r
+    CopyMem (ScratchBufferPtr, Image, ImageSize);\r
+    ScratchBufferSize += ImageSize;\r
+    ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
+    // 1.2. Pad 0xFF\r
+    RestSize = AvailableSize - ImageSize;\r
+    if (RestSize > 0) {\r
+      SetMem (ScratchBufferPtr, RestSize, 0xFF);\r
+      ScratchBufferSize += RestSize;\r
+      ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
+    }\r
+    Status = UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // 2. If there is empty FIT microcode entry with enough space, use it.\r
+  //\r
+  EmptyFitMicrocodeEntry = FindEmptyFitMicrocode (MicrocodeFmpPrivate, ImageSize, &AvailableSize);\r
+  if (EmptyFitMicrocodeEntry != NULL) {\r
+    DEBUG((DEBUG_INFO, "Use empty FIT microcode entry\n"));\r
+    // 2.1. Copy new image\r
+    CopyMem (ScratchBufferPtr, Image, ImageSize);\r
+    ScratchBufferSize += ImageSize;\r
+    ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
+    // 2.2. Pad 0xFF\r
+    RestSize = AvailableSize - ImageSize;\r
+    if (RestSize > 0) {\r
+      SetMem (ScratchBufferPtr, RestSize, 0xFF);\r
+      ScratchBufferSize += RestSize;\r
+      ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
+    }\r
+    Status = UpdateMicrocode ((UINTN) EmptyFitMicrocodeEntry, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);\r
+    if (!EFI_ERROR (Status) && (TargetMicrocodeEntryPoint != NULL)) {\r
+      //\r
+      // Empty old microcode.\r
+      //\r
+      ScratchBufferPtr = MicrocodePatchScratchBuffer;\r
+      SetMem (ScratchBufferPtr, TargetTotalSize, 0xFF);\r
+      ScratchBufferSize = TargetTotalSize;\r
+      ScratchBufferPtr = (UINT8 *) MicrocodePatchScratchBuffer + ScratchBufferSize;\r
+      UpdateMicrocode ((UINTN) TargetMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);\r
+    }\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // 3. If there is unused microcode entry with enough space, use it.\r
+  //\r
+  UnusedFitMicrocodeEntry = FindUnusedFitMicrocode (MicrocodeFmpPrivate, ImageSize, &AvailableSize);\r
+  if (UnusedFitMicrocodeEntry != NULL) {\r
+    DEBUG((DEBUG_INFO, "Use unused FIT microcode entry\n"));\r
+    // 3.1. Copy new image\r
+    CopyMem (ScratchBufferPtr, Image, ImageSize);\r
+    ScratchBufferSize += ImageSize;\r
+    ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
+    // 3.2. Pad 0xFF\r
+    RestSize = AvailableSize - ImageSize;\r
+    if (RestSize > 0) {\r
+      SetMem (ScratchBufferPtr, RestSize, 0xFF);\r
+      ScratchBufferSize += RestSize;\r
+      ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
+    }\r
+    Status = UpdateMicrocode ((UINTN) UnusedFitMicrocodeEntry, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);\r
+    if (!EFI_ERROR (Status) && (TargetMicrocodeEntryPoint != NULL)) {\r
+      //\r
+      // Empty old microcode.\r
+      //\r
+      ScratchBufferPtr = MicrocodePatchScratchBuffer;\r
+      SetMem (ScratchBufferPtr, TargetTotalSize, 0xFF);\r
+      ScratchBufferSize = TargetTotalSize;\r
+      ScratchBufferPtr = (UINT8 *) MicrocodePatchScratchBuffer + ScratchBufferSize;\r
+      UpdateMicrocode ((UINTN) TargetMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);\r
+    }\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // 4. No usable FIT microcode entry.\r
+  //\r
+  DEBUG((DEBUG_ERROR, "No usable FIT microcode entry\n"));\r
+  *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;\r
+  Status = EFI_OUT_OF_RESOURCES;\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   Update Microcode flash region.\r
 \r
@@ -753,8 +1066,8 @@ UpdateMicrocodeFlashRegion (
       AvailableSize = (UINTN)MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN)TargetMicrocodeEntryPoint;\r
     }\r
     DEBUG((DEBUG_INFO, "  AvailableSize - 0x%x\n", AvailableSize));\r
+    ASSERT (AvailableSize >= TargetTotalSize);\r
   }\r
-  ASSERT (AvailableSize >= TargetTotalSize);\r
   UsedRegionSize = GetCurrentMicrocodeUsedRegionSize(MicrocodeFmpPrivate);\r
   DEBUG((DEBUG_INFO, "  UsedRegionSize - 0x%x\n", UsedRegionSize));\r
   ASSERT (UsedRegionSize >= TargetTotalSize);\r
@@ -762,8 +1075,8 @@ UpdateMicrocodeFlashRegion (
     ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >= ((UINTN)TargetMicrocodeEntryPoint + TargetTotalSize));\r
   }\r
   //\r
-  // Total Size means the Microcode data size.\r
-  // Available Size means the Microcode data size plus the pad till (1) next Microcode or (2) the end.\r
+  // Total Size means the Microcode size.\r
+  // Available Size means the Microcode size plus the pad till (1) next Microcode or (2) the end.\r
   //\r
   // (1)\r
   // +------+-----------+-----+------+===================+\r
@@ -793,11 +1106,11 @@ UpdateMicrocodeFlashRegion (
     DEBUG((DEBUG_INFO, "Replace old microcode in situ\n"));\r
     //\r
     // +------+------------+------+===================+\r
-    // |Other1| Old Image  |Other2|      Empty        |\r
+    // |Other | Old Image  | ...  |      Empty        |\r
     // +------+------------+------+===================+\r
     //\r
     // +------+---------+--+------+===================+\r
-    // |Other1|New Image|FF|Other2|      Empty        |\r
+    // |Other |New Image|FF| ...  |      Empty        |\r
     // +------+---------+--+------+===================+\r
     //\r
     // 1.1. Copy new image\r
@@ -835,11 +1148,11 @@ UpdateMicrocodeFlashRegion (
       DEBUG((DEBUG_INFO, "Reorg and replace old microcode\n"));\r
       //\r
       // +------+------------+------+===================+\r
-      // |Other1| Old Image  |Other2|      Empty        |\r
+      // |Other | Old Image  | ...  |      Empty        |\r
       // +------+------------+------+===================+\r
       //\r
       // +------+---------------+------+================+\r
-      // |Other1|   New Image   |Other2|      Empty     |\r
+      // |Other |   New Image   | ...  |      Empty     |\r
       // +------+---------------+------+================+\r
       //\r
       // 2.1. Copy new image\r
@@ -849,7 +1162,7 @@ UpdateMicrocodeFlashRegion (
       // 2.2. Copy rest images after the old image.\r
       if (NextMicrocodeEntryPoint != 0) {\r
         RestSize = (UINTN)MicrocodePatchAddress + UsedRegionSize - ((UINTN)NextMicrocodeEntryPoint);\r
-        CopyMem (ScratchBufferPtr, (UINT8 *)TargetMicrocodeEntryPoint + TargetTotalSize, RestSize);\r
+        CopyMem (ScratchBufferPtr, NextMicrocodeEntryPoint, RestSize);\r
         ScratchBufferSize += RestSize;\r
         ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
       }\r
@@ -932,7 +1245,7 @@ UpdateMicrocodeFlashRegion (
                                    call to FreePool().\r
 \r
   @retval EFI_SUCCESS               The Microcode image is written.\r
-  @retval EFI_VOLUME_CORRUPTED      The Microcode image is corrupt.\r
+  @retval EFI_VOLUME_CORRUPTED      The Microcode image is corrupted.\r
   @retval EFI_INCOMPATIBLE_VERSION  The Microcode image version is incorrect.\r
   @retval EFI_SECURITY_VIOLATION    The Microcode image fails to load.\r
   @retval EFI_WRITE_PROTECTED       The flash device is read only.\r
@@ -963,7 +1276,6 @@ MicrocodeWrite (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  *LastAttemptVersion = ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision;\r
   TargetCpuIndex = (UINTN)-1;\r
   Status = VerifyMicrocode(MicrocodeFmpPrivate, AlignedImage, ImageSize, TRUE, LastAttemptStatus, AbortReason, &TargetCpuIndex);\r
   if (EFI_ERROR(Status)) {\r
@@ -972,6 +1284,7 @@ MicrocodeWrite (
     return Status;\r
   }\r
   DEBUG((DEBUG_INFO, "Pass VerifyMicrocode\n"));\r
+  *LastAttemptVersion = ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision;\r
 \r
   DEBUG((DEBUG_INFO, "  TargetCpuIndex - 0x%x\n", TargetCpuIndex));\r
   ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount);\r
@@ -985,13 +1298,23 @@ MicrocodeWrite (
   }\r
   DEBUG((DEBUG_INFO, "  TargetMicrocodeEntryPoint - 0x%x\n", TargetMicrocodeEntryPoint));\r
 \r
-  Status = UpdateMicrocodeFlashRegion(\r
-             MicrocodeFmpPrivate,\r
-             TargetMicrocodeEntryPoint,\r
-             AlignedImage,\r
-             ImageSize,\r
-             LastAttemptStatus\r
-             );\r
+  if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {\r
+    Status = UpdateMicrocodeFlashRegionWithFit (\r
+               MicrocodeFmpPrivate,\r
+               TargetMicrocodeEntryPoint,\r
+               AlignedImage,\r
+               ImageSize,\r
+               LastAttemptStatus\r
+               );\r
+  } else {\r
+    Status = UpdateMicrocodeFlashRegion (\r
+               MicrocodeFmpPrivate,\r
+               TargetMicrocodeEntryPoint,\r
+               AlignedImage,\r
+               ImageSize,\r
+               LastAttemptStatus\r
+               );\r
+  }\r
 \r
   FreePool(AlignedImage);\r
 \r