]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/EsrtFmpDxe: Enhance ESRT to support multiple controllers
authorJin, Eric <eric.jin@intel.com>
Mon, 5 Aug 2019 08:02:48 +0000 (16:02 +0800)
committerHao A Wu <hao.a.wu@intel.com>
Wed, 7 Aug 2019 05:18:32 +0000 (13:18 +0800)
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1525

The patch is to merge multiple FMP instances into single ESRT entry
when they have the same GUID.

The policy to LastAttemptStatus/LastAttemptVersion of ESRT entry is:
If all the LastAttemptStatus are LAST_ATTEMPT_STATUS_SUCCESS, then
LastAttemptVersion should be the smallest of LastAttemptVersion. If
any of the LastAttemptStatus is not LAST_ATTEMPT_STATUS_SUCCESS,
then the LastAttemptVersion/LastAttemptStatus should be the values
of the first FMP instance whose LastAttemptStatus is not
LAST_ATTEMPT_STATUS_SUCCESS.

To detect possible duplicated GUID/HardwareInstance, a table of
GUID/HardwareInstance pairs from all the EFI_FIRMWARE_IMAGE_DESCRIPTORs
from all FMP instances is built. If a duplicate is found, then generate
a DEBUG_ERROR message, generate an ASSERT(), and ignore the duplicate
EFI_FIRMWARE_IMAGE_DESCRIPTOR.

Add an internal worker function called FmpGetFirmwareImageDescriptor()
that retrieves the list of EFI_FIRMWARE_IMAGE_DESCRIPTORs from a single
FMP instance and returns the descriptors in an allocated buffer. This
function is used to get the descriptors used to build the table of
unique GUID/HardwareInstance pairs.  It is then used again to generate
the ESRT Table from all the EFI_FIRMWARE_IMAGE_DESCRIPTORs from all the
FMP instances. 2 passes are performed so the total number of
descriptors is known. This allows the correct sized buffers to always
be allocated.

Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: Eric Jin <eric.jin@intel.com>
Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c

index 2356da662e288e594ffd6cc99904e9e79ba43dfd..4670349f89d73a9814df9e9d37adb4ebf8486849 100644 (file)
@@ -2,7 +2,7 @@
   Publishes ESRT table from Firmware Management Protocol instances\r
 \r
   Copyright (c) 2016, Microsoft Corporation\r
-  Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r
 \r
   All rights reserved.\r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #include <Guid/EventGroup.h>\r
 #include <Guid/SystemResourceTable.h>\r
 \r
+///\r
+/// Structure for array of unique GUID/HardwareInstance pairs from the\r
+/// current set of EFI_FIRMWARE_IMAGE_DESCRIPTORs from all FMP Protocols.\r
+///\r
+typedef struct {\r
+  ///\r
+  /// A unique GUID identifying the firmware image type.\r
+  ///\r
+  EFI_GUID                      ImageTypeGuid;\r
+  ///\r
+  /// An optional number to identify the unique hardware instance within the\r
+  /// system for devices that may have multiple instances whenever possible.\r
+  ///\r
+  UINT64                        HardwareInstance;\r
+} GUID_HARDWAREINSTANCE_PAIR;\r
+\r
 /**\r
  Print ESRT to debug console.\r
 \r
@@ -33,11 +49,6 @@ PrintTable (
   IN EFI_SYSTEM_RESOURCE_TABLE  *Table\r
   );\r
 \r
-//\r
-// Number of ESRT entries to grow by each time we run out of room\r
-//\r
-#define GROWTH_STEP  10\r
-\r
 /**\r
   Install EFI System Resource Table into the UEFI Configuration Table\r
 \r
@@ -101,90 +112,129 @@ IsSystemFmp (
 }\r
 \r
 /**\r
-  Function to create a single ESRT Entry and add it to the ESRT\r
-  given a FMP descriptor.  If the guid is already in the ESRT it\r
-  will be ignored.  The ESRT will grow if it does not have enough room.\r
-\r
-  @param[in, out] Table             On input, pointer to the pointer to the ESRT.\r
-                                    On output, same as input or pointer to the pointer\r
-                                    to new enlarged ESRT.\r
-  @param[in]      FmpImageInfoBuf   Pointer to the EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
-  @param[in]      FmpVersion        FMP Version.\r
-\r
-  @return  Status code.\r
+  Function to create a single ESRT Entry and add it to the ESRT with\r
+  a given FMP descriptor.  If the GUID is already in the ESRT, then the ESRT\r
+  entry is updated.\r
+\r
+  @param[in,out] Table                Pointer to the ESRT Table.\r
+  @param[in,out] HardwareInstances    Pointer to the GUID_HARDWAREINSTANCE_PAIR.\r
+  @param[in,out] NumberOfDescriptors  The number of EFI_FIRMWARE_IMAGE_DESCRIPTORs.\r
+  @param[in]     FmpImageInfoBuf      Pointer to the EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+  @param[in]     FmpVersion           FMP Version.\r
+\r
+  @retval  EFI_SUCCESS     FmpImageInfoBuf was use to fill in a new ESRT entry\r
+                           in Table.\r
+  @retval  EFI_SUCCESS     The ImageTypeId GUID in FmpImageInfoBuf matches an\r
+                           existing ESRT entry in Table, and the information\r
+                           from FmpImageInfoBuf was merged into the the existing\r
+                           ESRT entry.\r
+  @retval  EFI_UNSPOORTED  The GUID/HardareInstance in FmpImageInfoBuf has is a\r
+                           duplicate.\r
 \r
 **/\r
 EFI_STATUS\r
 CreateEsrtEntry (\r
-  IN OUT EFI_SYSTEM_RESOURCE_TABLE  **Table,\r
-  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR  *FmpImageInfoBuf,\r
-  IN UINT32                         FmpVersion\r
+  IN OUT EFI_SYSTEM_RESOURCE_TABLE      *Table,\r
+  IN OUT GUID_HARDWAREINSTANCE_PAIR     *HardwareInstances,\r
+  IN OUT UINT32                         *NumberOfDescriptors,\r
+  IN     EFI_FIRMWARE_IMAGE_DESCRIPTOR  *FmpImageInfoBuf,\r
+  IN     UINT32                         FmpVersion\r
   )\r
 {\r
   UINTN                      Index;\r
   EFI_SYSTEM_RESOURCE_ENTRY  *Entry;\r
-  UINTN                      NewSize;\r
-  EFI_SYSTEM_RESOURCE_TABLE  *NewTable;\r
+  UINT64                     FmpHardwareInstance;\r
 \r
-  Index = 0;\r
-  Entry = NULL;\r
+  FmpHardwareInstance = 0;\r
+  if (FmpVersion >= 3) {\r
+    FmpHardwareInstance = FmpImageInfoBuf->HardwareInstance;\r
+  }\r
 \r
-  Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)((*Table) + 1);\r
   //\r
-  // Make sure Guid isn't already in the list\r
+  // Check to see of FmpImageInfoBuf GUID/HardwareInstance is unique\r
   //\r
-  for (Index = 0; Index < (*Table)->FwResourceCount; Index++) {\r
-    if (CompareGuid (&Entry->FwClass, &FmpImageInfoBuf->ImageTypeId)) {\r
-      DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: ESRT Entry already exists for FMP Instance with GUID %g\n", &Entry->FwClass));\r
-      return EFI_INVALID_PARAMETER;\r
+  for (Index = 0; Index < *NumberOfDescriptors; Index++) {\r
+    if (CompareGuid (&HardwareInstances[Index].ImageTypeGuid, &FmpImageInfoBuf->ImageTypeId)) {\r
+      if (HardwareInstances[Index].HardwareInstance == FmpHardwareInstance) {\r
+        DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Duplicate firmware image descriptor with GUID %g HardwareInstance:0x%x\n", &FmpImageInfoBuf->ImageTypeId, FmpHardwareInstance));\r
+        ASSERT (\r
+          !CompareGuid (&HardwareInstances[Index].ImageTypeGuid, &FmpImageInfoBuf->ImageTypeId) ||\r
+          HardwareInstances[Index].HardwareInstance != FmpHardwareInstance\r
+          );\r
+        return EFI_UNSUPPORTED;\r
+      }\r
     }\r
-    Entry++;\r
   }\r
 \r
   //\r
-  // Grow table if needed\r
+  // Record new GUID/HardwareInstance pair\r
   //\r
-  if ((*Table)->FwResourceCount >= (*Table)->FwResourceCountMax) {\r
-    NewSize  = (((*Table)->FwResourceCountMax + GROWTH_STEP) * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE);\r
-    NewTable = AllocateZeroPool (NewSize);\r
-    if (NewTable == NULL) {\r
-      DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to allocate memory larger table for ESRT. \n"));\r
-      return EFI_OUT_OF_RESOURCES;\r
+  CopyGuid (&HardwareInstances[*NumberOfDescriptors].ImageTypeGuid, &FmpImageInfoBuf->ImageTypeId);\r
+  HardwareInstances[*NumberOfDescriptors].HardwareInstance = FmpHardwareInstance;\r
+  *NumberOfDescriptors = *NumberOfDescriptors + 1;\r
+\r
+  DEBUG ((DEBUG_INFO, "EsrtFmpDxe: Add new image descriptor with GUID %g HardwareInstance:0x%x\n", &FmpImageInfoBuf->ImageTypeId, FmpHardwareInstance));\r
+\r
+  //\r
+  // Check to see if GUID is already in the ESRT table\r
+  //\r
+  Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)(Table + 1);\r
+  for (Index = 0; Index < Table->FwResourceCount; Index++, Entry++) {\r
+    if (!CompareGuid (&Entry->FwClass, &FmpImageInfoBuf->ImageTypeId)) {\r
+      continue;\r
     }\r
+    DEBUG ((DEBUG_INFO, "EsrtFmpDxe: ESRT Entry already exists for FMP Instance with GUID %g\n", &Entry->FwClass));\r
+\r
     //\r
-    // Copy the whole old table into new table buffer\r
-    //\r
-    CopyMem (\r
-      NewTable,\r
-      (*Table),\r
-      (((*Table)->FwResourceCountMax) * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE)\r
-      );\r
-    //\r
-    // Update max\r
+    // Set ESRT FwVersion to the smaller of the two values\r
     //\r
-    NewTable->FwResourceCountMax = NewTable->FwResourceCountMax + GROWTH_STEP;\r
+    Entry->FwVersion = MIN (FmpImageInfoBuf->Version, Entry->FwVersion);\r
+\r
     //\r
-    // Free old table\r
+    // VERSION 2 has Lowest Supported\r
     //\r
-    FreePool ((*Table));\r
+    if (FmpVersion >= 2) {\r
+      //\r
+      // Set ESRT LowestSupportedFwVersion to the smaller of the two values\r
+      //\r
+      Entry->LowestSupportedFwVersion =\r
+        MIN (\r
+          FmpImageInfoBuf->LowestSupportedImageVersion,\r
+          Entry->LowestSupportedFwVersion\r
+          );\r
+    }\r
+\r
     //\r
-    // Reassign pointer to new table.\r
+    // VERSION 3 supports last attempt values\r
     //\r
-    (*Table) = NewTable;\r
+    if (FmpVersion >= 3) {\r
+      //\r
+      // Update the ESRT entry with the last attempt status and last attempt\r
+      // version from the first FMP instance whose last attempt status is not\r
+      // SUCCESS.  If all FMP instances are SUCCESS, then set version to the\r
+      // smallest value from all FMP instances.\r
+      //\r
+      if (Entry->LastAttemptStatus == LAST_ATTEMPT_STATUS_SUCCESS) {\r
+        if (FmpImageInfoBuf->LastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {\r
+          Entry->LastAttemptStatus = FmpImageInfoBuf->LastAttemptStatus;\r
+          Entry->LastAttemptVersion = FmpImageInfoBuf->LastAttemptVersion;\r
+        } else {\r
+          Entry->LastAttemptVersion =\r
+            MIN (\r
+              FmpImageInfoBuf->LastAttemptVersion,\r
+              Entry->LastAttemptVersion\r
+              );\r
+        }\r
+      }\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
   }\r
 \r
   //\r
-  // ESRT table has enough room for the new entry so add new entry\r
-  //\r
-  Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)(((UINT8 *)(*Table)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE));\r
-  //\r
-  // Move to the location of new entry\r
-  //\r
-  Entry = Entry + (*Table)->FwResourceCount;\r
+  // Add a new ESRT Table Entry\r
   //\r
-  // Increment resource count\r
-  //\r
-  (*Table)->FwResourceCount++;\r
+  Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)(Table + 1) + Table->FwResourceCount;\r
 \r
   CopyGuid (&Entry->FwClass, &FmpImageInfoBuf->ImageTypeId);\r
 \r
@@ -195,11 +245,11 @@ CreateEsrtEntry (
     Entry->FwType = (UINT32)(ESRT_FW_TYPE_DEVICEFIRMWARE);\r
   }\r
 \r
-  Entry->FwVersion = FmpImageInfoBuf->Version;\r
+  Entry->FwVersion                = FmpImageInfoBuf->Version;\r
   Entry->LowestSupportedFwVersion = 0;\r
-  Entry->CapsuleFlags = 0;\r
-  Entry->LastAttemptVersion = 0;\r
-  Entry->LastAttemptStatus = 0;\r
+  Entry->CapsuleFlags             = 0;\r
+  Entry->LastAttemptVersion       = 0;\r
+  Entry->LastAttemptStatus        = 0;\r
 \r
   //\r
   // VERSION 2 has Lowest Supported\r
@@ -213,12 +263,93 @@ CreateEsrtEntry (
   //\r
   if (FmpVersion >= 3) {\r
     Entry->LastAttemptVersion = FmpImageInfoBuf->LastAttemptVersion;\r
-    Entry->LastAttemptStatus = FmpImageInfoBuf->LastAttemptStatus;\r
+    Entry->LastAttemptStatus  = FmpImageInfoBuf->LastAttemptStatus;\r
   }\r
 \r
+  //\r
+  // Increment the number of active ESRT Table Entries\r
+  //\r
+  Table->FwResourceCount++;\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Function to retrieve the EFI_FIRMWARE_IMAGE_DESCRIPTOR from an FMP Instance.\r
+  The returned buffer is allocated using AllocatePool() and must be freed by the\r
+  caller using FreePool().\r
+\r
+  @param[in]  Fmp                        Pointer to an EFI_FIRMWARE_MANAGEMENT_PROTOCOL.\r
+  @param[out] FmpImageInfoDescriptorVer  Pointer to the version number associated\r
+                                         with the returned EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+  @param[out] FmpImageInfoCount          Pointer to the number of the returned\r
+                                         EFI_FIRMWARE_IMAGE_DESCRIPTORs.\r
+  @param[out] DescriptorSize             Pointer to the size, in bytes, of each\r
+                                         returned EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+\r
+  @return  Pointer to the retrieved EFI_FIRMWARE_IMAGE_DESCRIPTOR.  If the\r
+           descriptor can not be retrieved, then NULL is returned.\r
+\r
+**/\r
+EFI_FIRMWARE_IMAGE_DESCRIPTOR *\r
+FmpGetFirmwareImageDescriptor (\r
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp,\r
+  OUT UINT32                            *FmpImageInfoDescriptorVer,\r
+  OUT UINT8                             *FmpImageInfoCount,\r
+  OUT UINTN                             *DescriptorSize\r
+  )\r
+{\r
+  EFI_STATUS                     Status;\r
+  UINTN                          ImageInfoSize;\r
+  UINT32                         PackageVersion;\r
+  CHAR16                         *PackageVersionName;\r
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR  *FmpImageInfoBuf;\r
+\r
+  ImageInfoSize = 0;\r
+  Status = Fmp->GetImageInfo (\r
+                  Fmp,                        // FMP Pointer\r
+                  &ImageInfoSize,             // Buffer Size (in this case 0)\r
+                  NULL,                       // NULL so we can get size\r
+                  FmpImageInfoDescriptorVer,  // DescriptorVersion\r
+                  FmpImageInfoCount,          // DescriptorCount\r
+                  DescriptorSize,             // DescriptorSize\r
+                  &PackageVersion,            // PackageVersion\r
+                  &PackageVersionName         // PackageVersionName\r
+                  );\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Unexpected Failure in GetImageInfo.  Status = %r\n", Status));\r
+    return NULL;\r
+  }\r
+\r
+  FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
+  if (FmpImageInfoBuf == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to get memory for FMP descriptor.\n"));\r
+    return NULL;\r
+  }\r
+\r
+  PackageVersionName = NULL;\r
+  Status = Fmp->GetImageInfo (\r
+                  Fmp,                        // FMP Pointer\r
+                  &ImageInfoSize,             // ImageInfoSize\r
+                  FmpImageInfoBuf,            // ImageInfo\r
+                  FmpImageInfoDescriptorVer,  // DescriptorVersion\r
+                  FmpImageInfoCount,          // DescriptorCount\r
+                  DescriptorSize,             // DescriptorSize\r
+                  &PackageVersion,            // PackageVersion\r
+                  &PackageVersionName         // PackageVersionName\r
+                  );\r
+  if (PackageVersionName != NULL) {\r
+    FreePool (PackageVersionName);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failure in GetImageInfo.  Status = %r\n", Status));\r
+    FreePool (FmpImageInfoBuf);\r
+    return NULL;\r
+  }\r
+\r
+  return FmpImageInfoBuf;\r
+}\r
+\r
 /**\r
   Function to create ESRT based on FMP Instances.\r
   Create ESRT table, get the descriptors from FMP Instance and\r
@@ -232,29 +363,26 @@ CreateFmpBasedEsrt (
   VOID\r
   )\r
 {\r
-  EFI_STATUS                        Status;\r
-  EFI_SYSTEM_RESOURCE_TABLE         *Table;\r
-  UINTN                             NoProtocols;\r
-  VOID                              **Buffer;\r
-  UINTN                             Index;\r
-  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;\r
-  UINTN                             DescriptorSize;\r
-  EFI_FIRMWARE_IMAGE_DESCRIPTOR     *FmpImageInfoBuf;\r
-  EFI_FIRMWARE_IMAGE_DESCRIPTOR     *FmpImageInfoBufOrg;\r
-  UINT8                             FmpImageInfoCount;\r
-  UINT32                            FmpImageInfoDescriptorVer;\r
-  UINTN                             ImageInfoSize;\r
-  UINT32                            PackageVersion;\r
-  CHAR16                            *PackageVersionName;\r
+  EFI_STATUS                     Status;\r
+  UINTN                          NoProtocols;\r
+  VOID                           **Buffer;\r
+  UINTN                          Index;\r
+  UINT32                         FmpImageInfoDescriptorVer;\r
+  UINT8                          FmpImageInfoCount;\r
+  UINTN                          DescriptorSize;\r
+  UINT32                         NumberOfDescriptors;\r
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR  *FmpImageInfoBuf;\r
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR  *OrgFmpImageInfoBuf;\r
+  EFI_SYSTEM_RESOURCE_TABLE      *Table;\r
+  GUID_HARDWAREINSTANCE_PAIR     *HardwareInstances;\r
 \r
   Status             = EFI_SUCCESS;\r
-  Table              = NULL;\r
   NoProtocols        = 0;\r
   Buffer             = NULL;\r
-  PackageVersionName = NULL;\r
   FmpImageInfoBuf    = NULL;\r
-  FmpImageInfoBufOrg = NULL;\r
-  Fmp                = NULL;\r
+  OrgFmpImageInfoBuf = NULL;\r
+  Table              = NULL;\r
+  HardwareInstances  = NULL;\r
 \r
   Status = EfiLocateProtocolBuffer (\r
              &gEfiFirmwareManagementProtocolGuid,\r
@@ -266,69 +394,64 @@ CreateFmpBasedEsrt (
   }\r
 \r
   //\r
-  // Allocate Memory for table\r
+  // Count the total number of EFI_FIRMWARE_IMAGE_DESCRIPTORs\r
+  //\r
+  for (Index = 0, NumberOfDescriptors = 0; Index < NoProtocols; Index++) {\r
+    FmpImageInfoBuf = FmpGetFirmwareImageDescriptor (\r
+                        (EFI_FIRMWARE_MANAGEMENT_PROTOCOL *) Buffer[Index],\r
+                        &FmpImageInfoDescriptorVer,\r
+                        &FmpImageInfoCount,\r
+                        &DescriptorSize\r
+                        );\r
+    if (FmpImageInfoBuf != NULL) {\r
+      NumberOfDescriptors += FmpImageInfoCount;\r
+      FreePool (FmpImageInfoBuf);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Allocate ESRT Table and GUID/HardwareInstance table\r
   //\r
   Table = AllocateZeroPool (\r
-             (GROWTH_STEP * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE)\r
+             (NumberOfDescriptors * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE)\r
              );\r
   if (Table == NULL) {\r
     DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to allocate memory for ESRT.\n"));\r
-    gBS->FreePool (Buffer);\r
+    FreePool (Buffer);\r
     return NULL;\r
   }\r
 \r
+  HardwareInstances = AllocateZeroPool (NumberOfDescriptors * sizeof (GUID_HARDWAREINSTANCE_PAIR));\r
+  if (HardwareInstances == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to allocate memory for HW Instance Table.\n"));\r
+    FreePool (Table);\r
+    FreePool (Buffer);\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Initialize ESRT Table\r
+  //\r
   Table->FwResourceCount    = 0;\r
-  Table->FwResourceCountMax = GROWTH_STEP;\r
+  Table->FwResourceCountMax = NumberOfDescriptors;\r
   Table->FwResourceVersion  = EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION;\r
 \r
+  NumberOfDescriptors = 0;\r
   for (Index = 0; Index < NoProtocols; Index++) {\r
-    Fmp = (EFI_FIRMWARE_MANAGEMENT_PROTOCOL *) Buffer[Index];\r
-\r
-    ImageInfoSize = 0;\r
-    Status = Fmp->GetImageInfo (\r
-                    Fmp,                         // FMP Pointer\r
-                    &ImageInfoSize,              // Buffer Size (in this case 0)\r
-                    NULL,                        // NULL so we can get size\r
-                    &FmpImageInfoDescriptorVer,  // DescriptorVersion\r
-                    &FmpImageInfoCount,          // DescriptorCount\r
-                    &DescriptorSize,             // DescriptorSize\r
-                    &PackageVersion,             // PackageVersion\r
-                    &PackageVersionName          // PackageVersionName\r
-                    );\r
-\r
-    if (Status != EFI_BUFFER_TOO_SMALL) {\r
-      DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Unexpected Failure in GetImageInfo.  Status = %r\n", Status));\r
-      continue;\r
-    }\r
-\r
-    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
+    FmpImageInfoBuf = FmpGetFirmwareImageDescriptor (\r
+                        (EFI_FIRMWARE_MANAGEMENT_PROTOCOL *) Buffer[Index],\r
+                        &FmpImageInfoDescriptorVer,\r
+                        &FmpImageInfoCount,\r
+                        &DescriptorSize\r
+                        );\r
     if (FmpImageInfoBuf == NULL) {\r
-      DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to get memory for descriptors.\n"));\r
-      continue;\r
-    }\r
-\r
-    FmpImageInfoBufOrg = FmpImageInfoBuf;\r
-    PackageVersionName = NULL;\r
-    Status = Fmp->GetImageInfo (\r
-                    Fmp,\r
-                    &ImageInfoSize,              // ImageInfoSize\r
-                    FmpImageInfoBuf,             // ImageInfo\r
-                    &FmpImageInfoDescriptorVer,  // DescriptorVersion\r
-                    &FmpImageInfoCount,          // DescriptorCount\r
-                    &DescriptorSize,             // DescriptorSize\r
-                    &PackageVersion,             // PackageVersion\r
-                    &PackageVersionName          // PackageVersionName\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failure in GetImageInfo.  Status = %r\n", Status));\r
-      FreePool (FmpImageInfoBufOrg);\r
-      FmpImageInfoBufOrg = NULL;\r
       continue;\r
     }\r
 \r
     //\r
     // Check each descriptor and read from the one specified\r
     //\r
+    OrgFmpImageInfoBuf = FmpImageInfoBuf;\r
     while (FmpImageInfoCount > 0) {\r
       //\r
       // If the descriptor has the IN USE bit set, create ESRT entry otherwise ignore.\r
@@ -337,7 +460,7 @@ CreateFmpBasedEsrt (
         //\r
         // Create ESRT entry\r
         //\r
-        CreateEsrtEntry (&Table, FmpImageInfoBuf, FmpImageInfoDescriptorVer);\r
+        CreateEsrtEntry (Table, HardwareInstances, &NumberOfDescriptors, FmpImageInfoBuf, FmpImageInfoDescriptorVer);\r
       }\r
       FmpImageInfoCount--;\r
       //\r
@@ -346,15 +469,12 @@ CreateFmpBasedEsrt (
       FmpImageInfoBuf = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)(((UINT8 *)FmpImageInfoBuf) + DescriptorSize);\r
     }\r
 \r
-    if (PackageVersionName != NULL) {\r
-      FreePool (PackageVersionName);\r
-      PackageVersionName = NULL;\r
-    }\r
-    FreePool (FmpImageInfoBufOrg);\r
-    FmpImageInfoBufOrg = NULL;\r
+    FreePool (OrgFmpImageInfoBuf);\r
+    OrgFmpImageInfoBuf = NULL;\r
   }\r
 \r
-  gBS->FreePool (Buffer);\r
+  FreePool (Buffer);\r
+  FreePool (HardwareInstances);\r
   return Table;\r
 }\r
 \r