]> git.proxmox.com Git - mirror_edk2.git/blobdiff - FmpDevicePkg/FmpDxe/FmpDxe.c
FmdDevicePkg/FmpDxe: Support Fmp Capsule Dependency.
[mirror_edk2.git] / FmpDevicePkg / FmpDxe / FmpDxe.c
index dab3310834c113a05cdcc5d15c2eda91f7d6aaf3..aa92331966c0ae9285573f9650882da5ae19faf8 100644 (file)
@@ -4,13 +4,15 @@
   information provided through PCDs and libraries.\r
 \r
   Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>\r
-  Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>\r
 \r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "FmpDxe.h"\r
+#include "VariableSupport.h"\r
+#include "Dependency.h"\r
 \r
 ///\r
 /// FILE_GUID from FmpDxe.inf.  When FmpDxe.inf is used in a platform, the\r
@@ -73,7 +75,13 @@ const FIRMWARE_MANAGEMENT_PRIVATE_DATA  mFirmwareManagementPrivateDataTemplate =
   NULL,                                        // VersionName\r
   TRUE,                                        // RuntimeVersionSupported\r
   NULL,                                        // FmpDeviceLockEvent\r
-  FALSE                                        // FmpDeviceLocked\r
+  FALSE,                                       // FmpDeviceLocked\r
+  NULL,                                        // FmpDeviceContext\r
+  NULL,                                        // VersionVariableName\r
+  NULL,                                        // LsvVariableName\r
+  NULL,                                        // LastAttemptStatusVariableName\r
+  NULL,                                        // LastAttemptVersionVariableName\r
+  NULL                                         // FmpStateVariableName\r
 };\r
 \r
 ///\r
@@ -140,9 +148,11 @@ FmpDxeProgress (
 /**\r
   Returns a pointer to the ImageTypeId GUID value.  An attempt is made to get\r
   the GUID value from the FmpDeviceLib. If the FmpDeviceLib does not provide\r
-  a GUID value, then gEfiCallerIdGuid is returned.\r
+  a GUID value, then PcdFmpDeviceImageTypeIdGuid is used.  If the size of\r
+  PcdFmpDeviceImageTypeIdGuid is not the size of EFI_GUID, then gEfiCallerIdGuid\r
+  is returned.\r
 \r
-  @return  The ImageTypeId GUID\r
+  @retval  The ImageTypeId GUID\r
 \r
 **/\r
 EFI_GUID *\r
@@ -152,18 +162,26 @@ GetImageTypeIdGuid (
 {\r
   EFI_STATUS  Status;\r
   EFI_GUID    *FmpDeviceLibGuid;\r
+  UINTN       ImageTypeIdGuidSize;\r
 \r
   FmpDeviceLibGuid = NULL;\r
   Status = FmpDeviceGetImageTypeIdGuidPtr (&FmpDeviceLibGuid);\r
   if (EFI_ERROR (Status)) {\r
     if (Status != EFI_UNSUPPORTED) {\r
-      DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", Status));\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", mImageIdName, Status));\r
     }\r
-    return &gEfiCallerIdGuid;\r
+  } else if (FmpDeviceLibGuid == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n", mImageIdName));\r
+    Status = EFI_NOT_FOUND;\r
   }\r
-  if (FmpDeviceLibGuid == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n"));\r
-    return &gEfiCallerIdGuid;\r
+  if (EFI_ERROR (Status)) {\r
+    ImageTypeIdGuidSize = PcdGetSize (PcdFmpDeviceImageTypeIdGuid);\r
+    if (ImageTypeIdGuidSize == sizeof (EFI_GUID)) {\r
+      FmpDeviceLibGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceImageTypeIdGuid);\r
+    } else {\r
+      DEBUG ((DEBUG_INFO, "FmpDxe(%s): Fall back to ImageTypeIdGuid of gEfiCallerIdGuid\n", mImageIdName));\r
+      FmpDeviceLibGuid = &gEfiCallerIdGuid;\r
+    }\r
   }\r
   return FmpDeviceLibGuid;\r
 }\r
@@ -171,7 +189,7 @@ GetImageTypeIdGuid (
 /**\r
   Returns a pointer to the Null-terminated Unicode ImageIdName string.\r
 \r
-  @return  Null-terminated Unicode ImageIdName string.\r
+  @retval  Null-terminated Unicode ImageIdName string.\r
 \r
 **/\r
 CHAR16 *\r
@@ -188,12 +206,15 @@ GetImageTypeNameString (
   2. Check if we have a variable for lowest supported version (this will be updated with each capsule applied)\r
   3. Check Fixed at build PCD\r
 \r
-  @return  The largest value\r
+  @param[in] Private  Pointer to the private context structure for the\r
+                      Firmware Management Protocol instance.\r
+\r
+  @retval  The largest value\r
 \r
 **/\r
 UINT32\r
 GetLowestSupportedVersion (\r
-  VOID\r
+  FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private\r
   )\r
 {\r
   EFI_STATUS  Status;\r
@@ -230,7 +251,7 @@ GetLowestSupportedVersion (
   //\r
   // Check the lowest supported version UEFI variable for this device\r
   //\r
-  VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable();\r
+  VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable (Private);\r
   if (VariableLowestSupportedVersion > ReturnLsv) {\r
     ReturnLsv = VariableLowestSupportedVersion;\r
   }\r
@@ -255,6 +276,13 @@ PopulateDescriptor (
   )\r
 {\r
   EFI_STATUS  Status;\r
+  VOID        *Image;\r
+  UINTN       ImageSize;\r
+  BOOLEAN     IsDepexValid;\r
+  UINT32      DepexSize;\r
+\r
+  Image     = NULL;\r
+  ImageSize = 0;\r
 \r
   if (Private->DescriptorPopulated) {\r
     return;\r
@@ -265,6 +293,20 @@ PopulateDescriptor (
   Private->Descriptor.ImageId     = Private->Descriptor.ImageIndex;\r
   Private->Descriptor.ImageIdName = GetImageTypeNameString();\r
 \r
+  //\r
+  // Get the hardware instance from FmpDeviceLib\r
+  //\r
+  Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance);\r
+  if (Status == EFI_UNSUPPORTED) {\r
+    Private->Descriptor.HardwareInstance = 0;\r
+  }\r
+\r
+  //\r
+  // Generate UEFI Variable names used to store status information for this\r
+  // FMP instance.\r
+  //\r
+  GenerateFmpVariableNames (Private);\r
+\r
   //\r
   // Get the version.  Some devices don't support getting the firmware version\r
   // at runtime.  If FmpDeviceLib does not support returning a version, then\r
@@ -273,12 +315,12 @@ PopulateDescriptor (
   Status = FmpDeviceGetVersion (&Private->Descriptor.Version);\r
   if (Status == EFI_UNSUPPORTED) {\r
     Private->RuntimeVersionSupported = FALSE;\r
-    Private->Descriptor.Version = GetVersionFromVariable();\r
+    Private->Descriptor.Version = GetVersionFromVariable (Private);\r
   } else if (EFI_ERROR (Status)) {\r
     //\r
     // Unexpected error.   Use default version.\r
     //\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: GetVersion() from FmpDeviceLib (%s) returned %r\n", GetImageTypeNameString(), Status));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetVersion() from FmpDeviceLib (%s) returned %r\n", mImageIdName, GetImageTypeNameString(), Status));\r
     Private->Descriptor.Version = DEFAULT_VERSION;\r
   }\r
 \r
@@ -296,20 +338,20 @@ PopulateDescriptor (
   //\r
   Status = FmpDeviceGetVersionString (&Private->Descriptor.VersionName);\r
   if (Status == EFI_UNSUPPORTED) {\r
-    DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() unsupported in FmpDeviceLib.\n"));\r
+    DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() unsupported in FmpDeviceLib.\n", mImageIdName));\r
     Private->Descriptor.VersionName = AllocateCopyPool (\r
                                         sizeof (VERSION_STRING_NOT_SUPPORTED),\r
                                         VERSION_STRING_NOT_SUPPORTED\r
                                         );\r
   } else if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() not available in FmpDeviceLib.\n"));\r
+    DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() not available in FmpDeviceLib.\n", mImageIdName));\r
     Private->Descriptor.VersionName = AllocateCopyPool (\r
                                         sizeof (VERSION_STRING_NOT_AVAILABLE),\r
                                         VERSION_STRING_NOT_AVAILABLE\r
                                         );\r
   }\r
 \r
-  Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion();\r
+  Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion (Private);\r
 \r
   //\r
   // Get attributes from the FmpDeviceLib\r
@@ -341,18 +383,50 @@ PopulateDescriptor (
     Private->Descriptor.Size = 0;\r
   }\r
 \r
-  Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable ();\r
-  Private->Descriptor.LastAttemptStatus  = GetLastAttemptStatusFromVariable ();\r
+  Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable (Private);\r
+  Private->Descriptor.LastAttemptStatus  = GetLastAttemptStatusFromVariable (Private);\r
 \r
   //\r
-  // Get the hardware instance from FmpDeviceLib\r
+  // Get the dependency from the FmpDeviceLib and populate it to the descriptor.\r
   //\r
-  Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance);\r
-  if (Status == EFI_UNSUPPORTED) {\r
-    Private->Descriptor.HardwareInstance = 0;\r
+  Private->Descriptor.Dependencies = NULL;\r
+\r
+  //\r
+  // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY\r
+  //\r
+  if (Private->Descriptor.AttributesSupported & IMAGE_ATTRIBUTE_DEPENDENCY) {\r
+    //\r
+    // The parameter "Image" of FmpDeviceGetImage() is extended to contain the dependency.\r
+    // Get the dependency from the Image.\r
+    //\r
+    ImageSize = Private->Descriptor.Size;\r
+    Image = AllocatePool (ImageSize);\r
+    if (Image != NULL) {\r
+      Status = FmpDeviceGetImage (Image, &ImageSize);\r
+      if (Status == EFI_BUFFER_TOO_SMALL) {\r
+        FreePool (Image);\r
+        Image = AllocatePool (ImageSize);\r
+        if (Image != NULL) {\r
+          Status = FmpDeviceGetImage (Image, &ImageSize);\r
+        }\r
+      }\r
+    }\r
+    if (!EFI_ERROR (Status) && Image != NULL) {\r
+      IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP *) Image, ImageSize, &DepexSize);\r
+      if (IsDepexValid == TRUE) {\r
+        Private->Descriptor.Dependencies = AllocatePool (DepexSize);\r
+        if (Private->Descriptor.Dependencies != NULL) {\r
+          CopyMem (Private->Descriptor.Dependencies->Dependencies, Image, DepexSize);\r
+        }\r
+      }\r
+    }\r
   }\r
 \r
   Private->DescriptorPopulated = TRUE;\r
+\r
+  if (Image != NULL) {\r
+    FreePool (Image);\r
+  }\r
 }\r
 \r
 /**\r
@@ -421,7 +495,7 @@ GetTheImageInfo (
   // Check for valid pointer\r
   //\r
   if (ImageInfoSize == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: GetImageInfo() - ImageInfoSize is NULL.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is NULL.\n", mImageIdName));\r
     Status = EFI_INVALID_PARAMETER;\r
     goto cleanup;\r
   }\r
@@ -432,7 +506,7 @@ GetTheImageInfo (
   //\r
   if (*ImageInfoSize < (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR))) {\r
     *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);\r
-    DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImageInfo() - ImageInfoSize is to small.\n"));\r
+    DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is to small.\n", mImageIdName));\r
     Status = EFI_BUFFER_TOO_SMALL;\r
     goto cleanup;\r
   }\r
@@ -442,7 +516,7 @@ GetTheImageInfo (
   //\r
   if ( (ImageInfo == NULL) || (DescriptorVersion == NULL) || (DescriptorCount == NULL) || (DescriptorSize == NULL)\r
        || (PackageVersion == NULL)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: GetImageInfo() - Pointer Parameter is NULL.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - Pointer Parameter is NULL.\n", mImageIdName));\r
     Status = EFI_INVALID_PARAMETER;\r
     goto cleanup;\r
   }\r
@@ -453,7 +527,7 @@ GetTheImageInfo (
   *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);\r
 \r
   //\r
-  // make sure the descriptor has already been loaded\r
+  // Make sure the descriptor has already been loaded or refreshed\r
   //\r
   PopulateDescriptor (Private);\r
 \r
@@ -514,8 +588,17 @@ GetTheImage (
   EFI_STATUS                        Status;\r
   FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;\r
   UINTN                             Size;\r
+  UINT8                             *ImageBuffer;\r
+  UINTN                             ImageBufferSize;\r
+  UINT32                            DepexSize;\r
 \r
-  Status = EFI_SUCCESS;\r
+  if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status          = EFI_SUCCESS;\r
+  ImageBuffer     = NULL;\r
+  DepexSize       = 0;\r
 \r
   //\r
   // Retrieve the private context structure\r
@@ -527,13 +610,13 @@ GetTheImage (
   // Check to make sure index is 1 (only 1 image for this device)\r
   //\r
   if (ImageIndex != 1) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - Image Index Invalid.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Index Invalid.\n", mImageIdName));\r
     Status = EFI_INVALID_PARAMETER;\r
     goto cleanup;\r
   }\r
 \r
   if (ImageSize == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - ImageSize Pointer Parameter is NULL.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - ImageSize Pointer Parameter is NULL.\n", mImageIdName));\r
     Status = EFI_INVALID_PARAMETER;\r
     goto cleanup;\r
   }\r
@@ -545,21 +628,67 @@ GetTheImage (
   if (EFI_ERROR (Status)) {\r
     Size = 0;\r
   }\r
-  if (*ImageSize < Size) {\r
-    *ImageSize = Size;\r
-    DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImage() - ImageSize is to small.\n"));\r
+\r
+  //\r
+  // The parameter "Image" of FmpDeviceGetImage() is extended to contain the dependency.\r
+  // Get the Fmp Payload from the Image.\r
+  //\r
+  ImageBufferSize = Size;\r
+  ImageBuffer = AllocatePool (ImageBufferSize);\r
+  if (ImageBuffer == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - AllocatePool fails.\n", mImageIdName));\r
+    Status = EFI_NOT_FOUND;\r
+    goto cleanup;\r
+  }\r
+  Status = FmpDeviceGetImage (ImageBuffer, &ImageBufferSize);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    FreePool (ImageBuffer);\r
+    ImageBuffer = AllocatePool (ImageBufferSize);\r
+    if (ImageBuffer == NULL) {\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - AllocatePool fails.\n", mImageIdName));\r
+      Status = EFI_NOT_FOUND;\r
+      goto cleanup;\r
+    }\r
+    Status = FmpDeviceGetImage (ImageBuffer, &ImageBufferSize);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    goto cleanup;\r
+  }\r
+\r
+  //\r
+  // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY\r
+  //\r
+  if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {\r
+    //\r
+    // Validate the dependency to get its size.\r
+    //\r
+    ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP *) ImageBuffer, ImageBufferSize, &DepexSize);\r
+  }\r
+\r
+  if (*ImageSize < ImageBufferSize - DepexSize) {\r
+    *ImageSize = ImageBufferSize - DepexSize;\r
+    DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName));\r
     Status = EFI_BUFFER_TOO_SMALL;\r
     goto cleanup;\r
   }\r
 \r
   if (Image == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - Image Pointer Parameter is NULL.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Pointer Parameter is NULL.\n", mImageIdName));\r
     Status = EFI_INVALID_PARAMETER;\r
     goto cleanup;\r
   }\r
 \r
-  Status = FmpDeviceGetImage (Image, ImageSize);\r
+  //\r
+  // Image is after the dependency expression.\r
+  //\r
+  *ImageSize = ImageBufferSize - DepexSize;\r
+  CopyMem (Image, ImageBuffer + DepexSize, *ImageSize);\r
+  Status = EFI_SUCCESS;\r
+\r
 cleanup:\r
+  if (ImageBuffer != NULL) {\r
+    FreePool (ImageBuffer);\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -680,6 +809,10 @@ CheckTheImage (
   UINTN                             PublicKeyDataLength;\r
   UINT8                             *PublicKeyDataXdr;\r
   UINT8                             *PublicKeyDataXdrEnd;\r
+  EFI_FIRMWARE_IMAGE_DEP            *Dependencies;\r
+  UINT32                            DependenciesSize;\r
+  BOOLEAN                           IsDepexValid;\r
+  BOOLEAN                           IsDepexSatisfied;\r
 \r
   Status           = EFI_SUCCESS;\r
   RawSize          = 0;\r
@@ -688,6 +821,12 @@ CheckTheImage (
   Version          = 0;\r
   FmpHeaderSize    = 0;\r
   AllHeaderSize    = 0;\r
+  Dependencies     = NULL;\r
+  DependenciesSize = 0;\r
+\r
+  if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
 \r
   //\r
   // Retrieve the private context structure\r
@@ -696,12 +835,12 @@ CheckTheImage (
   FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
 \r
   //\r
-  // make sure the descriptor has already been loaded\r
+  // Make sure the descriptor has already been loaded or refreshed\r
   //\r
   PopulateDescriptor (Private);\r
 \r
   if (ImageUpdatable == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName));\r
     Status = EFI_INVALID_PARAMETER;\r
     goto cleanup;\r
   }\r
@@ -712,7 +851,7 @@ CheckTheImage (
   *ImageUpdatable = IMAGE_UPDATABLE_VALID;\r
 \r
   if (Image == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - Image Pointer Parameter is NULL.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName));\r
     //\r
     // not sure if this is needed\r
     //\r
@@ -724,7 +863,7 @@ CheckTheImage (
   PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr);\r
 \r
   if (PublicKeyDataXdr == NULL || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: Invalid certificate, skipping it.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName));\r
     Status = EFI_ABORTED;\r
   } else {\r
     //\r
@@ -734,7 +873,8 @@ CheckTheImage (
       Index++;\r
       DEBUG (\r
         (DEBUG_INFO,\r
-        "FmpDxe: Certificate #%d [%p..%p].\n",\r
+        "FmpDxe(%s): Certificate #%d [%p..%p].\n",\r
+        mImageIdName,\r
         Index,\r
         PublicKeyDataXdr,\r
         PublicKeyDataXdrEnd\r
@@ -745,7 +885,7 @@ CheckTheImage (
         //\r
         // Key data extends beyond end of PCD\r
         //\r
-        DEBUG ((DEBUG_ERROR, "FmpDxe: Certificate size extends beyond end of PCD, skipping it.\n"));\r
+        DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate size extends beyond end of PCD, skipping it.\n", mImageIdName));\r
         Status = EFI_ABORTED;\r
         break;\r
       }\r
@@ -761,7 +901,7 @@ CheckTheImage (
         //\r
         // Key data extends beyond end of PCD\r
         //\r
-        DEBUG ((DEBUG_ERROR, "FmpDxe: Certificate extends beyond end of PCD, skipping it.\n"));\r
+        DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName));\r
         Status = EFI_ABORTED;\r
         break;\r
       }\r
@@ -781,7 +921,7 @@ CheckTheImage (
   }\r
 \r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - Authentication Failed %r.\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Authentication Failed %r.\n", mImageIdName, Status));\r
     goto cleanup;\r
   }\r
 \r
@@ -789,7 +929,7 @@ CheckTheImage (
   // Check to make sure index is 1\r
   //\r
   if (ImageIndex != 1) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - Image Index Invalid.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName));\r
     *ImageUpdatable = IMAGE_UPDATABLE_INVALID_TYPE;\r
     Status = EFI_SUCCESS;\r
     goto cleanup;\r
@@ -801,16 +941,39 @@ CheckTheImage (
   //\r
   FmpPayloadHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize );\r
   if (FmpPayloadHeader == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpHeader failed.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));\r
     Status = EFI_ABORTED;\r
     goto cleanup;\r
   }\r
   Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", Status));\r
-    *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
-    Status = EFI_SUCCESS;\r
-    goto cleanup;\r
+    //\r
+    // Check if there is dependency expression\r
+    //\r
+    IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP*) FmpPayloadHeader, FmpPayloadSize, &DependenciesSize);\r
+    if (IsDepexValid && (DependenciesSize < FmpPayloadSize)) {\r
+      //\r
+      // Fmp payload is after dependency expression\r
+      //\r
+      Dependencies = (EFI_FIRMWARE_IMAGE_DEP*) FmpPayloadHeader;\r
+      FmpPayloadHeader = (UINT8 *) Dependencies + DependenciesSize;\r
+      FmpPayloadSize = FmpPayloadSize - DependenciesSize;\r
+      Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));\r
+        *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
+        Status = EFI_SUCCESS;\r
+        goto cleanup;\r
+      }\r
+    } else {\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency is invalid.\n", mImageIdName));\r
+      mDependenciesCheckStatus = DEPENDENCIES_INVALID;\r
+      *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
+      Status = EFI_SUCCESS;\r
+      goto cleanup;\r
+    }\r
+  } else {\r
+    DEBUG ((DEBUG_WARN, "FmpDxe(%s): CheckTheImage() - No dependency associated in image.\n", mImageIdName));\r
   }\r
 \r
   //\r
@@ -819,14 +982,30 @@ CheckTheImage (
   if (Version < Private->Descriptor.LowestSupportedImageVersion) {\r
     DEBUG (\r
       (DEBUG_ERROR,\r
-      "FmpDxe: CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",\r
-      Version, Private->Descriptor.LowestSupportedImageVersion)\r
+      "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",\r
+      mImageIdName, Version, Private->Descriptor.LowestSupportedImageVersion)\r
       );\r
     *ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;\r
     Status = EFI_SUCCESS;\r
     goto cleanup;\r
   }\r
 \r
+  //\r
+  // Evaluate dependency expression\r
+  //\r
+  Status = EvaluateImageDependencies (Private->Descriptor.ImageTypeId, Version, Dependencies, DependenciesSize, &IsDepexSatisfied);\r
+  if (!IsDepexSatisfied || EFI_ERROR (Status)) {\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed %r.\n", mImageIdName, Status));\r
+    } else {\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency is not satisfied.\n", mImageIdName));\r
+    }\r
+    mDependenciesCheckStatus = DEPENDENCIES_UNSATISFIED;\r
+    *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
+    Status = EFI_SUCCESS;\r
+    goto cleanup;\r
+  }\r
+\r
   //\r
   // Get the FmpHeaderSize so we can determine the real payload size\r
   //\r
@@ -842,9 +1021,9 @@ CheckTheImage (
   // Call FmpDevice Lib Check Image on the\r
   // Raw payload.  So all headers need stripped off\r
   //\r
-  AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize );\r
+  AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);\r
   if (AllHeaderSize == 0) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetAllHeaderSize failed.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName));\r
     Status = EFI_ABORTED;\r
     goto cleanup;\r
   }\r
@@ -855,7 +1034,7 @@ CheckTheImage (
   //\r
   Status = FmpDeviceCheckImage ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdatable);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName, Status));\r
   }\r
 \r
 cleanup:\r
@@ -928,10 +1107,15 @@ SetTheImage (
   VOID                              *FmpHeader;\r
   UINTN                             FmpPayloadSize;\r
   UINT32                            AllHeaderSize;\r
-  UINT32                            IncommingFwVersion;\r
+  UINT32                            IncomingFwVersion;\r
   UINT32                            LastAttemptStatus;\r
   UINT32                            Version;\r
   UINT32                            LowestSupportedVersion;\r
+  EFI_FIRMWARE_IMAGE_DEP            *Dependencies;\r
+  UINT32                            DependenciesSize;\r
+  BOOLEAN                           IsDepexValid;\r
+  UINT8                             *ImageBuffer;\r
+  UINTN                             ImageBufferSize;\r
 \r
   Status             = EFI_SUCCESS;\r
   Updateable         = 0;\r
@@ -940,8 +1124,16 @@ SetTheImage (
   FmpHeader          = NULL;\r
   FmpPayloadSize     = 0;\r
   AllHeaderSize      = 0;\r
-  IncommingFwVersion = 0;\r
+  IncomingFwVersion  = 0;\r
   LastAttemptStatus  = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
+  Dependencies       = NULL;\r
+  DependenciesSize   = 0;\r
+  ImageBuffer        = NULL;\r
+  ImageBufferSize    = 0;\r
+\r
+  if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
 \r
   //\r
   // Retrieve the private context structure\r
@@ -949,24 +1141,37 @@ SetTheImage (
   Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
   FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
 \r
-  SetLastAttemptVersionInVariable (IncommingFwVersion); //set to 0 to clear any previous results.\r
+  //\r
+  // Make sure the descriptor has already been loaded or refreshed\r
+  //\r
+  PopulateDescriptor (Private);\r
+\r
+  //\r
+  // Set to 0 to clear any previous results.\r
+  //\r
+  SetLastAttemptVersionInVariable (Private, IncomingFwVersion);\r
 \r
   //\r
   // if we have locked the device, then skip the set operation.\r
   // it should be blocked by hardware too but we can catch here even faster\r
   //\r
   if (Private->FmpDeviceLocked) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Device is already locked.  Can't update.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Device is already locked.  Can't update.\n", mImageIdName));\r
     Status = EFI_UNSUPPORTED;\r
     goto cleanup;\r
   }\r
 \r
+  //\r
+  // Set check status to satisfied before CheckTheImage()\r
+  //\r
+  mDependenciesCheckStatus = DEPENDENCIES_SATISFIED;\r
+\r
   //\r
   // Call check image to verify the image\r
   //\r
   Status = CheckTheImage (This, ImageIndex, Image, ImageSize, &Updateable);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Check The Image failed with %r.\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName, Status));\r
     if (Status == EFI_SECURITY_VIOLATION) {\r
       LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;\r
     }\r
@@ -979,31 +1184,51 @@ SetTheImage (
   //\r
   FmpHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize );\r
   if (FmpHeader == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetFmpHeader failed.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));\r
     Status = EFI_ABORTED;\r
     goto cleanup;\r
   }\r
-  Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncommingFwVersion);\r
+  Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Check if there is dependency expression\r
+    //\r
+    IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP*) FmpHeader, FmpPayloadSize, &DependenciesSize);\r
+    if (IsDepexValid && (DependenciesSize < FmpPayloadSize)) {\r
+      //\r
+      // Fmp payload is after dependency expression\r
+      //\r
+      Dependencies = (EFI_FIRMWARE_IMAGE_DEP*) FmpHeader;\r
+      FmpHeader = (UINT8 *) FmpHeader + DependenciesSize;\r
+      FmpPayloadSize = FmpPayloadSize - DependenciesSize;\r
+      Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);\r
+    }\r
+  }\r
   if (!EFI_ERROR (Status)) {\r
     //\r
     // Set to actual value\r
     //\r
-    SetLastAttemptVersionInVariable (IncommingFwVersion);\r
+    SetLastAttemptVersionInVariable (Private, IncomingFwVersion);\r
   }\r
 \r
 \r
   if (Updateable != IMAGE_UPDATABLE_VALID) {\r
     DEBUG (\r
       (DEBUG_ERROR,\r
-      "FmpDxed: SetTheImage() - Check The Image returned that the Image was not valid for update.  Updatable value = 0x%X.\n",\r
-      Updateable)\r
+      "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update.  Updatable value = 0x%X.\n",\r
+      mImageIdName, Updateable)\r
       );\r
+    if (mDependenciesCheckStatus == DEPENDENCIES_UNSATISFIED) {\r
+      LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;\r
+    } else if (mDependenciesCheckStatus == DEPENDENCIES_INVALID) {\r
+      LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;\r
+    }\r
     Status = EFI_ABORTED;\r
     goto cleanup;\r
   }\r
 \r
   if (Progress == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Invalid progress callback\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName));\r
     Status = EFI_INVALID_PARAMETER;\r
     goto cleanup;\r
   }\r
@@ -1015,7 +1240,7 @@ SetTheImage (
   //\r
   Status = Progress (1);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Progress Callback failed with Status %r.\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Progress Callback failed with Status %r.\n", mImageIdName, Status));\r
   }\r
 \r
   //\r
@@ -1023,14 +1248,14 @@ SetTheImage (
   //\r
   Status = CheckSystemPower (&BooleanValue);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemPower - API call failed %r.\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName, Status));\r
     goto cleanup;\r
   }\r
   if (!BooleanValue) {\r
     Status = EFI_ABORTED;\r
     DEBUG (\r
       (DEBUG_ERROR,\r
-      "FmpDxe: SetTheImage() - CheckSystemPower - returned False.  Update not allowed due to System Power.\n")\r
+      "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False.  Update not allowed due to System Power.\n", mImageIdName)\r
       );\r
     LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT;\r
     goto cleanup;\r
@@ -1043,14 +1268,14 @@ SetTheImage (
   //\r
   Status = CheckSystemThermal (&BooleanValue);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemThermal - API call failed %r.\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName, Status));\r
     goto cleanup;\r
   }\r
   if (!BooleanValue) {\r
     Status = EFI_ABORTED;\r
     DEBUG (\r
       (DEBUG_ERROR,\r
-      "FmpDxe: SetTheImage() - CheckSystemThermal - returned False.  Update not allowed due to System Thermal.\n")\r
+      "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False.  Update not allowed due to System Thermal.\n", mImageIdName)\r
       );\r
     goto cleanup;\r
   }\r
@@ -1062,14 +1287,14 @@ SetTheImage (
   //\r
   Status = CheckSystemEnvironment (&BooleanValue);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName, Status));\r
     goto cleanup;\r
   }\r
   if (!BooleanValue) {\r
     Status = EFI_ABORTED;\r
     DEBUG (\r
       (DEBUG_ERROR,\r
-      "FmpDxe: SetTheImage() - CheckSystemEnvironment - returned False.  Update not allowed due to System Environment.\n")\r
+      "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False.  Update not allowed due to System Environment.\n", mImageIdName)\r
       );\r
     goto cleanup;\r
   }\r
@@ -1080,24 +1305,52 @@ SetTheImage (
   // Save LastAttemptStatus as error so that if SetImage never returns the error\r
   // state is recorded.\r
   //\r
-  SetLastAttemptStatusInVariable (LastAttemptStatus);\r
+  SetLastAttemptStatusInVariable (Private, LastAttemptStatus);\r
 \r
   //\r
   // Strip off all the headers so the device can process its firmware\r
   //\r
   Status = GetFmpPayloadHeaderSize (FmpHeader, FmpPayloadSize, &FmpHeaderSize);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName, Status));\r
     goto cleanup;\r
   }\r
 \r
-  AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize );\r
+  AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);\r
   if (AllHeaderSize == 0) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetAllHeaderSize failed.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName));\r
     Status = EFI_ABORTED;\r
     goto cleanup;\r
   }\r
 \r
+  //\r
+  // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY\r
+  //\r
+  if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {\r
+    //\r
+    // To support saving dependency, extend param "Image" of FmpDeviceSetImage() to\r
+    // contain the dependency inside. FmpDeviceSetImage() is responsible for saving\r
+    // the dependency which can be used for future dependency check.\r
+    //\r
+    ImageBufferSize = DependenciesSize + ImageSize - AllHeaderSize;\r
+    ImageBuffer = AllocatePool (ImageBufferSize);\r
+    if (ImageBuffer == NULL) {\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - AllocatePool failed.\n", mImageIdName));\r
+      Status = EFI_ABORTED;\r
+      goto cleanup;\r
+    }\r
+    CopyMem (ImageBuffer, Dependencies->Dependencies, DependenciesSize);\r
+    CopyMem (ImageBuffer + DependenciesSize, (UINT8 *)Image + AllHeaderSize, ImageBufferSize - DependenciesSize);\r
+  } else {\r
+    ImageBufferSize = ImageSize - AllHeaderSize;\r
+    ImageBuffer = AllocateCopyPool(ImageBufferSize, (UINT8 *)Image + AllHeaderSize);\r
+    if (ImageBuffer == NULL) {\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - AllocatePool failed.\n", mImageIdName));\r
+      Status = EFI_ABORTED;\r
+      goto cleanup;\r
+    }\r
+  }\r
+\r
   //\r
   // Indicate that control is handed off to FmpDeviceLib\r
   //\r
@@ -1107,15 +1360,15 @@ SetTheImage (
   //Copy the requested image to the firmware using the FmpDeviceLib\r
   //\r
   Status = FmpDeviceSetImage (\r
-             (((UINT8 *)Image) + AllHeaderSize),\r
-             ImageSize - AllHeaderSize,\r
+             ImageBuffer,\r
+             ImageBufferSize,\r
              VendorCode,\r
              FmpDxeProgress,\r
-             IncommingFwVersion,\r
+             IncomingFwVersion,\r
              AbortReason\r
              );\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() SetImage from FmpDeviceLib failed. Status =  %r.\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status =  %r.\n", mImageIdName, Status));\r
     goto cleanup;\r
   }\r
 \r
@@ -1132,23 +1385,25 @@ SetTheImage (
   if (!Private->RuntimeVersionSupported) {\r
     Version = DEFAULT_VERSION;\r
     GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);\r
-    SetVersionInVariable (Version);\r
+    SetVersionInVariable (Private, Version);\r
   }\r
 \r
   //\r
   // Update lowest supported variable\r
   //\r
-  {\r
-    LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
-    GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);\r
-    SetLowestSupportedVersionInVariable (LowestSupportedVersion);\r
-  }\r
+  LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
+  GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);\r
+  SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion);\r
 \r
   LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
 \r
 cleanup:\r
+  if (ImageBuffer != NULL) {\r
+    FreePool (ImageBuffer);\r
+  }\r
+\r
   mProgressFunc = NULL;\r
-  SetLastAttemptStatusInVariable (LastAttemptStatus);\r
+  SetLastAttemptStatusInVariable (Private, LastAttemptStatus);\r
 \r
   if (Progress != NULL) {\r
     //\r
@@ -1285,9 +1540,9 @@ FmpDxeLockEventNotify (
     Status = FmpDeviceLock();\r
     if (EFI_ERROR (Status)) {\r
       if (Status != EFI_UNSUPPORTED) {\r
-        DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLock() returned error.  Status = %r\n", Status));\r
+        DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLock() returned error.  Status = %r\n", mImageIdName, Status));\r
       } else {\r
-        DEBUG ((DEBUG_WARN, "FmpDxe: FmpDeviceLock() returned error.  Status = %r\n", Status));\r
+        DEBUG ((DEBUG_WARN, "FmpDxe(%s): FmpDeviceLock() returned error.  Status = %r\n", mImageIdName, Status));\r
       }\r
     }\r
     Private->FmpDeviceLocked = TRUE;\r
@@ -1314,8 +1569,6 @@ InstallFmpInstance (
   EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;\r
   FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;\r
 \r
-  DEBUG ((DEBUG_ERROR, "InstallFmpInstance: Entry\n"));\r
-\r
   //\r
   // Only allow a single FMP Protocol instance to be installed\r
   //\r
@@ -1339,7 +1592,7 @@ InstallFmpInstance (
               &mFirmwareManagementPrivateDataTemplate\r
               );\r
   if (Private == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for private structure.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to allocate memory for private structure.\n", mImageIdName));\r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto cleanup;\r
   }\r
@@ -1347,10 +1600,7 @@ InstallFmpInstance (
   //\r
   // Initialize private context data structure\r
   //\r
-  DEBUG ((DEBUG_ERROR, "InstallFmpInstance: Initialize private context data structure\n"));\r
-\r
   Private->Handle = Handle;\r
-\r
   Private->FmpDeviceContext = NULL;\r
   Status = FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
   if (Status == EFI_UNSUPPORTED) {\r
@@ -1359,17 +1609,20 @@ InstallFmpInstance (
     goto cleanup;\r
   }\r
 \r
-  DEBUG ((DEBUG_ERROR, "InstallFmpInstance: Lock events\n"));\r
+  //\r
+  // Make sure the descriptor has already been loaded or refreshed\r
+  //\r
+  PopulateDescriptor (Private);\r
 \r
   if (IsLockFmpDeviceAtLockEventGuidRequired ()) {\r
     //\r
-    // Lock all UEFI Variables used by this module.\r
+    // Register all UEFI Variables used by this module to be locked.\r
     //\r
-    Status = LockAllFmpVariables ();\r
+    Status = LockAllFmpVariables (Private);\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variables.  Status = %r.\n", Status));\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register variables to lock.  Status = %r.\n", mImageIdName, Status));\r
     } else {\r
-      DEBUG ((DEBUG_INFO, "FmpDxe: All variables locked\n"));\r
+      DEBUG ((DEBUG_INFO, "FmpDxe(%s): All variables registered to lock\n", mImageIdName));\r
     }\r
 \r
     //\r
@@ -1384,32 +1637,27 @@ InstallFmpInstance (
                     &Private->FmpDeviceLockEvent\r
                     );\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to register notification.  Status = %r\n", Status));\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register notification.  Status = %r\n", mImageIdName, Status));\r
     }\r
     ASSERT_EFI_ERROR (Status);\r
   } else {\r
-    DEBUG ((DEBUG_VERBOSE, "FmpDxe: Not registering notification to call FmpDeviceLock() because mfg mode\n"));\r
+    DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): Not registering notification to call FmpDeviceLock() because mfg mode\n", mImageIdName));\r
   }\r
 \r
   //\r
   // Install FMP Protocol and FMP Progress Protocol\r
   //\r
-  DEBUG ((DEBUG_ERROR, "InstallFmpInstance: Install FMP Protocol and FMP Progress Protocol\n"));\r
-\r
   Status = gBS->InstallMultipleProtocolInterfaces (\r
                   &Private->Handle,\r
                   &gEfiFirmwareManagementProtocolGuid, &Private->Fmp,\r
                   &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress,\r
                   NULL\r
                   );\r
-\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: Protocol install error. Status = %r.\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol install error. Status = %r.\n", mImageIdName, Status));\r
     goto cleanup;\r
   }\r
 \r
-  DEBUG ((DEBUG_INFO, "FmpDxe: Protocols Installed!\n"));\r
-\r
 cleanup:\r
 \r
   if (EFI_ERROR (Status)) {\r
@@ -1417,6 +1665,27 @@ cleanup:
       if (Private->FmpDeviceLockEvent != NULL) {\r
         gBS->CloseEvent (Private->FmpDeviceLockEvent);\r
       }\r
+      if (Private->Descriptor.VersionName != NULL) {\r
+        FreePool (Private->Descriptor.VersionName);\r
+      }\r
+      if (Private->FmpDeviceContext != NULL) {\r
+        FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
+      }\r
+      if (Private->VersionVariableName != NULL) {\r
+        FreePool (Private->VersionVariableName);\r
+      }\r
+      if (Private->LsvVariableName != NULL) {\r
+        FreePool (Private->LsvVariableName);\r
+      }\r
+      if (Private->LastAttemptStatusVariableName != NULL) {\r
+        FreePool (Private->LastAttemptStatusVariableName);\r
+      }\r
+      if (Private->LastAttemptVersionVariableName != NULL) {\r
+        FreePool (Private->LastAttemptVersionVariableName);\r
+      }\r
+      if (Private->FmpStateVariableName != NULL) {\r
+        FreePool (Private->FmpStateVariableName);\r
+      }\r
       FreePool (Private);\r
     }\r
   }\r
@@ -1453,6 +1722,7 @@ UninstallFmpInstance (
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                   );\r
   if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol open error. Status = %r.\n", mImageIdName, Status));\r
     return Status;\r
   }\r
 \r
@@ -1470,11 +1740,31 @@ UninstallFmpInstance (
                   NULL\r
                   );\r
   if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol uninstall error. Status = %r.\n", mImageIdName, Status));\r
     return Status;\r
   }\r
 \r
-  FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
-\r
+  if (Private->Descriptor.VersionName != NULL) {\r
+    FreePool (Private->Descriptor.VersionName);\r
+  }\r
+  if (Private->FmpDeviceContext != NULL) {\r
+    FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
+  }\r
+  if (Private->VersionVariableName != NULL) {\r
+    FreePool (Private->VersionVariableName);\r
+  }\r
+  if (Private->LsvVariableName != NULL) {\r
+    FreePool (Private->LsvVariableName);\r
+  }\r
+  if (Private->LastAttemptStatusVariableName != NULL) {\r
+    FreePool (Private->LastAttemptStatusVariableName);\r
+  }\r
+  if (Private->LastAttemptVersionVariableName != NULL) {\r
+    FreePool (Private->LastAttemptVersionVariableName);\r
+  }\r
+  if (Private->FmpStateVariableName != NULL) {\r
+    FreePool (Private->FmpStateVariableName);\r
+  }\r
   FreePool (Private);\r
 \r
   return EFI_SUCCESS;\r
@@ -1537,11 +1827,11 @@ FmpDxeEntryPoint (
     //\r
     // PcdFmpDeviceImageIdName must be set to a non-empty Unicode string\r
     //\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib PcdFmpDeviceImageIdName is an empty string.\n"));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe: PcdFmpDeviceImageIdName is an empty string.\n"));\r
     ASSERT (FALSE);\r
+    return EFI_UNSUPPORTED;\r
   }\r
 \r
-\r
   //\r
   // Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.\r
   //\r
@@ -1562,7 +1852,7 @@ FmpDxeEntryPoint (
   if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {\r
     mLockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);\r
   }\r
-  DEBUG ((DEBUG_INFO, "FmpDxe: Lock GUID: %g\n", mLockGuid));\r
+  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Lock GUID: %g\n", mImageIdName, mLockGuid));\r
 \r
   //\r
   // Register with library the install function so if the library uses\r
@@ -1573,24 +1863,25 @@ FmpDxeEntryPoint (
   Status = RegisterFmpInstaller (InstallFmpInstance);\r
   if (Status == EFI_UNSUPPORTED) {\r
     mFmpSingleInstance = TRUE;\r
-    DEBUG ((DEBUG_INFO, "FmpDxe: FmpDeviceLib registration returned EFI_UNSUPPORTED.  Installing single FMP instance.\n"));\r
+    DEBUG ((DEBUG_INFO, "FmpDxe(%s): FmpDeviceLib registration returned EFI_UNSUPPORTED.  Installing single FMP instance.\n", mImageIdName));\r
     Status = RegisterFmpUninstaller (UninstallFmpInstance);\r
     if (Status == EFI_UNSUPPORTED) {\r
       Status = InstallFmpInstance (ImageHandle);\r
     } else {\r
-      DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n"));\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));\r
       Status = EFI_UNSUPPORTED;\r
     }\r
   } else if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib registration returned %r.  No FMP installed.\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib registration returned %r.  No FMP installed.\n", mImageIdName, Status));\r
   } else {\r
     DEBUG ((\r
       DEBUG_INFO,\r
-      "FmpDxe: FmpDeviceLib registration returned EFI_SUCCESS.  Expect FMP to be installed during the BDS/Device connection phase.\n"\r
+      "FmpDxe(%s): FmpDeviceLib registration returned EFI_SUCCESS.  Expect FMP to be installed during the BDS/Device connection phase.\n",\r
+      mImageIdName\r
       ));\r
     Status = RegisterFmpUninstaller (UninstallFmpInstance);\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n"));\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));\r
     }\r
   }\r
 \r