IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
authorStar Zeng <star.zeng@intel.com>
Wed, 28 Mar 2018 08:52:12 +0000 (16:52 +0800)
committerStar Zeng <star.zeng@intel.com>
Wed, 9 May 2018 08:27:30 +0000 (16:27 +0800)
It is the second step for
https://bugzilla.tianocore.org/show_bug.cgi?id=540.

V2: Use error handling instead of ASSERT for FIT table checking result.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c
IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf

index ef5e630..bc1387b 100644 (file)
@@ -272,7 +272,7 @@ FmpSetImage (
   }\r
 \r
   Status = MicrocodeWrite(MicrocodeFmpPrivate, (VOID *)Image, ImageSize, &MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, &MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus, AbortReason);\r
-  DEBUG((DEBUG_INFO, "SetImage - LastAttemp Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));\r
+  DEBUG((DEBUG_INFO, "SetImage - LastAttempt Version - 0x%x, Status - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));\r
   VarStatus = gRT->SetVariable(\r
                      MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME,\r
                      &gEfiCallerIdGuid,\r
@@ -280,7 +280,7 @@ FmpSetImage (
                      sizeof(MicrocodeFmpPrivate->LastAttempt),\r
                      &MicrocodeFmpPrivate->LastAttempt\r
                      );\r
-  DEBUG((DEBUG_INFO, "SetLastAttemp - %r\n", VarStatus));\r
+  DEBUG((DEBUG_INFO, "SetLastAttempt - %r\n", VarStatus));\r
 \r
   if (!EFI_ERROR(Status)) {\r
     InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);\r
@@ -414,6 +414,212 @@ FmpSetPackageInfo (
   return EFI_UNSUPPORTED;\r
 }\r
 \r
+/**\r
+  Sort FIT microcode entries based upon MicrocodeEntryPoint, from low to high.\r
+\r
+  @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
+\r
+**/\r
+VOID\r
+SortFitMicrocodeInfo (\r
+  IN MICROCODE_FMP_PRIVATE_DATA     *MicrocodeFmpPrivate\r
+  )\r
+{\r
+  FIT_MICROCODE_INFO        *FitMicrocodeEntry;\r
+  FIT_MICROCODE_INFO        *NextFitMicrocodeEntry;\r
+  FIT_MICROCODE_INFO        TempFitMicrocodeEntry;\r
+  FIT_MICROCODE_INFO        *FitMicrocodeEntryEnd;\r
+\r
+  FitMicrocodeEntry = MicrocodeFmpPrivate->FitMicrocodeInfo;\r
+  NextFitMicrocodeEntry = FitMicrocodeEntry + 1;\r
+  FitMicrocodeEntryEnd = MicrocodeFmpPrivate->FitMicrocodeInfo + MicrocodeFmpPrivate->FitMicrocodeEntryCount;\r
+  while (FitMicrocodeEntry < FitMicrocodeEntryEnd) {\r
+    while (NextFitMicrocodeEntry < FitMicrocodeEntryEnd) {\r
+      if (FitMicrocodeEntry->MicrocodeEntryPoint > NextFitMicrocodeEntry->MicrocodeEntryPoint) {\r
+        CopyMem (&TempFitMicrocodeEntry, FitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));\r
+        CopyMem (FitMicrocodeEntry, NextFitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));\r
+        CopyMem (NextFitMicrocodeEntry, &TempFitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));\r
+      }\r
+\r
+      NextFitMicrocodeEntry = NextFitMicrocodeEntry + 1;\r
+    }\r
+\r
+    FitMicrocodeEntry     = FitMicrocodeEntry + 1;\r
+    NextFitMicrocodeEntry = FitMicrocodeEntry + 1;\r
+  }\r
+}\r
+\r
+/**\r
+  Initialize FIT microcode information.\r
+\r
+  @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
+\r
+  @return EFI_SUCCESS           FIT microcode information is initialized.\r
+  @return EFI_OUT_OF_RESOURCES  No enough resource for the initialization.\r
+  @return EFI_DEVICE_ERROR      There is something wrong in FIT microcode entry.\r
+**/\r
+EFI_STATUS\r
+InitializeFitMicrocodeInfo (\r
+  IN MICROCODE_FMP_PRIVATE_DATA     *MicrocodeFmpPrivate\r
+  )\r
+{\r
+  UINT64                            FitPointer;\r
+  FIRMWARE_INTERFACE_TABLE_ENTRY    *FitEntry;\r
+  UINT32                            EntryNum;\r
+  UINT32                            MicrocodeEntryNum;\r
+  UINT32                            Index;\r
+  UINTN                             Address;\r
+  VOID                              *MicrocodePatchAddress;\r
+  UINTN                             MicrocodePatchRegionSize;\r
+  FIT_MICROCODE_INFO                *FitMicrocodeInfo;\r
+  FIT_MICROCODE_INFO                *FitMicrocodeInfoNext;\r
+  CPU_MICROCODE_HEADER              *MicrocodeEntryPoint;\r
+  CPU_MICROCODE_HEADER              *MicrocodeEntryPointNext;\r
+  UINTN                             FitMicrocodeIndex;\r
+  MICROCODE_INFO                    *MicrocodeInfo;\r
+  UINTN                             MicrocodeIndex;\r
+\r
+  if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {\r
+    FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);\r
+    MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;\r
+    MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;\r
+  }\r
+\r
+  FitPointer = *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS;\r
+  if ((FitPointer == 0) ||\r
+      (FitPointer == 0xFFFFFFFFFFFFFFFF) ||\r
+      (FitPointer == 0xEEEEEEEEEEEEEEEE)) {\r
+    //\r
+    // No FIT table.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+  FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;\r
+  if ((FitEntry[0].Type != FIT_TYPE_00_HEADER) ||\r
+      (FitEntry[0].Address != FIT_TYPE_00_SIGNATURE)) {\r
+    //\r
+    // Invalid FIT table, treat it as no FIT table.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;\r
+\r
+  //\r
+  // Calculate microcode entry number.\r
+  //\r
+  MicrocodeEntryNum = 0;\r
+  for (Index = 0; Index < EntryNum; Index++) {\r
+    if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {\r
+      MicrocodeEntryNum++;\r
+    }\r
+  }\r
+  if (MicrocodeEntryNum == 0) {\r
+    //\r
+    // No FIT microcode entry.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Allocate buffer.\r
+  //\r
+  MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));\r
+  if (MicrocodeFmpPrivate->FitMicrocodeInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;\r
+\r
+  MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;\r
+  MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;\r
+\r
+  //\r
+  // Collect microcode entry info.\r
+  //\r
+  MicrocodeEntryNum = 0;\r
+  for (Index = 0; Index < EntryNum; Index++) {\r
+    if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {\r
+      Address = (UINTN) FitEntry[Index].Address;\r
+      if ((Address < (UINTN) MicrocodePatchAddress) ||\r
+          (Address >= ((UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize))) {\r
+        DEBUG ((\r
+          DEBUG_ERROR,\r
+          "InitializeFitMicrocodeInfo - Address (0x%x) is not in Microcode Region\n",\r
+          Address\r
+          ));\r
+        goto ErrorExit;\r
+      }\r
+      FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[MicrocodeEntryNum];\r
+      FitMicrocodeInfo->MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) Address;\r
+      if ((*(UINT32 *) Address) == 0xFFFFFFFF) {\r
+        //\r
+        // It is the empty slot as long as the first dword is 0xFFFF_FFFF.\r
+        //\r
+        FitMicrocodeInfo->Empty = TRUE;\r
+      } else {\r
+        FitMicrocodeInfo->Empty = FALSE;\r
+      }\r
+      MicrocodeEntryNum++;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Every microcode should have a FIT microcode entry.\r
+  //\r
+  for (MicrocodeIndex = 0; MicrocodeIndex < MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) {\r
+    MicrocodeInfo = &MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex];\r
+    for (FitMicrocodeIndex = 0; FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount; FitMicrocodeIndex++) {\r
+      FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];\r
+      if (MicrocodeInfo->MicrocodeEntryPoint == FitMicrocodeInfo->MicrocodeEntryPoint) {\r
+        FitMicrocodeInfo->TotalSize = MicrocodeInfo->TotalSize;\r
+        FitMicrocodeInfo->InUse = MicrocodeInfo->InUse;\r
+        break;\r
+      }\r
+    }\r
+    if (FitMicrocodeIndex >= MicrocodeFmpPrivate->FitMicrocodeEntryCount) {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "InitializeFitMicrocodeInfo - There is no FIT microcode entry for Microcode (0x%x)\n",\r
+        MicrocodeInfo->MicrocodeEntryPoint\r
+        ));\r
+      goto ErrorExit;\r
+    }\r
+  }\r
+\r
+  SortFitMicrocodeInfo (MicrocodeFmpPrivate);\r
+\r
+  //\r
+  // Check overlap.\r
+  //\r
+  for (FitMicrocodeIndex = 0; FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount - 1; FitMicrocodeIndex++) {\r
+    FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];\r
+    MicrocodeEntryPoint = FitMicrocodeInfo->MicrocodeEntryPoint;\r
+    FitMicrocodeInfoNext = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex + 1];\r
+    MicrocodeEntryPointNext = FitMicrocodeInfoNext->MicrocodeEntryPoint;\r
+    if ((MicrocodeEntryPoint >= MicrocodeEntryPointNext) ||\r
+        ((FitMicrocodeInfo->TotalSize != 0) &&\r
+         ((UINTN) MicrocodeEntryPoint + FitMicrocodeInfo->TotalSize) >\r
+          (UINTN) MicrocodeEntryPointNext)) {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "InitializeFitMicrocodeInfo - There is overlap between FIT microcode entries (0x%x 0x%x)\n",\r
+        MicrocodeEntryPoint,\r
+        MicrocodeEntryPointNext\r
+        ));\r
+      goto ErrorExit;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+  FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);\r
+  MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;\r
+  MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;\r
+  return EFI_DEVICE_ERROR;\r
+}\r
+\r
 /**\r
   Initialize Processor Microcode Index.\r
 \r
@@ -460,14 +666,16 @@ InitializedProcessorMicrocodeIndex (
 \r
   @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
 \r
-  @return EFI_SUCCESS Microcode Descriptor is initialized.\r
+  @return EFI_SUCCESS           Microcode Descriptor is initialized.\r
+  @return EFI_OUT_OF_RESOURCES  No enough resource for the initialization.\r
 **/\r
 EFI_STATUS\r
 InitializeMicrocodeDescriptor (\r
   IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
   )\r
 {\r
-  UINT8    CurrentMicrocodeCount;\r
+  EFI_STATUS Status;\r
+  UINT8      CurrentMicrocodeCount;\r
 \r
   CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate, 0, NULL, NULL);\r
 \r
@@ -496,6 +704,7 @@ InitializeMicrocodeDescriptor (
   if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {\r
     MicrocodeFmpPrivate->MicrocodeInfo = AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount * sizeof(MICROCODE_INFO));\r
     if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {\r
+      FreePool (MicrocodeFmpPrivate->ImageDescriptor);\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
   }\r
@@ -505,6 +714,14 @@ InitializeMicrocodeDescriptor (
 \r
   InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);\r
 \r
+  Status = InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);\r
+  if (EFI_ERROR(Status)) {\r
+    FreePool (MicrocodeFmpPrivate->ImageDescriptor);\r
+    FreePool (MicrocodeFmpPrivate->MicrocodeInfo);\r
+    DEBUG((DEBUG_ERROR, "InitializeFitMicrocodeInfo - %r\n", Status));\r
+    return Status;\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -513,7 +730,8 @@ InitializeMicrocodeDescriptor (
 \r
   @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
 \r
-  @return EFI_SUCCESS private data is initialized.\r
+  @return EFI_SUCCESS           Processor information is initialized.\r
+  @return EFI_OUT_OF_RESOURCES  No enough resource for the initialization.\r
 **/\r
 EFI_STATUS\r
 InitializeProcessorInfo (\r
@@ -583,6 +801,7 @@ DumpPrivateInfo (
   PROCESSOR_INFO                       *ProcessorInfo;\r
   MICROCODE_INFO                       *MicrocodeInfo;\r
   EFI_FIRMWARE_IMAGE_DESCRIPTOR        *ImageDescriptor;\r
+  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;\r
 \r
   DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));\r
   DEBUG ((DEBUG_INFO, "  ProcessorCount - 0x%x\n", MicrocodeFmpPrivate->ProcessorCount));\r
@@ -635,6 +854,23 @@ DumpPrivateInfo (
     DEBUG((DEBUG_VERBOSE, "    LastAttemptStatus           - 0x%x\n", ImageDescriptor[Index].LastAttemptStatus));\r
     DEBUG((DEBUG_VERBOSE, "    HardwareInstance            - 0x%lx\n", ImageDescriptor[Index].HardwareInstance));\r
   }\r
+\r
+  if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {\r
+    DEBUG ((DEBUG_INFO, "FitMicrocodeInfo:\n"));\r
+    FitMicrocodeInfo = MicrocodeFmpPrivate->FitMicrocodeInfo;\r
+    DEBUG ((DEBUG_INFO, "  FitMicrocodeEntryCount - 0x%x\n", MicrocodeFmpPrivate->FitMicrocodeEntryCount));\r
+    for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; Index++) {\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "  FitMicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x, 0x%x)\n",\r
+        Index,\r
+        FitMicrocodeInfo[Index].MicrocodeEntryPoint,\r
+        FitMicrocodeInfo[Index].TotalSize,\r
+        FitMicrocodeInfo[Index].InUse,\r
+        FitMicrocodeInfo[Index].Empty\r
+        ));\r
+    }\r
+  }\r
 }\r
 \r
 /**\r
@@ -671,8 +907,8 @@ InitializePrivateData (
                      &VarSize,\r
                      &MicrocodeFmpPrivate->LastAttempt\r
                      );\r
-  DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus));\r
-  DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));\r
+  DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus));\r
+  DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));\r
 \r
   Result = GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, &MicrocodeFmpPrivate->MicrocodePatchRegionSize);\r
   if (!Result) {\r
@@ -688,6 +924,7 @@ InitializePrivateData (
 \r
   Status = InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);\r
   if (EFI_ERROR(Status)) {\r
+    FreePool (MicrocodeFmpPrivate->ProcessorInfo);\r
     DEBUG((DEBUG_ERROR, "InitializeMicrocodeDescriptor - %r\n", Status));\r
     return Status;\r
   }\r
index 2cb0adb..9098712 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
index 4442032..3f92c51 100644 (file)
@@ -20,6 +20,8 @@
 #include <Guid/SystemResourceTable.h>\r
 #include <Guid/MicrocodeFmp.h>\r
 \r
+#include <IndustryStandard/FirmwareInterfaceTable.h>\r
+\r
 #include <Protocol/FirmwareManagement.h>\r
 #include <Protocol/MpService.h>\r
 \r
@@ -57,6 +59,13 @@ typedef struct {
   BOOLEAN                InUse;\r
 } MICROCODE_INFO;\r
 \r
+typedef struct {\r
+  CPU_MICROCODE_HEADER   *MicrocodeEntryPoint;\r
+  UINTN                  TotalSize;\r
+  BOOLEAN                InUse;\r
+  BOOLEAN                Empty;\r
+} FIT_MICROCODE_INFO;\r
+\r
 typedef struct {\r
   UINTN                  CpuIndex;\r
   UINT32                 ProcessorSignature;\r
@@ -86,11 +95,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
   UINTN                                BspIndex;\r
   UINTN                                ProcessorCount;\r
   PROCESSOR_INFO                       *ProcessorInfo;\r
+  UINT32                               FitMicrocodeEntryCount;\r
+  FIT_MICROCODE_INFO                   *FitMicrocodeInfo;\r
 };\r
 \r
 typedef struct _MICROCODE_FMP_PRIVATE_DATA  MICROCODE_FMP_PRIVATE_DATA;\r
 \r
-#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME  L"MicrocodeLastAttempVar"\r
+#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME  L"MicrocodeLastAttemptVar"\r
 \r
 /**\r
   Returns a pointer to the MICROCODE_FMP_PRIVATE_DATA structure from the input a as Fmp.\r
index dbc9085..24f06c2 100644 (file)
@@ -3,7 +3,7 @@
 #\r
 # Produce FMP instance to update Microcode.\r
 #\r
-#  Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
 #  which accompanies this distribution.  The full text of the license may be found at\r
@@ -65,6 +65,7 @@
 \r
 [Depex]\r
   gEfiVariableArchProtocolGuid AND\r
+  gEfiVariableWriteArchProtocolGuid AND\r
   gEfiMpServiceProtocolGuid\r
 \r
 [UserExtensions.TianoCore."ExtraFiles"]\r