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