]> git.proxmox.com Git - mirror_edk2.git/blobdiff - FmpDevicePkg/FmpDxe/FmpDxe.c
FmpDevicePkg/FmpDxe: Add PcdFmpDeviceStorageAccessEnable
[mirror_edk2.git] / FmpDevicePkg / FmpDxe / FmpDxe.c
index b25a1511c70cbbe3735593e45db37cd865000b88..3ca9d3526ad3ff91e4220af8fe55a32dab2f9530 100644 (file)
@@ -1,67 +1,18 @@
-/**  @file\r
+/** @file\r
   Produces a Firmware Management Protocol that supports updates to a firmware\r
   image stored in a firmware device with platform and firmware device specific\r
   information provided through PCDs and libraries.\r
 \r
   Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>\r
-  Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
-\r
-  Redistribution and use in source and binary forms, with or without\r
-  modification, are permitted provided that the following conditions are met:\r
-  1. Redistributions of source code must retain the above copyright notice,\r
-  this list of conditions and the following disclaimer.\r
-  2. Redistributions in binary form must reproduce the above copyright notice,\r
-  this list of conditions and the following disclaimer in the documentation\r
-  and/or other materials provided with the distribution.\r
-\r
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
-  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
-  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\r
-  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
-  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
-  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
-  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
-  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r
-  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+  Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
-#include <PiDxe.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/FmpAuthenticationLib.h>\r
-#include <Library/FmpDeviceLib.h>\r
-#include <Library/FmpPayloadHeaderLib.h>\r
-#include <Library/CapsuleUpdatePolicyLib.h>\r
-#include <Protocol/FirmwareManagement.h>\r
-#include <Protocol/FirmwareManagementProgress.h>\r
-#include <Guid/SystemResourceTable.h>\r
-#include <Guid/EventGroup.h>\r
+#include "FmpDxe.h"\r
 #include "VariableSupport.h"\r
 \r
-#define VERSION_STRING_NOT_SUPPORTED  L"VERSION STRING NOT SUPPORTED"\r
-#define VERSION_STRING_NOT_AVAILABLE  L"VERSION STRING NOT AVAILABLE"\r
-\r
-/**\r
-  Check to see if any of the keys in PcdFmpDevicePkcs7CertBufferXdr matches\r
-  the test key.  PcdFmpDeviceTestKeySha256Digest contains the SHA256 hash of\r
-  the test key.  For each key in PcdFmpDevicePkcs7CertBufferXdr, compute the\r
-  SHA256 hash and compare it to PcdFmpDeviceTestKeySha256Digest.  If the\r
-  SHA256 hash matches or there is then error computing the SHA256 hash, then\r
-  set PcdTestKeyUsed to TRUE.  Skip this check if PcdTestKeyUsed is already\r
-  TRUE or PcdFmpDeviceTestKeySha256Digest is not exactly SHA256_DIGEST_SIZE\r
-  bytes.\r
-**/\r
-VOID\r
-DetectTestKey (\r
-  VOID\r
-  );\r
-\r
 ///\r
 /// FILE_GUID from FmpDxe.inf.  When FmpDxe.inf is used in a platform, the\r
 /// FILE_GUID must always be overridden in the <Defines> section to provide\r
@@ -73,30 +24,79 @@ const EFI_GUID  mDefaultModuleFileGuid = {
   0x78ef0a56, 0x1cf0, 0x4535, { 0xb5, 0xda, 0xf6, 0xfd, 0x2f, 0x40, 0x5a, 0x11 }\r
 };\r
 \r
-EFI_FIRMWARE_IMAGE_DESCRIPTOR  mDesc;\r
-BOOLEAN                        mDescriptorPopulated     = FALSE;\r
-BOOLEAN                        mRuntimeVersionSupported = TRUE;\r
-BOOLEAN                        mFmpInstalled            = FALSE;\r
-\r
 ///\r
-/// Function pointer to progress function\r
+/// TRUE if FmpDeviceLib manages a single firmware storage device.\r
 ///\r
-EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  mProgressFunc      = NULL;\r
-BOOLEAN                                        mProgressSupported = FALSE;\r
+BOOLEAN  mFmpSingleInstance = FALSE;\r
 \r
-CHAR16  *mImageIdName = NULL;\r
-UINT64  mImageId      = 0x1;\r
-CHAR16  *mVersionName = NULL;\r
+///\r
+/// Firmware Management Protocol instance that is initialized in the entry\r
+/// point from PCD settings.\r
+///\r
+EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL  mFmpProgress;\r
 \r
-EFI_EVENT  mFmpDeviceLockEvent;\r
 //\r
-// Indicates if an attempt has been made to lock a \r
-// FLASH storage device by calling FmpDeviceLock().\r
-// A FLASH storage device may not support being locked,\r
-// so this variable is set to TRUE even if FmpDeviceLock()\r
-// returns an error.\r
+// Template of the private context structure for the Firmware Management\r
+// Protocol instance\r
 //\r
-BOOLEAN    mFmpDeviceLocked = FALSE;\r
+const FIRMWARE_MANAGEMENT_PRIVATE_DATA  mFirmwareManagementPrivateDataTemplate = {\r
+  FIRMWARE_MANAGEMENT_PRIVATE_DATA_SIGNATURE,  // Signature\r
+  NULL,                                        // Handle\r
+  {                                            // Fmp\r
+    GetTheImageInfo,\r
+    GetTheImage,\r
+    SetTheImage,\r
+    CheckTheImage,\r
+    GetPackageInfo,\r
+    SetPackageInfo\r
+  },\r
+  FALSE,                                       // DescriptorPopulated\r
+  {                                            // Desc\r
+    1,     // ImageIndex\r
+    //\r
+    // ImageTypeId\r
+    //\r
+    { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },\r
+    1,     // ImageId\r
+    NULL,  // ImageIdName\r
+    0,     // Version\r
+    NULL,  // VersionName\r
+    0,     // Size\r
+    0,     // AttributesSupported\r
+    0,     // AttributesSetting\r
+    0,     // Compatibilities\r
+    0,     // LowestSupportedImageVersion\r
+    0,     // LastAttemptVersion\r
+    0,     // LastAttemptStatus\r
+    0      // HardwareInstance\r
+  },\r
+  NULL,                                        // ImageIdName\r
+  NULL,                                        // VersionName\r
+  TRUE,                                        // RuntimeVersionSupported\r
+  NULL,                                        // FmpDeviceLockEvent\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
+/// GUID that is used to create event used to lock the firmware storage device.\r
+///\r
+EFI_GUID  *mLockGuid = NULL;\r
+\r
+///\r
+/// Progress() function pointer passed into SetTheImage()\r
+///\r
+EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  mProgressFunc = NULL;\r
+\r
+///\r
+/// Null-terminated Unicode string retrieved from PcdFmpDeviceImageIdName.\r
+///\r
+CHAR16  *mImageIdName = NULL;\r
 \r
 /**\r
   Callback function to report the process of the firmware updating.\r
@@ -128,10 +128,6 @@ FmpDxeProgress (
 \r
   Status = EFI_UNSUPPORTED;\r
 \r
-  if (!mProgressSupported) {\r
-    return Status;\r
-  }\r
-\r
   if (mProgressFunc == NULL) {\r
     return Status;\r
   }\r
@@ -142,7 +138,6 @@ FmpDxeProgress (
   Status = mProgressFunc (((Completion * 92) / 100) + 6);\r
 \r
   if (Status == EFI_UNSUPPORTED) {\r
-    mProgressSupported = FALSE;\r
     mProgressFunc = NULL;\r
   }\r
 \r
@@ -152,9 +147,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
@@ -164,18 +161,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
@@ -183,7 +188,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
@@ -200,12 +205,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
-  Take 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
@@ -229,6 +237,7 @@ GetLowestSupportedVersion (
   //\r
   // Check the FmpDeviceLib\r
   //\r
+  DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
   Status = FmpDeviceGetLowestSupportedVersion (&DeviceLibLowestSupportedVersion);\r
   if (EFI_ERROR (Status)) {\r
     DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
@@ -241,7 +250,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
@@ -253,101 +262,123 @@ GetLowestSupportedVersion (
 }\r
 \r
 /**\r
-  Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the module global\r
-  variable mDesc.\r
+  Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the private\r
+  context structure.\r
+\r
+  @param[in] Private  Pointer to the private context structure for the\r
+                      Firmware Management Protocol instance.\r
 \r
 **/\r
 VOID\r
 PopulateDescriptor (\r
-  VOID\r
+  FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private\r
   )\r
 {\r
   EFI_STATUS  Status;\r
 \r
-  mDesc.ImageIndex = 1;\r
-  CopyGuid (&mDesc.ImageTypeId, GetImageTypeIdGuid());\r
-  mDesc.ImageId = mImageId;\r
-  mDesc.ImageIdName = GetImageTypeNameString();\r
+  if (Private->DescriptorPopulated) {\r
+    return;\r
+  }\r
+\r
+  Private->Descriptor.ImageIndex = 1;\r
+  CopyGuid (&Private->Descriptor.ImageTypeId, GetImageTypeIdGuid());\r
+  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
   // it is stored in a UEFI variable.\r
   //\r
-  Status = FmpDeviceGetVersion (&mDesc.Version);\r
+  Status = FmpDeviceGetVersion (&Private->Descriptor.Version);\r
   if (Status == EFI_UNSUPPORTED) {\r
-    mRuntimeVersionSupported = FALSE;\r
-    mDesc.Version = GetVersionFromVariable();\r
+    Private->RuntimeVersionSupported = FALSE;\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
-    mDesc.Version = DEFAULT_VERSION;\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
   //\r
   // Free the current version name.  Shouldn't really happen but this populate\r
   // function could be called multiple times (to refresh).\r
   //\r
-  if (mVersionName != NULL) {\r
-    FreePool (mVersionName);\r
-    mVersionName = NULL;\r
+  if (Private->Descriptor.VersionName != NULL) {\r
+    FreePool (Private->Descriptor.VersionName);\r
+    Private->Descriptor.VersionName = NULL;\r
   }\r
 \r
   //\r
   // Attempt to get the version string from the FmpDeviceLib\r
   //\r
-  Status = FmpDeviceGetVersionString (&mVersionName);\r
+  Status = FmpDeviceGetVersionString (&Private->Descriptor.VersionName);\r
   if (Status == EFI_UNSUPPORTED) {\r
-    DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() unsupported in FmpDeviceLib.\n"));\r
-    mVersionName = AllocateCopyPool (\r
-                     sizeof (VERSION_STRING_NOT_SUPPORTED),\r
-                     VERSION_STRING_NOT_SUPPORTED\r
-                     );\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
-    mVersionName = AllocateCopyPool (\r
-                     sizeof (VERSION_STRING_NOT_AVAILABLE),\r
-                     VERSION_STRING_NOT_AVAILABLE\r
-                     );\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
-  mDesc.VersionName = mVersionName;\r
-\r
-  mDesc.LowestSupportedImageVersion = GetLowestSupportedVersion();\r
+  Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion (Private);\r
 \r
   //\r
   // Get attributes from the FmpDeviceLib\r
   //\r
-  FmpDeviceGetAttributes (&mDesc.AttributesSupported, &mDesc.AttributesSetting);\r
+  FmpDeviceGetAttributes (\r
+    &Private->Descriptor.AttributesSupported,\r
+    &Private->Descriptor.AttributesSetting\r
+    );\r
 \r
   //\r
   // Force set the updatable bits in the attributes;\r
   //\r
-  mDesc.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;\r
-  mDesc.AttributesSetting   |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;\r
+  Private->Descriptor.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;\r
+  Private->Descriptor.AttributesSetting   |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;\r
 \r
   //\r
   // Force set the authentication bits in the attributes;\r
   //\r
-  mDesc.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
-  mDesc.AttributesSetting   |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
+  Private->Descriptor.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
+  Private->Descriptor.AttributesSetting   |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
 \r
-  mDesc.Compatibilities = 0;\r
+  Private->Descriptor.Compatibilities = 0;\r
 \r
   //\r
   // Get the size of the firmware image from the FmpDeviceLib\r
   //\r
-  Status = FmpDeviceGetSize (&mDesc.Size);\r
+  Status = FmpDeviceGetSize (&Private->Descriptor.Size);\r
   if (EFI_ERROR (Status)) {\r
-    mDesc.Size = 0;\r
+    Private->Descriptor.Size = 0;\r
   }\r
 \r
-  mDesc.LastAttemptVersion = GetLastAttemptVersionFromVariable ();\r
-  mDesc.LastAttemptStatus  = GetLastAttemptStatusFromVariable ();\r
+  Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable (Private);\r
+  Private->Descriptor.LastAttemptStatus  = GetLastAttemptStatusFromVariable (Private);\r
 \r
-  mDescriptorPopulated = TRUE;\r
+  Private->DescriptorPopulated = TRUE;\r
 }\r
 \r
 /**\r
@@ -401,15 +432,22 @@ GetTheImageInfo (
   OUT    CHAR16                            **PackageVersionName\r
   )\r
 {\r
-  EFI_STATUS Status;\r
+  EFI_STATUS                        Status;\r
+  FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;\r
 \r
   Status = EFI_SUCCESS;\r
 \r
+  //\r
+  // Retrieve the private context structure\r
+  //\r
+  Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
+  FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+\r
   //\r
   // 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
@@ -420,7 +458,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
@@ -430,7 +468,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
@@ -440,15 +478,15 @@ GetTheImageInfo (
   //\r
   *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);\r
 \r
-\r
-  if (!mDescriptorPopulated) {\r
-    PopulateDescriptor();\r
-  }\r
+  //\r
+  // Make sure the descriptor has already been loaded or refreshed\r
+  //\r
+  PopulateDescriptor (Private);\r
 \r
   //\r
   // Copy the image descriptor\r
   //\r
-  CopyMem (ImageInfo, &mDesc, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR));\r
+  CopyMem (ImageInfo, &Private->Descriptor, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR));\r
 \r
   *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;\r
   *DescriptorCount = 1;\r
@@ -473,11 +511,11 @@ cleanup:
   This function allows a copy of the current firmware image to be created and saved.\r
   The saved copy could later been used, for example, in firmware image recovery or rollback.\r
 \r
-  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
-  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.\r
+  @param[in]      This           A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
+  @param[in]      ImageIndex     A unique number identifying the firmware image(s) within the device.\r
                                  The number is between 1 and DescriptorCount.\r
-  @param[out] Image              Points to the buffer where the current image is copied to.\r
-  @param[out] ImageSize          On entry, points to the size of the buffer pointed to by Image, in bytes.\r
+  @param[in, out] Image          Points to the buffer where the current image is copied to.\r
+  @param[in, out] ImageSize      On entry, points to the size of the buffer pointed to by Image, in bytes.\r
                                  On return, points to the length of the image, in bytes.\r
 \r
   @retval EFI_SUCCESS            The device was successfully updated with the new image.\r
@@ -499,22 +537,33 @@ GetTheImage (
   IN OUT UINTN                             *ImageSize\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  UINTN       Size;\r
+  EFI_STATUS                        Status;\r
+  FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;\r
+  UINTN                             Size;\r
+\r
+  if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
 \r
   Status = EFI_SUCCESS;\r
 \r
+  //\r
+  // Retrieve the private context structure\r
+  //\r
+  Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
+  FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+\r
   //\r
   // 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
+  if (ImageSize == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - ImageSize Pointer Parameter is NULL.\n", mImageIdName));\r
     Status = EFI_INVALID_PARAMETER;\r
     goto cleanup;\r
   }\r
@@ -528,13 +577,13 @@ GetTheImage (
   }\r
   if (*ImageSize < Size) {\r
     *ImageSize = Size;\r
-    DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImage() - ImageSize is to small.\n"));\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
@@ -645,21 +694,22 @@ CheckTheImage (
   IN  UINT8                             ImageIndex,\r
   IN  CONST VOID                        *Image,\r
   IN  UINTN                             ImageSize,\r
-  OUT UINT32                            *ImageUpdateable\r
+  OUT UINT32                            *ImageUpdatable\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  UINTN       RawSize;\r
-  VOID        *FmpPayloadHeader;\r
-  UINTN       FmpPayloadSize;\r
-  UINT32      Version;\r
-  UINT32      FmpHeaderSize;\r
-  UINTN       AllHeaderSize;\r
-  UINT32      Index;\r
-  VOID        *PublicKeyData;\r
-  UINTN       PublicKeyDataLength;\r
-  UINT8       *PublicKeyDataXdr;\r
-  UINT8       *PublicKeyDataXdrEnd;\r
+  EFI_STATUS                        Status;\r
+  FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;\r
+  UINTN                             RawSize;\r
+  VOID                              *FmpPayloadHeader;\r
+  UINTN                             FmpPayloadSize;\r
+  UINT32                            Version;\r
+  UINT32                            FmpHeaderSize;\r
+  UINTN                             AllHeaderSize;\r
+  UINT32                            Index;\r
+  VOID                              *PublicKeyData;\r
+  UINTN                             PublicKeyDataLength;\r
+  UINT8                             *PublicKeyDataXdr;\r
+  UINT8                             *PublicKeyDataXdrEnd;\r
 \r
   Status           = EFI_SUCCESS;\r
   RawSize          = 0;\r
@@ -669,15 +719,23 @@ CheckTheImage (
   FmpHeaderSize    = 0;\r
   AllHeaderSize    = 0;\r
 \r
+  if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   //\r
-  // make sure the descriptor has already been loaded\r
+  // Retrieve the private context structure\r
   //\r
-  if (!mDescriptorPopulated) {\r
-    PopulateDescriptor();\r
-  }\r
+  Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
+  FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+\r
+  //\r
+  // Make sure the descriptor has already been loaded or refreshed\r
+  //\r
+  PopulateDescriptor (Private);\r
 \r
-  if (ImageUpdateable == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - ImageUpdateable Pointer Parameter is NULL.\n"));\r
+  if (ImageUpdatable == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName));\r
     Status = EFI_INVALID_PARAMETER;\r
     goto cleanup;\r
   }\r
@@ -685,14 +743,14 @@ CheckTheImage (
   //\r
   //Set to valid and then if any tests fail it will update this flag.\r
   //\r
-  *ImageUpdateable = IMAGE_UPDATABLE_VALID;\r
+  *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
-    *ImageUpdateable = IMAGE_UPDATABLE_INVALID;\r
+    *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -700,7 +758,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
@@ -710,7 +768,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
@@ -721,7 +780,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
@@ -737,7 +796,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
@@ -757,7 +816,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
@@ -765,8 +824,8 @@ CheckTheImage (
   // Check to make sure index is 1\r
   //\r
   if (ImageIndex != 1) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - Image Index Invalid.\n"));\r
-    *ImageUpdateable = IMAGE_UPDATABLE_INVALID_TYPE;\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
   }\r
@@ -777,14 +836,14 @@ 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
-    *ImageUpdateable = IMAGE_UPDATABLE_INVALID;\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
@@ -792,13 +851,13 @@ CheckTheImage (
   //\r
   // Check the lowest supported version\r
   //\r
-  if (Version < mDesc.LowestSupportedImageVersion) {\r
+  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, mDesc.LowestSupportedImageVersion)\r
+      "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",\r
+      mImageIdName, Version, Private->Descriptor.LowestSupportedImageVersion)\r
       );\r
-    *ImageUpdateable = IMAGE_UPDATABLE_INVALID_OLD;\r
+    *ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;\r
     Status = EFI_SUCCESS;\r
     goto cleanup;\r
   }\r
@@ -809,7 +868,7 @@ CheckTheImage (
   Status = GetFmpPayloadHeaderSize (FmpPayloadHeader, FmpPayloadSize, &FmpHeaderSize);\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));\r
-    *ImageUpdateable = IMAGE_UPDATABLE_INVALID;\r
+    *ImageUpdatable = IMAGE_UPDATABLE_INVALID;\r
     Status = EFI_SUCCESS;\r
     goto cleanup;\r
   }\r
@@ -820,7 +879,7 @@ CheckTheImage (
   //\r
   AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize );\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
@@ -829,9 +888,9 @@ CheckTheImage (
   //\r
   // FmpDeviceLib CheckImage function to do any specific checks\r
   //\r
-  Status = FmpDeviceCheckImage ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdateable);\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
@@ -896,18 +955,18 @@ SetTheImage (
   OUT CHAR16                                         **AbortReason\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  UINT32      Updateable;\r
-  BOOLEAN     BooleanValue;\r
-  UINT32      FmpHeaderSize;\r
-  VOID        *FmpHeader;\r
-  UINTN       FmpPayloadSize;\r
-  UINT32      AllHeaderSize;\r
-  UINT32      IncommingFwVersion;\r
-  UINT32      LastAttemptStatus;\r
-  EFI_STATUS  GetAttributesStatus;\r
-  UINT64      AttributesSupported;\r
-  UINT64      AttributesSetting;\r
+  EFI_STATUS                        Status;\r
+  FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;\r
+  UINT32                            Updateable;\r
+  BOOLEAN                           BooleanValue;\r
+  UINT32                            FmpHeaderSize;\r
+  VOID                              *FmpHeader;\r
+  UINTN                             FmpPayloadSize;\r
+  UINT32                            AllHeaderSize;\r
+  UINT32                            IncommingFwVersion;\r
+  UINT32                            LastAttemptStatus;\r
+  UINT32                            Version;\r
+  UINT32                            LowestSupportedVersion;\r
 \r
   Status             = EFI_SUCCESS;\r
   Updateable         = 0;\r
@@ -919,15 +978,32 @@ SetTheImage (
   IncommingFwVersion = 0;\r
   LastAttemptStatus  = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
 \r
+  if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Retrieve the private context structure\r
+  //\r
+  Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
+  FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+\r
+  //\r
+  // Make sure the descriptor has already been loaded or refreshed\r
+  //\r
+  PopulateDescriptor (Private);\r
 \r
-  SetLastAttemptVersionInVariable (IncommingFwVersion); //set to 0 to clear any previous results.\r
+  //\r
+  // Set to 0 to clear any previous results.\r
+  //\r
+  SetLastAttemptVersionInVariable (Private, IncommingFwVersion);\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 (mFmpDeviceLocked) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Device is already locked.  Can't update.\n"));\r
+  if (Private->FmpDeviceLocked) {\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
@@ -937,7 +1013,7 @@ SetTheImage (
   //\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
@@ -950,7 +1026,7 @@ 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
@@ -959,35 +1035,34 @@ SetTheImage (
     //\r
     // Set to actual value\r
     //\r
-    SetLastAttemptVersionInVariable (IncommingFwVersion);\r
+    SetLastAttemptVersionInVariable (Private, IncommingFwVersion);\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
     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
 \r
   mProgressFunc = Progress;\r
-  mProgressSupported = TRUE;\r
 \r
   //\r
   // Checking the image is at least 1%\r
   //\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
@@ -995,14 +1070,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
@@ -1015,14 +1090,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
@@ -1034,14 +1109,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
@@ -1052,20 +1127,20 @@ 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
   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
@@ -1087,7 +1162,7 @@ SetTheImage (
              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
@@ -1101,39 +1176,24 @@ SetTheImage (
   //\r
   // Update the version stored in variable\r
   //\r
-  if (!mRuntimeVersionSupported) {\r
-    UINT32 Version = DEFAULT_VERSION;\r
+  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
-    UINT32 Version = DEFAULT_LOWESTSUPPORTEDVERSION;\r
-    GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &Version);\r
-    SetLowestSupportedVersionInVariable (Version);\r
-  }\r
+  LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
+  GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);\r
+  SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion);\r
 \r
   LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
 \r
-  //\r
-  // Set flag so the descriptor is repopulated\r
-  // This is only applied to devices that do not require reset\r
-  //\r
-  GetAttributesStatus = FmpDeviceGetAttributes (&AttributesSupported, &AttributesSetting);\r
-  if (!EFI_ERROR (GetAttributesStatus)) {\r
-    if (((AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED) == 0) ||\r
-        ((AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED) == 0)) {\r
-      mDescriptorPopulated = FALSE;\r
-    }\r
-  }\r
-\r
 cleanup:\r
   mProgressFunc = NULL;\r
-  mProgressSupported = FALSE;\r
-  SetLastAttemptStatusInVariable (LastAttemptStatus);\r
+  SetLastAttemptStatusInVariable (Private, LastAttemptStatus);\r
 \r
   if (Progress != NULL) {\r
     //\r
@@ -1142,6 +1202,12 @@ cleanup:
     Progress (100);\r
   }\r
 \r
+  //\r
+  // Need repopulate after SetImage is called to\r
+  // update LastAttemptVersion and LastAttemptStatus.\r
+  //\r
+  Private->DescriptorPopulated = FALSE;\r
+\r
   return Status;\r
 }\r
 \r
@@ -1251,35 +1317,25 @@ FmpDxeLockEventNotify (
   IN VOID       *Context\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
+  EFI_STATUS                        Status;\r
+  FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;\r
 \r
-  if (!mFmpDeviceLocked) {\r
-    if (IsLockFmpDeviceAtLockEventGuidRequired ()) {\r
-      //\r
-      // Lock all UEFI Variables used by this module.\r
-      //\r
-      Status = LockAllFmpVariables ();\r
-      if (EFI_ERROR (Status)) {\r
-        DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variables.  Status = %r.\n"));\r
-      } else {\r
-        DEBUG ((DEBUG_INFO, "FmpDxe: All variables locked\n"));\r
-      }\r
+  Private = (FIRMWARE_MANAGEMENT_PRIVATE_DATA *)Context;\r
 \r
-      //\r
-      // Lock the firmware device\r
-      //\r
-      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
-        } else {\r
-          DEBUG ((DEBUG_WARN, "FmpDxe: FmpDeviceLock() returned error.  Status = %r\n", Status));\r
-        }\r
+  if (!Private->FmpDeviceLocked) {\r
+    //\r
+    // Lock the firmware device\r
+    //\r
+    FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+    Status = FmpDeviceLock();\r
+    if (EFI_ERROR (Status)) {\r
+      if (Status != EFI_UNSUPPORTED) {\r
+        DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLock() returned error.  Status = %r\n", mImageIdName, Status));\r
+      } else {\r
+        DEBUG ((DEBUG_WARN, "FmpDxe(%s): FmpDeviceLock() returned error.  Status = %r\n", mImageIdName, Status));\r
       }\r
-      mFmpDeviceLocked = TRUE;\r
-    } else {\r
-      DEBUG ((DEBUG_VERBOSE, "FmpDxe: Not calling FmpDeviceLock() because mfg mode\n"));\r
     }\r
+    Private->FmpDeviceLocked = TRUE;\r
   }\r
 }\r
 \r
@@ -1299,85 +1355,233 @@ InstallFmpInstance (
   IN EFI_HANDLE  Handle\r
   )\r
 {\r
-  EFI_STATUS                                   Status;\r
-  EFI_FIRMWARE_MANAGEMENT_PROTOCOL             *Fmp;\r
-  EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL  *FmpProgress;\r
-\r
-  Status      = EFI_SUCCESS;\r
-  Fmp         = NULL;\r
-  FmpProgress = NULL;\r
+  EFI_STATUS                        Status;\r
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;\r
+  FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;\r
 \r
   //\r
   // Only allow a single FMP Protocol instance to be installed\r
   //\r
-  if (mFmpInstalled) {\r
+  Status = gBS->OpenProtocol (\r
+                  Handle,\r
+                  &gEfiFirmwareManagementProtocolGuid,\r
+                  (VOID **)&Fmp,\r
+                  NULL,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
     return EFI_ALREADY_STARTED;\r
   }\r
 \r
   //\r
   // Allocate FMP Protocol instance\r
   //\r
-  Fmp = AllocateZeroPool (sizeof (EFI_FIRMWARE_MANAGEMENT_PROTOCOL));\r
-  if (Fmp == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for FMP Protocol instance.\n"));\r
+  Private = AllocateCopyPool (\r
+              sizeof (mFirmwareManagementPrivateDataTemplate),\r
+              &mFirmwareManagementPrivateDataTemplate\r
+              );\r
+  if (Private == NULL) {\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
 \r
   //\r
-  // Allocate FMP Progress Protocol instance\r
+  // Initialize private context data structure\r
   //\r
-  FmpProgress = AllocateZeroPool (sizeof (EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL));\r
-  if (FmpProgress == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for FMP Progress Protocol instance.\n"));\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    FreePool (Fmp);\r
+  Private->Handle = Handle;\r
+  Private->FmpDeviceContext = NULL;\r
+  Status = FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+  if (Status == EFI_UNSUPPORTED) {\r
+    Private->FmpDeviceContext = NULL;\r
+  } else if (EFI_ERROR (Status)) {\r
     goto cleanup;\r
   }\r
 \r
   //\r
-  // Set up FMP Protocol function pointers\r
+  // Make sure the descriptor has already been loaded or refreshed\r
   //\r
-  Fmp->GetImageInfo   = GetTheImageInfo;\r
-  Fmp->GetImage       = GetTheImage;\r
-  Fmp->SetImage       = SetTheImage;\r
-  Fmp->CheckImage     = CheckTheImage;\r
-  Fmp->GetPackageInfo = GetPackageInfo;\r
-  Fmp->SetPackageInfo = SetPackageInfo;\r
+  PopulateDescriptor (Private);\r
 \r
-  //\r
-  // Fill in FMP Progress Protocol fields for Version 1\r
-  //\r
-  FmpProgress->Version                        = 1;\r
-  FmpProgress->ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);\r
-  FmpProgress->WatchdogSeconds                = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);\r
+  if (IsLockFmpDeviceAtLockEventGuidRequired ()) {\r
+    //\r
+    // Register all UEFI Variables used by this module to be locked.\r
+    //\r
+    Status = LockAllFmpVariables (Private);\r
+    if (EFI_ERROR (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(%s): All variables registered to lock\n", mImageIdName));\r
+    }\r
+\r
+    //\r
+    // Create and register notify function to lock the FMP device.\r
+    //\r
+    Status = gBS->CreateEventEx (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_CALLBACK,\r
+                    FmpDxeLockEventNotify,\r
+                    Private,\r
+                    mLockGuid,\r
+                    &Private->FmpDeviceLockEvent\r
+                    );\r
+    if (EFI_ERROR (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(%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
   Status = gBS->InstallMultipleProtocolInterfaces (\r
-                  &Handle,\r
-                  &gEfiFirmwareManagementProtocolGuid,\r
-                  Fmp,\r
-                  &gEdkiiFirmwareManagementProgressProtocolGuid,\r
-                  FmpProgress,\r
+                  &Private->Handle,\r
+                  &gEfiFirmwareManagementProtocolGuid, &Private->Fmp,\r
+                  &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress,\r
                   NULL\r
                   );\r
-\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: FMP Protocol install error. Status = %r.\n", Status));\r
-    FreePool (Fmp);\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol install error. Status = %r.\n", mImageIdName, Status));\r
     goto cleanup;\r
   }\r
 \r
-  DEBUG ((DEBUG_INFO, "FmpDxe: FMP Protocol Installed!\n"));\r
-  mFmpInstalled = TRUE;\r
-\r
 cleanup:\r
 \r
+  if (EFI_ERROR (Status)) {\r
+    if (Private != NULL) {\r
+      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
+\r
   return Status;\r
 }\r
 \r
+/**\r
+  Function to uninstall FMP instance.\r
+\r
+  @param[in]  Handle  The device handle to install a FMP instance on.\r
+\r
+  @retval  EFI_SUCCESS            FMP Installed\r
+  @retval  EFI_INVALID_PARAMETER  Handle was invalid\r
+  @retval  other                  Error installing FMP\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UninstallFmpInstance (\r
+  IN EFI_HANDLE  Handle\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;\r
+  FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Handle,\r
+                  &gEfiFirmwareManagementProtocolGuid,\r
+                  (VOID **)&Fmp,\r
+                  NULL,\r
+                  NULL,\r
+                  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
+  Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (Fmp);\r
+  FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
+\r
+  if (Private->FmpDeviceLockEvent != NULL) {\r
+    gBS->CloseEvent (Private->FmpDeviceLockEvent);\r
+  }\r
+\r
+  Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                  Private->Handle,\r
+                  &gEfiFirmwareManagementProtocolGuid, &Private->Fmp,\r
+                  &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress,\r
+                  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
+  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
+}\r
+\r
+/**\r
+  Unloads the application and its installed protocol.\r
+\r
+  @param ImageHandle       Handle that identifies the image to be unloaded.\r
+  @param  SystemTable      The system table.\r
+\r
+  @retval EFI_SUCCESS      The image has been unloaded.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FmpDxeLibDestructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  if (mFmpSingleInstance) {\r
+    return UninstallFmpInstance (ImageHandle);\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Main entry for this driver/library.\r
 \r
@@ -1393,7 +1597,6 @@ FmpDxeEntryPoint (
   )\r
 {\r
   EFI_STATUS  Status;\r
-  EFI_GUID    *LockGuid;\r
 \r
   //\r
   // Verify that a new FILE_GUID value has been provided in the <Defines>\r
@@ -1414,8 +1617,9 @@ 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
@@ -1423,6 +1627,23 @@ FmpDxeEntryPoint (
   //\r
   DetectTestKey ();\r
 \r
+  //\r
+  // Fill in FMP Progress Protocol fields for Version 1\r
+  //\r
+  mFmpProgress.Version                        = 1;\r
+  mFmpProgress.ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);\r
+  mFmpProgress.WatchdogSeconds                = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);\r
+\r
+  // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.\r
+  // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then\r
+  // gEfiEndOfDxeEventGroupGuid is used.\r
+  //\r
+  mLockGuid = &gEfiEndOfDxeEventGroupGuid;\r
+  if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {\r
+    mLockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);\r
+  }\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
   // UEFI driver model/driver binding protocol it can install FMP on its device handle\r
@@ -1431,41 +1652,28 @@ FmpDxeEntryPoint (
   //\r
   Status = RegisterFmpInstaller (InstallFmpInstance);\r
   if (Status == EFI_UNSUPPORTED) {\r
-    DEBUG ((DEBUG_INFO, "FmpDxe: FmpDeviceLib registration returned EFI_UNSUPPORTED.  Installing single FMP instance.\n"));\r
-    Status = InstallFmpInstance (ImageHandle);\r
+    mFmpSingleInstance = TRUE;\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(%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(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));\r
+    }\r
   }\r
 \r
-  //\r
-  // Register notify function to lock the FMP device.\r
-  // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.\r
-  // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then\r
-  // gEfiEndOfDxeEventGroupGuid is used.\r
-  //\r
-  LockGuid = &gEfiEndOfDxeEventGroupGuid;\r
-  if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {\r
-    LockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);\r
-  }\r
-  DEBUG ((DEBUG_INFO, "FmpDxe: Lock GUID: %g\n", LockGuid));\r
-\r
-  Status = gBS->CreateEventEx (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
-                  FmpDxeLockEventNotify,\r
-                  NULL,\r
-                  LockGuid,\r
-                  &mFmpDeviceLockEvent\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to register for ready to boot.  Status = %r\n", Status));\r
-  }\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
   return Status;\r
 }\r