* [PATCH 1/3] MdeModulePkg/EsrtFmpDxe: Merge multiple FMP into ESRT
@ 2019-07-31 15:00 Eric Jin
0 siblings, 0 replies; only message in thread
From: Eric Jin @ 2019-07-31 15:00 UTC (permalink / raw)
To: devel; +Cc: Sean Brogan, Bret Barkelew, Jian J Wang, Hao A Wu,
Michael D Kinney
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1525
If there are multiple FMP instances for the same GUID,
then merge them together into a single ESRT entry.
Generate DEBUG_ERROR message and ASSERT() if the same
GUID/HardwareInstance is produced by more than one FMP.
Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Eric Jin <eric.jin@intel.com>
---
MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c | 137 +++++++++++++++++---
1 file changed, 120 insertions(+), 17 deletions(-)
diff --git a/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c
index 2356da662e..d48f205797 100644
--- a/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c
+++ b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c
@@ -2,7 +2,7 @@
Publishes ESRT table from Firmware Management Protocol instances
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.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -102,8 +102,8 @@ IsSystemFmp (
/**
Function to create a single ESRT Entry and add it to the ESRT
- given a FMP descriptor. If the guid is already in the ESRT it
- will be ignored. The ESRT will grow if it does not have enough room.
+ given a FMP descriptor. If the guid is already in the ESRT, then the ESRT
+ entry is updated. The ESRT will grow if it does not have enough room.
@param[in, out] Table On input, pointer to the pointer to the ESRT.
On output, same as input or pointer to the pointer
@@ -117,6 +117,7 @@ IsSystemFmp (
EFI_STATUS
CreateEsrtEntry (
IN OUT EFI_SYSTEM_RESOURCE_TABLE **Table,
+ IN OUT UINT64 **HardwareInstances,
IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf,
IN UINT32 FmpVersion
)
@@ -125,18 +126,78 @@ CreateEsrtEntry (
EFI_SYSTEM_RESOURCE_ENTRY *Entry;
UINTN NewSize;
EFI_SYSTEM_RESOURCE_TABLE *NewTable;
+ UINT64 *NewHardwareInstances;
+ UINT64 FmpHardwareInstance;
Index = 0;
Entry = NULL;
Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)((*Table) + 1);
//
- // Make sure Guid isn't already in the list
+ // Check to see if GUID is already in the table
//
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;
+ //
+ // If HardwareInstance in ESRT and FmpImageInfoBuf are the same value
+ // for the same ImageTypeId GUID, then there is more than one FMP
+ // instance for the same FW device, which is an error condition.
+ // If FmpVersion is less than 3, then assume HardwareInstance is 0.
+ //
+ FmpHardwareInstance = 0;
+ if (FmpVersion >= 3) {
+ FmpHardwareInstance = FmpImageInfoBuf->HardwareInstance;
+ }
+ if ((*HardwareInstances)[Index] == FmpHardwareInstance) {
+ DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: ESRT Entry already exists for FMP Instance with GUID %g and HardwareInstance %016lx\n", &Entry->FwClass, (*HardwareInstances)[Index]));
+ ASSERT ((*HardwareInstances)[Index] != FmpHardwareInstance);
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((DEBUG_INFO, "EsrtFmpDxe: ESRT Entry already exists for FMP Instance with GUID %g\n", &Entry->FwClass));
+
+ //
+ // Set ESRT FwVersion to the smaller of the two values
+ //
+ 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) {
+ Entry->LastAttemptVersion =
+ MIN (
+ FmpImageInfoBuf->LastAttemptVersion,
+ Entry->LastAttemptVersion
+ );
+ //
+ // 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 (Entry->LastAttemptStatus == LAST_ATTEMPT_STATUS_SUCCESS) {
+ if (FmpImageInfoBuf->LastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {
+ Entry->LastAttemptStatus = FmpImageInfoBuf->LastAttemptStatus;
+ Entry->LastAttemptVersion = FmpImageInfoBuf->LastAttemptVersion;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
}
Entry++;
}
@@ -171,6 +232,29 @@ CreateEsrtEntry (
// Reassign pointer to new table.
//
(*Table) = NewTable;
+
+ NewSize = ((*Table)->FwResourceCountMax) * sizeof (UINT64);
+ NewHardwareInstances = AllocateZeroPool (NewSize);
+ if (NewHardwareInstances == NULL) {
+ DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to allocate memory larger table for Hardware Instances.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Copy the whole old table into new table buffer
+ //
+ CopyMem (
+ NewHardwareInstances,
+ (*HardwareInstances),
+ ((*Table)->FwResourceCountMax) * sizeof (UINT64)
+ );
+ //
+ // Free old table
+ //
+ FreePool ((*HardwareInstances));
+ //
+ // Reassign pointer to new table.
+ //
+ (*HardwareInstances) = NewHardwareInstances;
}
//
@@ -181,10 +265,6 @@ CreateEsrtEntry (
// Move to the location of new entry
//
Entry = Entry + (*Table)->FwResourceCount;
- //
- // Increment resource count
- //
- (*Table)->FwResourceCount++;
CopyGuid (&Entry->FwClass, &FmpImageInfoBuf->ImageTypeId);
@@ -195,11 +275,11 @@ CreateEsrtEntry (
Entry->FwType = (UINT32)(ESRT_FW_TYPE_DEVICEFIRMWARE);
}
- Entry->FwVersion = FmpImageInfoBuf->Version;
+ Entry->FwVersion = FmpImageInfoBuf->Version;
Entry->LowestSupportedFwVersion = 0;
- Entry->CapsuleFlags = 0;
- Entry->LastAttemptVersion = 0;
- Entry->LastAttemptStatus = 0;
+ Entry->CapsuleFlags = 0;
+ Entry->LastAttemptVersion = 0;
+ Entry->LastAttemptStatus = 0;
//
// VERSION 2 has Lowest Supported
@@ -213,9 +293,22 @@ CreateEsrtEntry (
//
if (FmpVersion >= 3) {
Entry->LastAttemptVersion = FmpImageInfoBuf->LastAttemptVersion;
- Entry->LastAttemptStatus = FmpImageInfoBuf->LastAttemptStatus;
+ Entry->LastAttemptStatus = FmpImageInfoBuf->LastAttemptStatus;
+ }
+
+ //
+ // VERSION 3 supports hardware instance
+ //
+ (*HardwareInstances)[(*Table)->FwResourceCount] = 0;
+ if (FmpVersion >= 3) {
+ (*HardwareInstances)[(*Table)->FwResourceCount] = FmpImageInfoBuf->HardwareInstance;
}
+ //
+ // Increment resource count
+ //
+ (*Table)->FwResourceCount++;
+
return EFI_SUCCESS;
}
@@ -234,6 +327,7 @@ CreateFmpBasedEsrt (
{
EFI_STATUS Status;
EFI_SYSTEM_RESOURCE_TABLE *Table;
+ UINT64 *HardwareInstances;
UINTN NoProtocols;
VOID **Buffer;
UINTN Index;
@@ -249,6 +343,7 @@ CreateFmpBasedEsrt (
Status = EFI_SUCCESS;
Table = NULL;
+ HardwareInstances = NULL;
NoProtocols = 0;
Buffer = NULL;
PackageVersionName = NULL;
@@ -266,7 +361,7 @@ CreateFmpBasedEsrt (
}
//
- // Allocate Memory for table
+ // Allocate Memory for tables
//
Table = AllocateZeroPool (
(GROWTH_STEP * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE)
@@ -277,6 +372,14 @@ CreateFmpBasedEsrt (
return NULL;
}
+ HardwareInstances = AllocateZeroPool (GROWTH_STEP * sizeof (UINT64));
+ if (HardwareInstances == NULL) {
+ DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to allocate memory for HW Instance Table.\n"));
+ gBS->FreePool (Table);
+ gBS->FreePool (Buffer);
+ return NULL;
+ }
+
Table->FwResourceCount = 0;
Table->FwResourceCountMax = GROWTH_STEP;
Table->FwResourceVersion = EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION;
@@ -337,7 +440,7 @@ CreateFmpBasedEsrt (
//
// Create ESRT entry
//
- CreateEsrtEntry (&Table, FmpImageInfoBuf, FmpImageInfoDescriptorVer);
+ CreateEsrtEntry (&Table, &HardwareInstances, FmpImageInfoBuf, FmpImageInfoDescriptorVer);
}
FmpImageInfoCount--;
//
--
2.20.1.windows.1
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2019-07-31 15:01 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-07-31 15:00 [PATCH 1/3] MdeModulePkg/EsrtFmpDxe: Merge multiple FMP into ESRT Eric Jin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox