]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c
Remove IntelSiliconPkg that has been moved to edk2-platform repo
[mirror_edk2.git] / IntelSiliconPkg / Feature / Capsule / MicrocodeUpdateDxe / MicrocodeUpdate.c
diff --git a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c
deleted file mode 100644 (file)
index 8491497..0000000
+++ /dev/null
@@ -1,1326 +0,0 @@
-/** @file\r
-  SetImage instance to update Microcode.\r
-\r
-  Caution: This module requires additional review when modified.\r
-  This module will have external input - capsule image.\r
-  This external input must be validated carefully to avoid security issue like\r
-  buffer overflow, integer overflow.\r
-\r
-  MicrocodeWrite() and VerifyMicrocode() will receive untrusted input and do basic validation.\r
-\r
-  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "MicrocodeUpdate.h"\r
-\r
-/**\r
-  Get Microcode Region.\r
-\r
-  @param[out] MicrocodePatchAddress      The address of Microcode\r
-  @param[out] MicrocodePatchRegionSize   The region size of Microcode\r
-\r
-  @retval TRUE   The Microcode region is returned.\r
-  @retval FALSE  No Microcode region.\r
-**/\r
-BOOLEAN\r
-GetMicrocodeRegion (\r
-  OUT VOID     **MicrocodePatchAddress,\r
-  OUT UINTN    *MicrocodePatchRegionSize\r
-  )\r
-{\r
-  *MicrocodePatchAddress = (VOID *)(UINTN)PcdGet64(PcdCpuMicrocodePatchAddress);\r
-  *MicrocodePatchRegionSize = (UINTN)PcdGet64(PcdCpuMicrocodePatchRegionSize);\r
-\r
-  if ((*MicrocodePatchAddress == NULL) || (*MicrocodePatchRegionSize == 0)) {\r
-    return FALSE;\r
-  }\r
-\r
-  return TRUE;\r
-}\r
-\r
-/**\r
-  Get Microcode update signature of currently loaded Microcode update.\r
-\r
-  @return  Microcode signature.\r
-\r
-**/\r
-UINT32\r
-GetCurrentMicrocodeSignature (\r
-  VOID\r
-  )\r
-{\r
-  UINT64 Signature;\r
-\r
-  AsmWriteMsr64(MSR_IA32_BIOS_SIGN_ID, 0);\r
-  AsmCpuid(CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);\r
-  Signature = AsmReadMsr64(MSR_IA32_BIOS_SIGN_ID);\r
-  return (UINT32)RShiftU64(Signature, 32);\r
-}\r
-\r
-/**\r
-  Get current processor signature.\r
-\r
-  @return current processor signature.\r
-**/\r
-UINT32\r
-GetCurrentProcessorSignature (\r
-  VOID\r
-  )\r
-{\r
-  UINT32                                  RegEax;\r
-  AsmCpuid(CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);\r
-  return RegEax;\r
-}\r
-\r
-/**\r
-  Get current platform ID.\r
-\r
-  @return current platform ID.\r
-**/\r
-UINT8\r
-GetCurrentPlatformId (\r
-  VOID\r
-  )\r
-{\r
-  UINT8                                   PlatformId;\r
-\r
-  PlatformId = (UINT8)AsmMsrBitFieldRead64(MSR_IA32_PLATFORM_ID, 50, 52);\r
-  return PlatformId;\r
-}\r
-\r
-/**\r
-  Load new Microcode.\r
-\r
-  @param[in] Address  The address of new Microcode.\r
-\r
-  @return  Loaded Microcode signature.\r
-\r
-**/\r
-UINT32\r
-LoadMicrocode (\r
-  IN UINT64  Address\r
-  )\r
-{\r
-  AsmWriteMsr64(MSR_IA32_BIOS_UPDT_TRIG, Address);\r
-  return GetCurrentMicrocodeSignature();\r
-}\r
-\r
-/**\r
-  Load Microcode on an Application Processor.\r
-  The function prototype for invoking a function on an Application Processor.\r
-\r
-  @param[in,out] Buffer  The pointer to private data buffer.\r
-**/\r
-VOID\r
-EFIAPI\r
-MicrocodeLoadAp (\r
-  IN OUT VOID  *Buffer\r
-  )\r
-{\r
-  MICROCODE_LOAD_BUFFER                *MicrocodeLoadBuffer;\r
-\r
-  MicrocodeLoadBuffer = Buffer;\r
-  MicrocodeLoadBuffer->Revision = LoadMicrocode (MicrocodeLoadBuffer->Address);\r
-}\r
-\r
-/**\r
-  Load new Microcode on this processor\r
-\r
-  @param[in]  MicrocodeFmpPrivate        The Microcode driver private data\r
-  @param[in]  CpuIndex                   The index of the processor.\r
-  @param[in]  Address                    The address of new Microcode.\r
-\r
-  @return  Loaded Microcode signature.\r
-\r
-**/\r
-UINT32\r
-LoadMicrocodeOnThis (\r
-  IN  MICROCODE_FMP_PRIVATE_DATA  *MicrocodeFmpPrivate,\r
-  IN  UINTN                       CpuIndex,\r
-  IN  UINT64                      Address\r
-  )\r
-{\r
-  EFI_STATUS                           Status;\r
-  EFI_MP_SERVICES_PROTOCOL             *MpService;\r
-  MICROCODE_LOAD_BUFFER                MicrocodeLoadBuffer;\r
-\r
-  if (CpuIndex == MicrocodeFmpPrivate->BspIndex) {\r
-    return LoadMicrocode (Address);\r
-  } else {\r
-    MpService = MicrocodeFmpPrivate->MpService;\r
-    MicrocodeLoadBuffer.Address = Address;\r
-    MicrocodeLoadBuffer.Revision = 0;\r
-    Status = MpService->StartupThisAP (\r
-                          MpService,\r
-                          MicrocodeLoadAp,\r
-                          CpuIndex,\r
-                          NULL,\r
-                          0,\r
-                          &MicrocodeLoadBuffer,\r
-                          NULL\r
-                          );\r
-    ASSERT_EFI_ERROR(Status);\r
-    return MicrocodeLoadBuffer.Revision;\r
-  }\r
-}\r
-\r
-/**\r
-  Collect processor information.\r
-  The function prototype for invoking a function on an Application Processor.\r
-\r
-  @param[in,out] Buffer  The pointer to private data buffer.\r
-**/\r
-VOID\r
-EFIAPI\r
-CollectProcessorInfo (\r
-  IN OUT VOID  *Buffer\r
-  )\r
-{\r
-  PROCESSOR_INFO  *ProcessorInfo;\r
-\r
-  ProcessorInfo = Buffer;\r
-  ProcessorInfo->ProcessorSignature = GetCurrentProcessorSignature();\r
-  ProcessorInfo->PlatformId = GetCurrentPlatformId();\r
-  ProcessorInfo->MicrocodeRevision = GetCurrentMicrocodeSignature();\r
-}\r
-\r
-/**\r
-  Get current Microcode information.\r
-\r
-  The ProcessorInformation (BspIndex/ProcessorCount/ProcessorInfo)\r
-  in MicrocodeFmpPrivate must be initialized.\r
-\r
-  The MicrocodeInformation (DescriptorCount/ImageDescriptor/MicrocodeInfo)\r
-  in MicrocodeFmpPrivate may not be avaiable in this function.\r
-\r
-  @param[in]   MicrocodeFmpPrivate        The Microcode driver private data\r
-  @param[in]   DescriptorCount            The count of Microcode ImageDescriptor allocated.\r
-  @param[out]  ImageDescriptor            Microcode ImageDescriptor\r
-  @param[out]  MicrocodeInfo              Microcode information\r
-\r
-  @return Microcode count\r
-**/\r
-UINTN\r
-GetMicrocodeInfo (\r
-  IN  MICROCODE_FMP_PRIVATE_DATA     *MicrocodeFmpPrivate,\r
-  IN  UINTN                          DescriptorCount,  OPTIONAL\r
-  OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR  *ImageDescriptor, OPTIONAL\r
-  OUT MICROCODE_INFO                 *MicrocodeInfo    OPTIONAL\r
-  )\r
-{\r
-  VOID                                    *MicrocodePatchAddress;\r
-  UINTN                                   MicrocodePatchRegionSize;\r
-  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;\r
-  UINTN                                   MicrocodeEnd;\r
-  UINTN                                   TotalSize;\r
-  UINTN                                   Count;\r
-  UINT64                                  ImageAttributes;\r
-  BOOLEAN                                 IsInUse;\r
-  EFI_STATUS                              Status;\r
-  UINT32                                  AttemptStatus;\r
-  UINTN                                   TargetCpuIndex;\r
-\r
-  MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;\r
-  MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;\r
-\r
-  DEBUG((DEBUG_INFO, "Microcode Region - 0x%x - 0x%x\n", MicrocodePatchAddress, MicrocodePatchRegionSize));\r
-\r
-  Count = 0;\r
-\r
-  MicrocodeEnd = (UINTN)MicrocodePatchAddress + MicrocodePatchRegionSize;\r
-  MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) MicrocodePatchAddress;\r
-  do {\r
-    if (MicrocodeEntryPoint->HeaderVersion == 0x1 && MicrocodeEntryPoint->LoaderRevision == 0x1) {\r
-      //\r
-      // It is the microcode header. It is not the padding data between microcode patches\r
-      // becasue the padding data should not include 0x00000001 and it should be the repeated\r
-      // byte format (like 0xXYXYXYXY....).\r
-      //\r
-      if (MicrocodeEntryPoint->DataSize == 0) {\r
-        TotalSize = 2048;\r
-      } else {\r
-        TotalSize = MicrocodeEntryPoint->TotalSize;\r
-      }\r
-\r
-      TargetCpuIndex = (UINTN)-1;\r
-      Status = VerifyMicrocode(MicrocodeFmpPrivate, MicrocodeEntryPoint, TotalSize, FALSE, &AttemptStatus, NULL, &TargetCpuIndex);\r
-      if (!EFI_ERROR(Status)) {\r
-        IsInUse = TRUE;\r
-        ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount);\r
-        MicrocodeFmpPrivate->ProcessorInfo[TargetCpuIndex].MicrocodeIndex = Count;\r
-      } else {\r
-        IsInUse = FALSE;\r
-      }\r
-\r
-      if (ImageDescriptor != NULL && DescriptorCount > Count) {\r
-        ImageDescriptor[Count].ImageIndex = (UINT8)(Count + 1);\r
-        CopyGuid (&ImageDescriptor[Count].ImageTypeId, &gMicrocodeFmpImageTypeIdGuid);\r
-        ImageDescriptor[Count].ImageId = LShiftU64(MicrocodeEntryPoint->ProcessorFlags, 32) + MicrocodeEntryPoint->ProcessorSignature.Uint32;\r
-        ImageDescriptor[Count].ImageIdName = NULL;\r
-        ImageDescriptor[Count].Version = MicrocodeEntryPoint->UpdateRevision;\r
-        ImageDescriptor[Count].VersionName = NULL;\r
-        ImageDescriptor[Count].Size = TotalSize;\r
-        ImageAttributes = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | IMAGE_ATTRIBUTE_RESET_REQUIRED;\r
-        if (IsInUse) {\r
-          ImageAttributes |= IMAGE_ATTRIBUTE_IN_USE;\r
-        }\r
-        ImageDescriptor[Count].AttributesSupported = ImageAttributes | IMAGE_ATTRIBUTE_IN_USE;\r
-        ImageDescriptor[Count].AttributesSetting = ImageAttributes;\r
-        ImageDescriptor[Count].Compatibilities = 0;\r
-        ImageDescriptor[Count].LowestSupportedImageVersion = MicrocodeEntryPoint->UpdateRevision; // do not support rollback\r
-        ImageDescriptor[Count].LastAttemptVersion = 0;\r
-        ImageDescriptor[Count].LastAttemptStatus = 0;\r
-        ImageDescriptor[Count].HardwareInstance = 0;\r
-      }\r
-      if (MicrocodeInfo != NULL && DescriptorCount > Count) {\r
-        MicrocodeInfo[Count].MicrocodeEntryPoint = MicrocodeEntryPoint;\r
-        MicrocodeInfo[Count].TotalSize = TotalSize;\r
-        MicrocodeInfo[Count].InUse = IsInUse;\r
-      }\r
-    } else {\r
-      //\r
-      // It is the padding data between the microcode patches for microcode patches alignment.\r
-      // Because the microcode patch is the multiple of 1-KByte, the padding data should not\r
-      // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode\r
-      // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to\r
-      // find the next possible microcode patch header.\r
-      //\r
-      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);\r
-      continue;\r
-    }\r
-\r
-    Count++;\r
-    ASSERT(Count < 0xFF);\r
-\r
-    //\r
-    // Get the next patch.\r
-    //\r
-    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);\r
-  } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));\r
-\r
-  return Count;\r
-}\r
-\r
-/**\r
-  Return matched processor information.\r
-\r
-  @param[in]  MicrocodeFmpPrivate        The Microcode driver private data\r
-  @param[in]  ProcessorSignature         The processor signature to be matched\r
-  @param[in]  ProcessorFlags             The processor flags to be matched\r
-  @param[in, out] TargetCpuIndex         On input, the index of target CPU which tries to match the Microcode. (UINTN)-1 means to try all.\r
-                                         On output, the index of target CPU which matches the Microcode.\r
-\r
-  @return matched processor information.\r
-**/\r
-PROCESSOR_INFO *\r
-GetMatchedProcessor (\r
-  IN MICROCODE_FMP_PRIVATE_DATA  *MicrocodeFmpPrivate,\r
-  IN UINT32                      ProcessorSignature,\r
-  IN UINT32                      ProcessorFlags,\r
-  IN OUT UINTN                   *TargetCpuIndex\r
-  )\r
-{\r
-  UINTN  Index;\r
-\r
-  if (*TargetCpuIndex != (UINTN)-1) {\r
-    Index = *TargetCpuIndex;\r
-    if ((ProcessorSignature == MicrocodeFmpPrivate->ProcessorInfo[Index].ProcessorSignature) &&\r
-        ((ProcessorFlags & (1 << MicrocodeFmpPrivate->ProcessorInfo[Index].PlatformId)) != 0)) {\r
-      return &MicrocodeFmpPrivate->ProcessorInfo[Index];\r
-    } else {\r
-      return NULL;\r
-    }\r
-  }\r
-\r
-  for (Index = 0; Index < MicrocodeFmpPrivate->ProcessorCount; Index++) {\r
-    if ((ProcessorSignature == MicrocodeFmpPrivate->ProcessorInfo[Index].ProcessorSignature) &&\r
-        ((ProcessorFlags & (1 << MicrocodeFmpPrivate->ProcessorInfo[Index].PlatformId)) != 0)) {\r
-      *TargetCpuIndex = Index;\r
-      return &MicrocodeFmpPrivate->ProcessorInfo[Index];\r
-    }\r
-  }\r
-  return NULL;\r
-}\r
-\r
-/**\r
-  Verify Microcode.\r
-\r
-  Caution: This function may receive untrusted input.\r
-\r
-  @param[in]  MicrocodeFmpPrivate        The Microcode driver private data\r
-  @param[in]  Image                      The Microcode image buffer.\r
-  @param[in]  ImageSize                  The size of Microcode image buffer in bytes.\r
-  @param[in]  TryLoad                    Try to load Microcode or not.\r
-  @param[out] LastAttemptStatus          The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
-  @param[out] AbortReason                A pointer to a pointer to a null-terminated string providing more\r
-                                         details for the aborted operation. The buffer is allocated by this function\r
-                                         with AllocatePool(), and it is the caller's responsibility to free it with a\r
-                                         call to FreePool().\r
-  @param[in, out] TargetCpuIndex         On input, the index of target CPU which tries to match the Microcode. (UINTN)-1 means to try all.\r
-                                         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 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
-**/\r
-EFI_STATUS\r
-VerifyMicrocode (\r
-  IN  MICROCODE_FMP_PRIVATE_DATA  *MicrocodeFmpPrivate,\r
-  IN  VOID                        *Image,\r
-  IN  UINTN                       ImageSize,\r
-  IN  BOOLEAN                     TryLoad,\r
-  OUT UINT32                      *LastAttemptStatus,\r
-  OUT CHAR16                      **AbortReason,   OPTIONAL\r
-  IN OUT UINTN                    *TargetCpuIndex\r
-  )\r
-{\r
-  UINTN                                   Index;\r
-  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;\r
-  UINTN                                   TotalSize;\r
-  UINTN                                   DataSize;\r
-  UINT32                                  CurrentRevision;\r
-  PROCESSOR_INFO                          *ProcessorInfo;\r
-  UINT32                                  InCompleteCheckSum32;\r
-  UINT32                                  CheckSum32;\r
-  UINTN                                   ExtendedTableLength;\r
-  UINT32                                  ExtendedTableCount;\r
-  CPU_MICROCODE_EXTENDED_TABLE            *ExtendedTable;\r
-  CPU_MICROCODE_EXTENDED_TABLE_HEADER     *ExtendedTableHeader;\r
-  BOOLEAN                                 CorrectMicrocode;\r
-\r
-  //\r
-  // Check HeaderVersion\r
-  //\r
-  MicrocodeEntryPoint = Image;\r
-  if (MicrocodeEntryPoint->HeaderVersion != 0x1) {\r
-    DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on HeaderVersion\n"));\r
-    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;\r
-    if (AbortReason != NULL) {\r
-      *AbortReason = AllocateCopyPool(sizeof(L"InvalidHeaderVersion"), L"InvalidHeaderVersion");\r
-    }\r
-    return EFI_INCOMPATIBLE_VERSION;\r
-  }\r
-  //\r
-  // Check LoaderRevision\r
-  //\r
-  if (MicrocodeEntryPoint->LoaderRevision != 0x1) {\r
-    DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on LoaderRevision\n"));\r
-    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;\r
-    if (AbortReason != NULL) {\r
-      *AbortReason = AllocateCopyPool(sizeof(L"InvalidLoaderVersion"), L"InvalidLoaderVersion");\r
-    }\r
-    return EFI_INCOMPATIBLE_VERSION;\r
-  }\r
-  //\r
-  // Check TotalSize\r
-  //\r
-  if (MicrocodeEntryPoint->DataSize == 0) {\r
-    TotalSize = 2048;\r
-  } else {\r
-    TotalSize = MicrocodeEntryPoint->TotalSize;\r
-  }\r
-  if (TotalSize <= sizeof(CPU_MICROCODE_HEADER)) {\r
-    DEBUG((DEBUG_ERROR, "VerifyMicrocode - TotalSize too small\n"));\r
-    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;\r
-    if (AbortReason != NULL) {\r
-      *AbortReason = AllocateCopyPool(sizeof(L"InvalidTotalSize"), L"InvalidTotalSize");\r
-    }\r
-    return EFI_VOLUME_CORRUPTED;\r
-  }\r
-  if ((TotalSize & (SIZE_1KB - 1)) != 0) {\r
-    DEBUG((DEBUG_ERROR, "VerifyMicrocode - TotalSize is not multiples of 1024 bytes (1 KBytes)\n"));\r
-    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;\r
-    if (AbortReason != NULL) {\r
-      *AbortReason = AllocateCopyPool(sizeof(L"InvalidTotalSize"), L"InvalidTotalSize");\r
-    }\r
-    return EFI_VOLUME_CORRUPTED;\r
-  }\r
-  if (TotalSize != ImageSize) {\r
-    DEBUG((DEBUG_ERROR, "VerifyMicrocode - TotalSize not equal to ImageSize\n"));\r
-    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;\r
-    if (AbortReason != NULL) {\r
-      *AbortReason = AllocateCopyPool(sizeof(L"InvalidTotalSize"), L"InvalidTotalSize");\r
-    }\r
-    return EFI_VOLUME_CORRUPTED;\r
-  }\r
-  //\r
-  // Check DataSize\r
-  //\r
-  if (MicrocodeEntryPoint->DataSize == 0) {\r
-    DataSize = 2048 - sizeof(CPU_MICROCODE_HEADER);\r
-  } else {\r
-    DataSize = MicrocodeEntryPoint->DataSize;\r
-  }\r
-  if (DataSize > TotalSize - sizeof(CPU_MICROCODE_HEADER)) {\r
-    DEBUG((DEBUG_ERROR, "VerifyMicrocode - DataSize too big\n"));\r
-    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;\r
-    if (AbortReason != NULL) {\r
-      *AbortReason = AllocateCopyPool(sizeof(L"InvalidDataSize"), L"InvalidDataSize");\r
-    }\r
-    return EFI_VOLUME_CORRUPTED;\r
-  }\r
-  if ((DataSize & 0x3) != 0) {\r
-    DEBUG((DEBUG_ERROR, "VerifyMicrocode - DataSize is not multiples of DWORDs\n"));\r
-    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;\r
-    if (AbortReason != NULL) {\r
-      *AbortReason = AllocateCopyPool(sizeof(L"InvalidDataSize"), L"InvalidDataSize");\r
-    }\r
-    return EFI_VOLUME_CORRUPTED;\r
-  }\r
-  //\r
-  // Check CheckSum32\r
-  //\r
-  CheckSum32 = CalculateSum32((UINT32 *)MicrocodeEntryPoint, DataSize + sizeof(CPU_MICROCODE_HEADER));\r
-  if (CheckSum32 != 0) {\r
-    DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on CheckSum32\n"));\r
-    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;\r
-    if (AbortReason != NULL) {\r
-      *AbortReason = AllocateCopyPool(sizeof(L"InvalidChecksum"), L"InvalidChecksum");\r
-    }\r
-    return EFI_VOLUME_CORRUPTED;\r
-  }\r
-  InCompleteCheckSum32 = CheckSum32;\r
-  InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorSignature.Uint32;\r
-  InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorFlags;\r
-  InCompleteCheckSum32 -= MicrocodeEntryPoint->Checksum;\r
-\r
-  //\r
-  // Check ProcessorSignature/ProcessorFlags\r
-  //\r
-\r
-  ProcessorInfo = GetMatchedProcessor (MicrocodeFmpPrivate, MicrocodeEntryPoint->ProcessorSignature.Uint32, MicrocodeEntryPoint->ProcessorFlags, TargetCpuIndex);\r
-  if (ProcessorInfo == NULL) {\r
-    CorrectMicrocode = FALSE;\r
-    ExtendedTableLength = TotalSize - (DataSize + sizeof(CPU_MICROCODE_HEADER));\r
-    if (ExtendedTableLength != 0) {\r
-      //\r
-      // Extended Table exist, check if the CPU in support list\r
-      //\r
-      ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *)((UINT8 *)(MicrocodeEntryPoint) + DataSize + sizeof(CPU_MICROCODE_HEADER));\r
-      //\r
-      // Calculate Extended Checksum\r
-      //\r
-      if ((ExtendedTableLength > sizeof(CPU_MICROCODE_EXTENDED_TABLE_HEADER)) && ((ExtendedTableLength & 0x3) == 0)) {\r
-        CheckSum32 = CalculateSum32((UINT32 *)ExtendedTableHeader, ExtendedTableLength);\r
-        if (CheckSum32 != 0) {\r
-          //\r
-          // Checksum incorrect\r
-          //\r
-          DEBUG((DEBUG_ERROR, "VerifyMicrocode - The checksum for extended table is incorrect\n"));\r
-        } else {\r
-          //\r
-          // Checksum correct\r
-          //\r
-          ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;\r
-          if (ExtendedTableCount > (ExtendedTableLength - sizeof(CPU_MICROCODE_EXTENDED_TABLE_HEADER)) / sizeof(CPU_MICROCODE_EXTENDED_TABLE)) {\r
-            DEBUG((DEBUG_ERROR, "VerifyMicrocode - ExtendedTableCount %d is too big\n", ExtendedTableCount));\r
-          } else {\r
-            ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *)(ExtendedTableHeader + 1);\r
-            for (Index = 0; Index < ExtendedTableCount; Index++) {\r
-              CheckSum32 = InCompleteCheckSum32;\r
-              CheckSum32 += ExtendedTable->ProcessorSignature.Uint32;\r
-              CheckSum32 += ExtendedTable->ProcessorFlag;\r
-              CheckSum32 += ExtendedTable->Checksum;\r
-              if (CheckSum32 != 0) {\r
-                DEBUG((DEBUG_ERROR, "VerifyMicrocode - The checksum for ExtendedTable entry with index 0x%x is incorrect\n", Index));\r
-              } else {\r
-                //\r
-                // Verify Header\r
-                //\r
-                ProcessorInfo = GetMatchedProcessor (MicrocodeFmpPrivate, ExtendedTable->ProcessorSignature.Uint32, ExtendedTable->ProcessorFlag, TargetCpuIndex);\r
-                if (ProcessorInfo != NULL) {\r
-                  //\r
-                  // Find one\r
-                  //\r
-                  CorrectMicrocode = TRUE;\r
-                  break;\r
-                }\r
-              }\r
-              ExtendedTable++;\r
-            }\r
-          }\r
-        }\r
-      }\r
-    }\r
-    if (!CorrectMicrocode) {\r
-      if (TryLoad) {\r
-        DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on Current ProcessorSignature/ProcessorFlags\n"));\r
-      }\r
-      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;\r
-      if (AbortReason != NULL) {\r
-        *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessorSignature/ProcessorFlags"), L"UnsupportedProcessorSignature/ProcessorFlags");\r
-      }\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Check UpdateRevision\r
-  //\r
-  CurrentRevision = ProcessorInfo->MicrocodeRevision;\r
-  if ((MicrocodeEntryPoint->UpdateRevision < CurrentRevision) ||\r
-      (TryLoad && (MicrocodeEntryPoint->UpdateRevision == CurrentRevision))) {\r
-    if (TryLoad) {\r
-      DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on UpdateRevision\n"));\r
-    }\r
-    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;\r
-    if (AbortReason != NULL) {\r
-      *AbortReason = AllocateCopyPool(sizeof(L"IncorrectRevision"), L"IncorrectRevision");\r
-    }\r
-    return EFI_INCOMPATIBLE_VERSION;\r
-  }\r
-\r
-  //\r
-  // try load MCU\r
-  //\r
-  if (TryLoad) {\r
-    CurrentRevision = LoadMicrocodeOnThis(MicrocodeFmpPrivate, ProcessorInfo->CpuIndex, (UINTN)MicrocodeEntryPoint + sizeof(CPU_MICROCODE_HEADER));\r
-    if (MicrocodeEntryPoint->UpdateRevision != CurrentRevision) {\r
-      DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on LoadMicrocode\n"));\r
-      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;\r
-      if (AbortReason != NULL) {\r
-        *AbortReason = AllocateCopyPool(sizeof(L"InvalidData"), L"InvalidData");\r
-      }\r
-      return EFI_SECURITY_VIOLATION;\r
-    }\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Get next Microcode entrypoint.\r
-\r
-  @param[in]  MicrocodeFmpPrivate        The Microcode driver private data\r
-  @param[in]  MicrocodeEntryPoint        Current Microcode entrypoint\r
-\r
-  @return next Microcode entrypoint.\r
-**/\r
-CPU_MICROCODE_HEADER *\r
-GetNextMicrocode (\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->DescriptorCount; Index++) {\r
-    if (MicrocodeEntryPoint == MicrocodeFmpPrivate->MicrocodeInfo[Index].MicrocodeEntryPoint) {\r
-      if (Index == (UINTN)MicrocodeFmpPrivate->DescriptorCount - 1) {\r
-        // it is last one\r
-        return NULL;\r
-      } else {\r
-        // return next one\r
-        return MicrocodeFmpPrivate->MicrocodeInfo[Index + 1].MicrocodeEntryPoint;\r
-      }\r
-    }\r
-  }\r
-\r
-  ASSERT(FALSE);\r
-  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
-  @param[in]  MicrocodeFmpPrivate        The Microcode driver private data\r
-\r
-  @return current Microcode used region size.\r
-**/\r
-UINTN\r
-GetCurrentMicrocodeUsedRegionSize (\r
-  IN MICROCODE_FMP_PRIVATE_DATA              *MicrocodeFmpPrivate\r
-  )\r
-{\r
-  if (MicrocodeFmpPrivate->DescriptorCount == 0) {\r
-    return 0;\r
-  }\r
-\r
-  return (UINTN)MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeFmpPrivate->DescriptorCount - 1].MicrocodeEntryPoint\r
-         + (UINTN)MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeFmpPrivate->DescriptorCount - 1].TotalSize\r
-         - (UINTN)MicrocodeFmpPrivate->MicrocodePatchAddress;\r
-}\r
-\r
-/**\r
-  Update Microcode.\r
-\r
-  @param[in]   Address            The flash address of Microcode.\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 updated.\r
-  @retval EFI_WRITE_PROTECTED   The flash device is read only.\r
-**/\r
-EFI_STATUS\r
-UpdateMicrocode (\r
-  IN UINT64   Address,\r
-  IN VOID     *Image,\r
-  IN UINTN    ImageSize,\r
-  OUT UINT32  *LastAttemptStatus\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-\r
-  DEBUG((DEBUG_INFO, "PlatformUpdate:"));\r
-  DEBUG((DEBUG_INFO, "  Address - 0x%lx,", Address));\r
-  DEBUG((DEBUG_INFO, "  Length - 0x%x\n", ImageSize));\r
-\r
-  Status = MicrocodeFlashWrite (\r
-             Address,\r
-             Image,\r
-             ImageSize\r
-             );\r
-  if (!EFI_ERROR(Status)) {\r
-    *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
-  } else {\r
-    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
-  }\r
-  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
-  @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
-UpdateMicrocodeFlashRegion (\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
-  UINTN                                   UsedRegionSize;\r
-  EFI_STATUS                              Status;\r
-  VOID                                    *MicrocodePatchScratchBuffer;\r
-  UINT8                                   *ScratchBufferPtr;\r
-  UINTN                                   ScratchBufferSize;\r
-  UINTN                                   RestSize;\r
-  UINTN                                   AvailableSize;\r
-  VOID                                    *NextMicrocodeEntryPoint;\r
-  MICROCODE_INFO                          *MicrocodeInfo;\r
-  UINTN                                   MicrocodeCount;\r
-  UINTN                                   Index;\r
-\r
-  DEBUG((DEBUG_INFO, "UpdateMicrocodeFlashRegion: 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
-  NextMicrocodeEntryPoint = NULL;\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 = GetNextMicrocode(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
-  UsedRegionSize = GetCurrentMicrocodeUsedRegionSize(MicrocodeFmpPrivate);\r
-  DEBUG((DEBUG_INFO, "  UsedRegionSize - 0x%x\n", UsedRegionSize));\r
-  ASSERT (UsedRegionSize >= TargetTotalSize);\r
-  if (TargetMicrocodeEntryPoint != NULL) {\r
-    ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >= ((UINTN)TargetMicrocodeEntryPoint + 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
-  // |<-        UsedRegionSize     ->|\r
-  //\r
-  // (2)\r
-  // +------+-----------+===================+\r
-  // | MCU  | Microcode |      Empty        |\r
-  // +------+-----------+===================+\r
-  //        | TotalSize |\r
-  //        |<-      AvailableSize        ->|\r
-  // |<-UsedRegionSize->|\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 enough space to remove old one and add new one, reorg and replace old microcode.\r
-  //\r
-  if (MicrocodePatchRegionSize - (UsedRegionSize - TargetTotalSize) >= ImageSize) {\r
-    if (TargetMicrocodeEntryPoint == NULL) {\r
-      DEBUG((DEBUG_INFO, "Append new microcode\n"));\r
-      //\r
-      // +------+------------+------+===================+\r
-      // |Other1|   Other    |Other2|      Empty        |\r
-      // +------+------------+------+===================+\r
-      //\r
-      // +------+------------+------+-----------+=======+\r
-      // |Other1|   Other    |Other2| New Image | Empty |\r
-      // +------+------------+------+-----------+=======+\r
-      //\r
-      Status = UpdateMicrocode((UINTN)MicrocodePatchAddress + UsedRegionSize, Image, ImageSize, LastAttemptStatus);\r
-    } else {\r
-      DEBUG((DEBUG_INFO, "Reorg and replace old microcode\n"));\r
-      //\r
-      // +------+------------+------+===================+\r
-      // |Other | Old Image  | ...  |      Empty        |\r
-      // +------+------------+------+===================+\r
-      //\r
-      // +------+---------------+------+================+\r
-      // |Other |   New Image   | ...  |      Empty     |\r
-      // +------+---------------+------+================+\r
-      //\r
-      // 2.1. Copy new image\r
-      CopyMem (ScratchBufferPtr, Image, ImageSize);\r
-      ScratchBufferSize += ImageSize;\r
-      ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
-      // 2.2. Copy rest images after the old image.\r
-      if (NextMicrocodeEntryPoint != 0) {\r
-        RestSize = (UINTN)MicrocodePatchAddress + UsedRegionSize - ((UINTN)NextMicrocodeEntryPoint);\r
-        CopyMem (ScratchBufferPtr, NextMicrocodeEntryPoint, RestSize);\r
-        ScratchBufferSize += RestSize;\r
-        ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
-      }\r
-      Status = UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);\r
-    }\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // 3. The new image can be put in MCU region, but not all others can be put.\r
-  //    So all the unused MCU is removed.\r
-  //\r
-  if (MicrocodePatchRegionSize >= ImageSize) {\r
-    //\r
-    // +------+------------+------+===================+\r
-    // |Other1| Old Image  |Other2|      Empty        |\r
-    // +------+------------+------+===================+\r
-    //\r
-    // +-------------------------------------+--------+\r
-    // |        New Image                    | Other  |\r
-    // +-------------------------------------+--------+\r
-    //\r
-    DEBUG((DEBUG_INFO, "Add new microcode from beginning\n"));\r
-\r
-    MicrocodeCount = MicrocodeFmpPrivate->DescriptorCount;\r
-    MicrocodeInfo = MicrocodeFmpPrivate->MicrocodeInfo;\r
-\r
-    // 3.1. Copy new image\r
-    CopyMem (ScratchBufferPtr, Image, ImageSize);\r
-    ScratchBufferSize += ImageSize;\r
-    ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
-    // 3.2. Copy some others to rest buffer\r
-    for (Index = 0; Index < MicrocodeCount; Index++) {\r
-      if (!MicrocodeInfo[Index].InUse) {\r
-        continue;\r
-      }\r
-      if (MicrocodeInfo[Index].MicrocodeEntryPoint == TargetMicrocodeEntryPoint) {\r
-        continue;\r
-      }\r
-      if (MicrocodeInfo[Index].TotalSize <= MicrocodePatchRegionSize - ScratchBufferSize) {\r
-        CopyMem (ScratchBufferPtr, MicrocodeInfo[Index].MicrocodeEntryPoint, MicrocodeInfo[Index].TotalSize);\r
-        ScratchBufferSize += MicrocodeInfo[Index].TotalSize;\r
-        ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
-      }\r
-    }\r
-    // 3.3. Pad 0xFF\r
-    RestSize = MicrocodePatchRegionSize - ScratchBufferSize;\r
-    if (RestSize > 0) {\r
-      SetMem (ScratchBufferPtr, RestSize, 0xFF);\r
-      ScratchBufferSize += RestSize;\r
-      ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;\r
-    }\r
-    Status = UpdateMicrocode((UINTN)MicrocodePatchAddress, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // 4. The new image size is bigger than the whole MCU region.\r
-  //\r
-  DEBUG((DEBUG_ERROR, "Microcode too big\n"));\r
-  *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;\r
-  Status = EFI_OUT_OF_RESOURCES;\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Write Microcode.\r
-\r
-  Caution: This function may receive untrusted input.\r
-\r
-  @param[in]   MicrocodeFmpPrivate The Microcode driver private data\r
-  @param[in]   Image               The Microcode image buffer.\r
-  @param[in]   ImageSize           The size of Microcode image buffer in bytes.\r
-  @param[out]  LastAttemptVersion  The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
-  @param[out]  LastAttemptStatus   The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
-  @param[out]  AbortReason         A pointer to a pointer to a null-terminated string providing more\r
-                                   details for the aborted operation. The buffer is allocated by this function\r
-                                   with AllocatePool(), and it is the caller's responsibility to free it with a\r
-                                   call to FreePool().\r
-\r
-  @retval EFI_SUCCESS               The Microcode image is written.\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
-**/\r
-EFI_STATUS\r
-MicrocodeWrite (\r
-  IN  MICROCODE_FMP_PRIVATE_DATA   *MicrocodeFmpPrivate,\r
-  IN  VOID                         *Image,\r
-  IN  UINTN                        ImageSize,\r
-  OUT UINT32                       *LastAttemptVersion,\r
-  OUT UINT32                       *LastAttemptStatus,\r
-  OUT CHAR16                       **AbortReason\r
-  )\r
-{\r
-  EFI_STATUS                              Status;\r
-  VOID                                    *AlignedImage;\r
-  CPU_MICROCODE_HEADER                    *TargetMicrocodeEntryPoint;\r
-  UINTN                                   TargetCpuIndex;\r
-  UINTN                                   TargetMicrcodeIndex;\r
-\r
-  //\r
-  // MCU must be 16 bytes aligned\r
-  //\r
-  AlignedImage = AllocateCopyPool(ImageSize, Image);\r
-  if (AlignedImage == NULL) {\r
-    DEBUG((DEBUG_ERROR, "Fail to allocate aligned image\n"));\r
-    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  TargetCpuIndex = (UINTN)-1;\r
-  Status = VerifyMicrocode(MicrocodeFmpPrivate, AlignedImage, ImageSize, TRUE, LastAttemptStatus, AbortReason, &TargetCpuIndex);\r
-  if (EFI_ERROR(Status)) {\r
-    DEBUG((DEBUG_ERROR, "Fail to verify Microcode Region\n"));\r
-    FreePool(AlignedImage);\r
-    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
-  TargetMicrcodeIndex = MicrocodeFmpPrivate->ProcessorInfo[TargetCpuIndex].MicrocodeIndex;\r
-  DEBUG((DEBUG_INFO, "  TargetMicrcodeIndex - 0x%x\n", TargetMicrcodeIndex));\r
-  if (TargetMicrcodeIndex != (UINTN)-1) {\r
-    ASSERT (TargetMicrcodeIndex < MicrocodeFmpPrivate->DescriptorCount);\r
-    TargetMicrocodeEntryPoint = MicrocodeFmpPrivate->MicrocodeInfo[TargetMicrcodeIndex].MicrocodeEntryPoint;\r
-  } else {\r
-    TargetMicrocodeEntryPoint = NULL;\r
-  }\r
-  DEBUG((DEBUG_INFO, "  TargetMicrocodeEntryPoint - 0x%x\n", TargetMicrocodeEntryPoint));\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
-  return Status;\r
-}\r
-\r
-\r