From: Michael D Kinney <michael.d.kinney@intel.com>
https://bugzilla.tianocore.org/show_bug.cgi?id=802
Based on content from the following branch/commits:
https://github.com/Microsoft/MS_UEFI/tree/share/MsCapsuleSupport
The EsrtFmpDxe module is a lightweight version of the EsrtDxe
module that produces ESRT entries based only on FMP Protocol
instances.
Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
---
MdeModulePkg/MdeModulePkg.dsc | 1 +
MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c | 482 +++++++++++++++++++++
.../Universal/EsrtFmpDxe/EsrtFmpDebugPrint.c | 161 +++++++
MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf | 74 ++++
MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.uni | 19 +
.../Universal/EsrtFmpDxe/EsrtFmpDxeExtra.uni | 18 +
6 files changed, 755 insertions(+)
create mode 100644 MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c
create mode 100644 MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDebugPrint.c
create mode 100644 MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf
create mode 100644 MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.uni
create mode 100644 MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxeExtra.uni
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 1c0085aee6..50002f8e3f 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -412,6 +412,7 @@
MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf
MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+ MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf
MdeModulePkg/Universal/PropertiesTableAttributesDxe/PropertiesTableAttributesDxe.inf
MdeModulePkg/Universal/FileExplorerDxe/FileExplorerDxe.inf {
diff --git a/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c
new file mode 100644
index 0000000000..b98430edbf
--- /dev/null
+++ b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c
@@ -0,0 +1,482 @@
+/** @file
+ Publishes ESRT table from Firmware Management Protocol instances
+
+ Copyright (c) 2016, Microsoft Corporation
+ Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/EventGroup.h>
+#include <Guid/SystemResourceTable.h>
+
+//
+// Print ESRT to debug console
+//
+VOID
+EFIAPI
+PrintTable (
+ IN EFI_SYSTEM_RESOURCE_TABLE *Table
+ );
+
+//
+// Number of ESRT entries to grow by each time we run out of room
+//
+#define GROWTH_STEP 10
+
+//
+// Module globals.
+//
+EFI_EVENT mEsrtReadyToBootEvent;
+EFI_SYSTEM_RESOURCE_TABLE *mTable = NULL;
+BOOLEAN mEsrtInstalled = FALSE;
+EFI_EVENT mFmpInstallEvent;
+VOID *mFmpInstallEventRegistration = NULL;
+
+/**
+ Install EFI System Resource Table into the UEFI Configuration Table
+
+ @return Status code.
+
+**/
+EFI_STATUS
+InstallEfiSystemResourceTableInUefiConfigurationTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ if (!mEsrtInstalled) {
+ if (mTable == NULL) {
+ DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Can't install ESRT table because it is NULL. \n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ } else if (mTable->FwResourceCount == 0) {
+ DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Can't install ESRT table because it has zero Entries. \n"));
+ Status = EFI_UNSUPPORTED;
+ } else {
+ //
+ // Install the pointer into config table
+ //
+ Status = gBS->InstallConfigurationTable (&gEfiSystemResourceTableGuid, mTable);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Can't install ESRT table. Status: %r. \n", Status));
+ } else {
+ DEBUG ((DEBUG_INFO, "EsrtFmpDxe: Installed ESRT table. \n"));
+ mEsrtInstalled = TRUE;
+ }
+ }
+ }
+ return Status;
+}
+
+/**
+ Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
+
+ @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR
+
+ @return TRUE It is a system FMP.
+ @return FALSE It is a device FMP.
+**/
+BOOLEAN
+IsSystemFmp (
+ IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo
+ )
+{
+ GUID *Guid;
+ UINTN Count;
+ UINTN Index;
+
+ Guid = PcdGetPtr (PcdSystemFmpCapsuleImageTypeIdGuid);
+ Count = PcdGetSize (PcdSystemFmpCapsuleImageTypeIdGuid) / sizeof(GUID);
+
+ for (Index = 0; Index < Count; Index++, Guid++) {
+ if (CompareGuid (&FmpImageInfo->ImageTypeId, Guid)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ 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.
+
+ @return Status code.
+
+**/
+EFI_STATUS
+EFIAPI
+CreateEsrtEntry (
+ IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf,
+ IN UINT32 FmpVersion
+ )
+{
+ UINTN Index;
+ EFI_SYSTEM_RESOURCE_ENTRY *Entry;
+ UINTN NewSize;
+ EFI_SYSTEM_RESOURCE_TABLE *NewTable;
+
+ Index = 0;
+ Entry = NULL;
+
+ //
+ // Get our ESRT table. This should never be null at this point
+ //
+ if (mTable == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)(mTable + 1);
+ //
+ // Make sure Guid isn't already in the list
+ //
+ for (Index = 0; Index < mTable->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
+ //
+ if (mTable->FwResourceCount >= mTable->FwResourceCountMax) {
+ //
+ // Can't grow table after installed.
+ // Only because didn't add support for this.
+ // Would need to re-install ESRT in system table if wanted to support
+ //
+ if (mEsrtInstalled) {
+ DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to install entry because ESRT table needed to grow after table already installed. \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewSize = ((mTable->FwResourceCountMax + GROWTH_STEP) * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE);
+ NewTable = AllocateRuntimeZeroPool (NewSize);
+ if (NewTable == NULL) {
+ DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to allocate memory larger table for ESRT. \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Copy the whole old table into new table buffer
+ //
+ CopyMem (
+ NewTable,
+ mTable,
+ ((mTable->FwResourceCountMax) * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE)
+ );
+ //
+ // Update max
+ //
+ NewTable->FwResourceCountMax = NewTable->FwResourceCountMax + GROWTH_STEP;
+ //
+ // Free old table
+ //
+ FreePool (mTable);
+ //
+ // Reassign pointer to new table.
+ //
+ mTable = NewTable;
+ }
+
+ //
+ // ESRT table has enough room for the new entry so add new entry
+ //
+ Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)(((UINT8 *)mTable) + sizeof (EFI_SYSTEM_RESOURCE_TABLE));
+ //
+ // Move to the location of new entry
+ //
+ Entry = Entry + mTable->FwResourceCount;
+ //
+ // Increment resource count
+ //
+ mTable->FwResourceCount++;
+
+ CopyGuid (&Entry->FwClass, &FmpImageInfoBuf->ImageTypeId);
+
+ if (IsSystemFmp (FmpImageInfoBuf)) {
+ DEBUG ((DEBUG_INFO, "EsrtFmpDxe: Found an ESRT entry for a System Device.\n"));
+ Entry->FwType = (UINT32)(ESRT_FW_TYPE_SYSTEMFIRMWARE);
+ } else {
+ Entry->FwType = (UINT32)(ESRT_FW_TYPE_DEVICEFIRMWARE);
+ }
+
+ Entry->FwVersion = FmpImageInfoBuf->Version;
+ Entry->LowestSupportedFwVersion = 0;
+ Entry->CapsuleFlags = 0;
+ Entry->LastAttemptVersion = 0;
+ Entry->LastAttemptStatus = 0;
+
+ //
+ // VERSION 2 has Lowest Supported
+ //
+ if (FmpVersion >= 2) {
+ Entry->LowestSupportedFwVersion = FmpImageInfoBuf->LowestSupportedImageVersion;
+ }
+
+ //
+ // VERSION 3 supports last attempt values
+ //
+ if (FmpVersion >= 3) {
+ Entry->LastAttemptVersion = FmpImageInfoBuf->LastAttemptVersion;
+ Entry->LastAttemptStatus = FmpImageInfoBuf->LastAttemptStatus;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Notify function for every Firmware Management Protocol being installed.
+ Get the descriptors from FMP Instance and create ESRT entries (ESRE)
+
+ @param[in] Event The Event that is being processed.
+ @param[in] Context The Event Context.
+
+**/
+VOID
+EFIAPI
+FmpInstallProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ UINTN BufferSize;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
+ UINTN DescriptorSize;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBufOrg;
+ UINT8 FmpImageInfoCount;
+ UINT32 FmpImageInfoDescriptorVer;
+ UINTN ImageInfoSize;
+ UINT32 PackageVersion;
+ CHAR16 *PackageVersionName;
+
+ Status = EFI_SUCCESS;
+ Handle = 0;
+ BufferSize = 0;
+ PackageVersionName = NULL;
+ FmpImageInfoBuf = NULL;
+ FmpImageInfoBufOrg = NULL;
+ Fmp = NULL;
+
+ DEBUG ((DEBUG_INFO, "FMP Installed Notify\n"));
+ while (TRUE) {
+ BufferSize = sizeof (EFI_HANDLE);
+ Status = gBS->LocateHandle (ByRegisterNotify, NULL, mFmpInstallEventRegistration, &BufferSize, &Handle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "EsrtFmpDxe: Failed to Locate handle from notify value. Status: %r\n", Status));
+ return;
+ }
+
+ Status = gBS->HandleProtocol (Handle, &gEfiFirmwareManagementProtocolGuid, (VOID **)&Fmp);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to get FMP for a handle 0x%x\n", Handle));
+ continue;
+ }
+ 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));
+ continue;
+ }
+
+ FmpImageInfoBuf = NULL;
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
+ 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));
+ goto CleanUp;
+ }
+
+ //
+ // Check each descriptor and read from the one specified
+ //
+ while (FmpImageInfoCount > 0) {
+ //
+ // If the descriptor has the IN USE bit set, create ESRT entry otherwise ignore.
+ //
+ if ((FmpImageInfoBuf->AttributesSetting & FmpImageInfoBuf->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE) == IMAGE_ATTRIBUTE_IN_USE) {
+ //
+ // Create ESRT entry
+ //
+ CreateEsrtEntry (FmpImageInfoBuf, FmpImageInfoDescriptorVer);
+ }
+ FmpImageInfoCount--;
+ //
+ // Increment the buffer pointer ahead by the size of the descriptor
+ //
+ FmpImageInfoBuf = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)(((UINT8 *)FmpImageInfoBuf) + DescriptorSize);
+ }
+
+ if (PackageVersionName != NULL) {
+ FreePool (PackageVersionName);
+ PackageVersionName = NULL;
+ }
+ if (FmpImageInfoBufOrg != NULL) {
+ FreePool (FmpImageInfoBufOrg);
+ FmpImageInfoBufOrg = NULL;
+ }
+ }
+
+CleanUp:
+ if (FmpImageInfoBufOrg != NULL) {
+ FreePool (FmpImageInfoBufOrg);
+ }
+ return;
+}
+
+/**
+ Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to
+ install the Efi System Resource Table.
+
+ @param[in] Event The Event that is being processed.
+ @param[in] Context The Event Context.
+
+**/
+VOID
+EFIAPI
+EsrtReadyToBootEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ InstallEfiSystemResourceTableInUefiConfigurationTable ();
+
+ //
+ // Print table on debug builds
+ //
+ DEBUG_CODE_BEGIN ();
+ PrintTable (mTable);
+ DEBUG_CODE_END ();
+}
+
+/**
+ The module Entry Point of the Efi System Resource Table DXE driver.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+EsrtFmpEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Allocate Memory for table
+ //
+ mTable = AllocateRuntimeZeroPool (
+ (GROWTH_STEP * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE)
+ );
+ ASSERT (mTable != NULL);
+ if (mTable == NULL) {
+ DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to allocate memory for ESRT.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mTable->FwResourceCount = 0;
+ mTable->FwResourceCountMax = GROWTH_STEP;
+ mTable->FwResourceVersion = EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION;
+
+ //
+ // Register notify function for all FMP installed
+ //
+ mFmpInstallEvent = EfiCreateProtocolNotifyEvent (
+ &gEfiFirmwareManagementProtocolGuid,
+ TPL_CALLBACK,
+ FmpInstallProtocolNotify,
+ NULL,
+ &mFmpInstallEventRegistration
+ );
+
+ ASSERT (mFmpInstallEvent != NULL);
+
+ if (mFmpInstallEvent == NULL) {
+ DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to Create Protocol Notify Event for FMP.\n"));
+ }
+
+ //
+ // Register notify function to install ESRT on ReadyToBoot Event.
+ //
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ EsrtReadyToBootEventNotify,
+ NULL,
+ &mEsrtReadyToBootEvent
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to register for ready to boot\n"));
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDebugPrint.c b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDebugPrint.c
new file mode 100644
index 0000000000..b4e5135e05
--- /dev/null
+++ b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDebugPrint.c
@@ -0,0 +1,161 @@
+/** @file
+ Publishes ESRT table from Firmware Management Protocol instances
+
+ Copyright (c) 2016, Microsoft Corporation
+ Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/SystemResourceTable.h>
+
+/**
+ Function to print a single ESRT Entry (ESRE) to the debug console
+
+ Print Format:
+ | 00000000-0000-0000-0000-000000000000 | SSSSSSSSSSSS | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 |
+
+ @param[in] Entry - Pointer to an ESRE entry
+ @retval EFI_SUCCESS
+ EFI_INVALID_PARAMETER
+**/
+EFI_STATUS
+EFIAPI
+PrintOutEsrtEntry (
+ IN EFI_SYSTEM_RESOURCE_ENTRY *Entry
+ )
+{
+ if (Entry == NULL) {
+ DEBUG ((DEBUG_INFO, "| ERROR: Invalid resource entry pointer "));
+ DEBUG ((DEBUG_INFO, " |\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // GUID FW Class (36 chars plus table formatting)
+ //
+ DEBUG ((DEBUG_INFO, "| %g |", &Entry->FwClass));
+
+ //
+ // Entry Type (12 chars plus table formatting)
+ //
+ switch (Entry->FwType) {
+ case (ESRT_FW_TYPE_SYSTEMFIRMWARE) :
+ DEBUG ((DEBUG_INFO, " System FW |"));
+ break;
+ case (ESRT_FW_TYPE_DEVICEFIRMWARE) :
+ DEBUG ((DEBUG_INFO, " Device FW |"));
+ break;
+ case (ESRT_FW_TYPE_UEFIDRIVER) :
+ DEBUG ((DEBUG_INFO, " Uefi Driver |"));
+ break;
+ case (ESRT_FW_TYPE_UNKNOWN) :
+ DEBUG ((DEBUG_INFO, " Unknown Type |"));
+ break;
+ default:
+ DEBUG ((DEBUG_INFO, " ? 0x%8X |", Entry->FwType));
+ break;
+ }
+
+ //
+ // FW Version (10 char UINT32 string plus table formatting)
+ // Lowest Supported Version (10 char UINT32 string plus table formatting)
+ // Capsule Flags (10 char UINT32 string plus table formatting)
+ // Last Attempt Version (10 char UINT32 string plus table formatting)
+ // Last Attempt Status (10 char UINT32 string plus table formatting)
+ //
+ DEBUG ((DEBUG_INFO,
+ " 0x%8X | 0x%8X | 0x%8X | 0x%8X | 0x%8X |\n",
+ Entry->FwVersion,
+ Entry->LowestSupportedFwVersion,
+ Entry->CapsuleFlags,
+ Entry->LastAttemptVersion,
+ Entry->LastAttemptStatus
+ ));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to print the ESRT table to the debug console
+
+ @param[in] Table - Pointer to the ESRT table
+**/
+VOID
+EFIAPI
+PrintTable (
+ IN EFI_SYSTEM_RESOURCE_TABLE *Table
+ )
+{
+ EFI_SYSTEM_RESOURCE_ENTRY *Entry;
+ UINTN Index;
+
+ Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)(((UINT8 *)Table) + sizeof (EFI_SYSTEM_RESOURCE_TABLE));
+
+ //
+ // Print ESRT table information
+ //
+ DEBUG ((DEBUG_INFO, "ESRT Table Information:\n"));
+ if (Table == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: Invalid table pointer\n"));
+ return;
+ }
+
+ DEBUG ((DEBUG_INFO, "+--------------------------------------------------------+\n"));
+ DEBUG ((DEBUG_INFO, "| Firmware Resource Count : 0x%08x |\n", Table->FwResourceCount));
+ DEBUG ((DEBUG_INFO, "| Firmware Resource Count Max : 0x%08x |\n", Table->FwResourceCountMax));
+ DEBUG ((DEBUG_INFO, "| Firmware Resource Entry Version : 0x%016x |\n", Table->FwResourceVersion));
+ DEBUG ((DEBUG_INFO, "+--------------------------------------------------------+\n"));
+
+ //
+ // Print table entry information
+ //
+ DEBUG ((DEBUG_INFO, "ESRT Table Entries:\n"));
+ if (Table->FwResourceVersion != EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION) {
+ DEBUG ((DEBUG_INFO, "ERROR: Unsupported Resource Entry Version\n"));
+ return;
+ }
+
+ DEBUG ((DEBUG_INFO, "+--------------------------------------+--------------+------------"));
+ DEBUG ((DEBUG_INFO, "+------------+------------+------------+------------+\n"));
+ DEBUG ((DEBUG_INFO, "| | | "));
+ DEBUG ((DEBUG_INFO, "| Lowest | | Last | Last |\n"));
+ DEBUG ((DEBUG_INFO, "| | Firmware | "));
+ DEBUG ((DEBUG_INFO, "| Supported | Capsule | Attempted | Attempted |\n"));
+ DEBUG ((DEBUG_INFO, "| CLASS GUID | Type | Version "));
+ DEBUG ((DEBUG_INFO, "| Version | Flags | Version | Status |\n"));
+ DEBUG ((DEBUG_INFO, "+--------------------------------------+--------------+------------"));
+ DEBUG ((DEBUG_INFO, "+------------+------------+------------+------------+\n"));
+
+ for (Index = 0; Index < Table->FwResourceCount; Index++) {
+ PrintOutEsrtEntry (&(Entry[Index]));
+ }
+
+ DEBUG ((DEBUG_INFO, "+--------------------------------------+--------------+------------"));
+ DEBUG ((DEBUG_INFO, "+------------+------------+------------+------------+\n"));
+}
+
diff --git a/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf
new file mode 100644
index 0000000000..6da5ce5b04
--- /dev/null
+++ b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf
@@ -0,0 +1,74 @@
+## @file
+# Publishes ESRT table from Firmware Management Protocol instances
+#
+# Copyright (c) 2016, Microsoft Corporation
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = EsrtFmpDxe
+ MODULE_UNI_FILE = EsrtFmpDxe.uni
+ FILE_GUID = FF626DA9-17EE-4949-A8B8-B10FA0044E9F
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = EsrtFmpEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ EsrtFmp.c
+ EsrtFmpDebugPrint.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ DebugLib
+ PcdLib
+
+[Protocols]
+ gEfiFirmwareManagementProtocolGuid ## CONSUMES
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGuid ## CONSUMES
+
+[Guids]
+ gEfiSystemResourceTableGuid ## PRODUCES
+
+[Depex]
+ TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ EsrtFmpDxeExtra.uni
diff --git a/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.uni b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.uni
new file mode 100644
index 0000000000..fdad5b5bd9
--- /dev/null
+++ b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.uni
@@ -0,0 +1,19 @@
+// /** @file
+// Publishes ESRT table from Firmware Management Protocol instances
+//
+// Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "Publishes ESRT table from Firmware Management Protocol instances"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This driver publishes the ESRT table from Firmware Management Protocol instances.<BR><BR>\n"
+ "The ESRT table is published when the Ready To Boot event is signaled.<BR>"
diff --git a/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxeExtra.uni b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxeExtra.uni
new file mode 100644
index 0000000000..2c6f6dab9c
--- /dev/null
+++ b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxeExtra.uni
@@ -0,0 +1,18 @@
+// /** @file
+// EsrtFmpDxe Localized Strings and Content
+//
+// Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"ESRT FMP DXE Driver"
--
2.14.2.windows.3
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Reviewed-by: Star Zeng <star.zeng@intel.com> Thanks, Star -----Original Message----- From: Kinney, Michael D Sent: Thursday, February 8, 2018 6:38 AM To: edk2-devel@lists.01.org Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Sean Brogan <sean.brogan@microsoft.com>; Yao, Jiewen <jiewen.yao@intel.com>; Zeng, Star <star.zeng@intel.com>; Dong, Eric <eric.dong@intel.com>; Ni, Ruiyu <ruiyu.ni@intel.com> Subject: [Patch V2 1/3] MdeModulePkg/EsrtFmpDxe: Add EsrtFmpDxe module From: Michael D Kinney <michael.d.kinney@intel.com> https://bugzilla.tianocore.org/show_bug.cgi?id=802 Based on content from the following branch/commits: https://github.com/Microsoft/MS_UEFI/tree/share/MsCapsuleSupport The EsrtFmpDxe module is a lightweight version of the EsrtDxe module that produces ESRT entries based only on FMP Protocol instances. Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Star Zeng <star.zeng@intel.com> Cc: Eric Dong <eric.dong@intel.com> Cc: Ruiyu Ni <ruiyu.ni@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> --- MdeModulePkg/MdeModulePkg.dsc | 1 + MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c | 482 +++++++++++++++++++++ .../Universal/EsrtFmpDxe/EsrtFmpDebugPrint.c | 161 +++++++ MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf | 74 ++++ MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.uni | 19 + .../Universal/EsrtFmpDxe/EsrtFmpDxeExtra.uni | 18 + 6 files changed, 755 insertions(+) create mode 100644 MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c create mode 100644 MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDebugPrint.c create mode 100644 MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf create mode 100644 MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.uni create mode 100644 MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxeExtra.uni diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 1c0085aee6..50002f8e3f 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -412,6 +412,7 @@ MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf + MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf MdeModulePkg/Universal/PropertiesTableAttributesDxe/PropertiesTableAttributesDxe.inf MdeModulePkg/Universal/FileExplorerDxe/FileExplorerDxe.inf { diff --git a/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c new file mode 100644 index 0000000000..b98430edbf --- /dev/null +++ b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmp.c @@ -0,0 +1,482 @@ +/** @file + Publishes ESRT table from Firmware Management Protocol instances + + Copyright (c) 2016, Microsoft Corporation Copyright (c) 2018, Intel + Corporation. All rights reserved.<BR> + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +**/ + +#include <Uefi.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> #include +<Library/UefiBootServicesTableLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <Library/UefiLib.h> +#include <Protocol/FirmwareManagement.h> #include <Guid/EventGroup.h> +#include <Guid/SystemResourceTable.h> + +// +// Print ESRT to debug console +// +VOID +EFIAPI +PrintTable ( + IN EFI_SYSTEM_RESOURCE_TABLE *Table + ); + +// +// Number of ESRT entries to grow by each time we run out of room // +#define GROWTH_STEP 10 + +// +// Module globals. +// +EFI_EVENT mEsrtReadyToBootEvent; +EFI_SYSTEM_RESOURCE_TABLE *mTable = NULL; +BOOLEAN mEsrtInstalled = FALSE; +EFI_EVENT mFmpInstallEvent; +VOID *mFmpInstallEventRegistration = NULL; + +/** + Install EFI System Resource Table into the UEFI Configuration Table + + @return Status code. + +**/ +EFI_STATUS +InstallEfiSystemResourceTableInUefiConfigurationTable ( + VOID + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + if (!mEsrtInstalled) { + if (mTable == NULL) { + DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Can't install ESRT table because it is NULL. \n")); + Status = EFI_OUT_OF_RESOURCES; + } else if (mTable->FwResourceCount == 0) { + DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Can't install ESRT table because it has zero Entries. \n")); + Status = EFI_UNSUPPORTED; + } else { + // + // Install the pointer into config table + // + Status = gBS->InstallConfigurationTable (&gEfiSystemResourceTableGuid, mTable); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Can't install ESRT table. Status: %r. \n", Status)); + } else { + DEBUG ((DEBUG_INFO, "EsrtFmpDxe: Installed ESRT table. \n")); + mEsrtInstalled = TRUE; + } + } + } + return Status; +} + +/** + Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo. + + @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR + + @return TRUE It is a system FMP. + @return FALSE It is a device FMP. +**/ +BOOLEAN +IsSystemFmp ( + IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo + ) +{ + GUID *Guid; + UINTN Count; + UINTN Index; + + Guid = PcdGetPtr (PcdSystemFmpCapsuleImageTypeIdGuid); + Count = PcdGetSize (PcdSystemFmpCapsuleImageTypeIdGuid) / + sizeof(GUID); + + for (Index = 0; Index < Count; Index++, Guid++) { + if (CompareGuid (&FmpImageInfo->ImageTypeId, Guid)) { + return TRUE; + } + } + + return FALSE; +} + +/** + 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. + + @return Status code. + +**/ +EFI_STATUS +EFIAPI +CreateEsrtEntry ( + IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf, + IN UINT32 FmpVersion + ) +{ + UINTN Index; + EFI_SYSTEM_RESOURCE_ENTRY *Entry; + UINTN NewSize; + EFI_SYSTEM_RESOURCE_TABLE *NewTable; + + Index = 0; + Entry = NULL; + + // + // Get our ESRT table. This should never be null at this point // + if (mTable == NULL) { + return EFI_DEVICE_ERROR; + } + + Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)(mTable + 1); // // Make sure + Guid isn't already in the list // for (Index = 0; Index < + mTable->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 + // + if (mTable->FwResourceCount >= mTable->FwResourceCountMax) { + // + // Can't grow table after installed. + // Only because didn't add support for this. + // Would need to re-install ESRT in system table if wanted to support + // + if (mEsrtInstalled) { + DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to install entry because ESRT table needed to grow after table already installed. \n")); + return EFI_OUT_OF_RESOURCES; + } + + NewSize = ((mTable->FwResourceCountMax + GROWTH_STEP) * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE); + NewTable = AllocateRuntimeZeroPool (NewSize); + if (NewTable == NULL) { + DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to allocate memory larger table for ESRT. \n")); + return EFI_OUT_OF_RESOURCES; + } + // + // Copy the whole old table into new table buffer + // + CopyMem ( + NewTable, + mTable, + ((mTable->FwResourceCountMax) * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE) + ); + // + // Update max + // + NewTable->FwResourceCountMax = NewTable->FwResourceCountMax + GROWTH_STEP; + // + // Free old table + // + FreePool (mTable); + // + // Reassign pointer to new table. + // + mTable = NewTable; + } + + // + // ESRT table has enough room for the new entry so add new entry // + Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)(((UINT8 *)mTable) + sizeof + (EFI_SYSTEM_RESOURCE_TABLE)); // // Move to the location of new + entry // Entry = Entry + mTable->FwResourceCount; // // Increment + resource count // mTable->FwResourceCount++; + + CopyGuid (&Entry->FwClass, &FmpImageInfoBuf->ImageTypeId); + + if (IsSystemFmp (FmpImageInfoBuf)) { + DEBUG ((DEBUG_INFO, "EsrtFmpDxe: Found an ESRT entry for a System Device.\n")); + Entry->FwType = (UINT32)(ESRT_FW_TYPE_SYSTEMFIRMWARE); + } else { + Entry->FwType = (UINT32)(ESRT_FW_TYPE_DEVICEFIRMWARE); + } + + Entry->FwVersion = FmpImageInfoBuf->Version; + Entry->LowestSupportedFwVersion = 0; Entry->CapsuleFlags = 0; + Entry->LastAttemptVersion = 0; Entry->LastAttemptStatus = 0; + + // + // VERSION 2 has Lowest Supported + // + if (FmpVersion >= 2) { + Entry->LowestSupportedFwVersion = + FmpImageInfoBuf->LowestSupportedImageVersion; + } + + // + // VERSION 3 supports last attempt values // if (FmpVersion >= 3) { + Entry->LastAttemptVersion = FmpImageInfoBuf->LastAttemptVersion; + Entry->LastAttemptStatus = FmpImageInfoBuf->LastAttemptStatus; + } + + return EFI_SUCCESS; +} + +/** + Notify function for every Firmware Management Protocol being installed. + Get the descriptors from FMP Instance and create ESRT entries (ESRE) + + @param[in] Event The Event that is being processed. + @param[in] Context The Event Context. + +**/ +VOID +EFIAPI +FmpInstallProtocolNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + UINTN BufferSize; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; + UINTN DescriptorSize; + EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf; + EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBufOrg; + UINT8 FmpImageInfoCount; + UINT32 FmpImageInfoDescriptorVer; + UINTN ImageInfoSize; + UINT32 PackageVersion; + CHAR16 *PackageVersionName; + + Status = EFI_SUCCESS; + Handle = 0; + BufferSize = 0; + PackageVersionName = NULL; + FmpImageInfoBuf = NULL; + FmpImageInfoBufOrg = NULL; + Fmp = NULL; + + DEBUG ((DEBUG_INFO, "FMP Installed Notify\n")); while (TRUE) { + BufferSize = sizeof (EFI_HANDLE); + Status = gBS->LocateHandle (ByRegisterNotify, NULL, mFmpInstallEventRegistration, &BufferSize, &Handle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "EsrtFmpDxe: Failed to Locate handle from notify value. Status: %r\n", Status)); + return; + } + + Status = gBS->HandleProtocol (Handle, &gEfiFirmwareManagementProtocolGuid, (VOID **)&Fmp); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to get FMP for a handle 0x%x\n", Handle)); + continue; + } + 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)); + continue; + } + + FmpImageInfoBuf = NULL; + FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize); + 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)); + goto CleanUp; + } + + // + // Check each descriptor and read from the one specified + // + while (FmpImageInfoCount > 0) { + // + // If the descriptor has the IN USE bit set, create ESRT entry otherwise ignore. + // + if ((FmpImageInfoBuf->AttributesSetting & FmpImageInfoBuf->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE) == IMAGE_ATTRIBUTE_IN_USE) { + // + // Create ESRT entry + // + CreateEsrtEntry (FmpImageInfoBuf, FmpImageInfoDescriptorVer); + } + FmpImageInfoCount--; + // + // Increment the buffer pointer ahead by the size of the descriptor + // + FmpImageInfoBuf = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)(((UINT8 *)FmpImageInfoBuf) + DescriptorSize); + } + + if (PackageVersionName != NULL) { + FreePool (PackageVersionName); + PackageVersionName = NULL; + } + if (FmpImageInfoBufOrg != NULL) { + FreePool (FmpImageInfoBufOrg); + FmpImageInfoBufOrg = NULL; + } + } + +CleanUp: + if (FmpImageInfoBufOrg != NULL) { + FreePool (FmpImageInfoBufOrg); + } + return; +} + +/** + Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This +is used to + install the Efi System Resource Table. + + @param[in] Event The Event that is being processed. + @param[in] Context The Event Context. + +**/ +VOID +EFIAPI +EsrtReadyToBootEventNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + InstallEfiSystemResourceTableInUefiConfigurationTable (); + + // + // Print table on debug builds + // + DEBUG_CODE_BEGIN (); + PrintTable (mTable); + DEBUG_CODE_END (); +} + +/** + The module Entry Point of the Efi System Resource Table DXE driver. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval Other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +EsrtFmpEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Allocate Memory for table + // + mTable = AllocateRuntimeZeroPool ( + (GROWTH_STEP * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE) + ); + ASSERT (mTable != NULL); + if (mTable == NULL) { + DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to allocate memory for ESRT.\n")); + return EFI_OUT_OF_RESOURCES; + } + + mTable->FwResourceCount = 0; + mTable->FwResourceCountMax = GROWTH_STEP; mTable->FwResourceVersion + = EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION; + + // + // Register notify function for all FMP installed // + mFmpInstallEvent = EfiCreateProtocolNotifyEvent ( + &gEfiFirmwareManagementProtocolGuid, + TPL_CALLBACK, + FmpInstallProtocolNotify, + NULL, + &mFmpInstallEventRegistration + ); + + ASSERT (mFmpInstallEvent != NULL); + + if (mFmpInstallEvent == NULL) { + DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to Create Protocol Notify + Event for FMP.\n")); } + + // + // Register notify function to install ESRT on ReadyToBoot Event. + // + Status = EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + EsrtReadyToBootEventNotify, + NULL, + &mEsrtReadyToBootEvent + ); + + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to register for ready to + boot\n")); } + + return Status; +} diff --git a/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDebugPrint.c b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDebugPrint.c new file mode 100644 index 0000000000..b4e5135e05 --- /dev/null +++ b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDebugPrint.c @@ -0,0 +1,161 @@ +/** @file + Publishes ESRT table from Firmware Management Protocol instances + + Copyright (c) 2016, Microsoft Corporation Copyright (c) 2018, Intel + Corporation. All rights reserved.<BR> + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +**/ + +#include <Uefi.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Protocol/FirmwareManagement.h> #include +<Guid/SystemResourceTable.h> + +/** + Function to print a single ESRT Entry (ESRE) to the debug console + + Print Format: + | 00000000-0000-0000-0000-000000000000 | SSSSSSSSSSSS | 0x00000000 | + 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | + + @param[in] Entry - Pointer to an ESRE entry + @retval EFI_SUCCESS + EFI_INVALID_PARAMETER **/ EFI_STATUS EFIAPI +PrintOutEsrtEntry ( + IN EFI_SYSTEM_RESOURCE_ENTRY *Entry + ) +{ + if (Entry == NULL) { + DEBUG ((DEBUG_INFO, "| ERROR: Invalid resource entry pointer ")); + DEBUG ((DEBUG_INFO, " |\n")); + return EFI_INVALID_PARAMETER; + } + + // + // GUID FW Class (36 chars plus table formatting) // DEBUG + ((DEBUG_INFO, "| %g |", &Entry->FwClass)); + + // + // Entry Type (12 chars plus table formatting) // switch + (Entry->FwType) { case (ESRT_FW_TYPE_SYSTEMFIRMWARE) : + DEBUG ((DEBUG_INFO, " System FW |")); + break; + case (ESRT_FW_TYPE_DEVICEFIRMWARE) : + DEBUG ((DEBUG_INFO, " Device FW |")); + break; + case (ESRT_FW_TYPE_UEFIDRIVER) : + DEBUG ((DEBUG_INFO, " Uefi Driver |")); + break; + case (ESRT_FW_TYPE_UNKNOWN) : + DEBUG ((DEBUG_INFO, " Unknown Type |")); + break; + default: + DEBUG ((DEBUG_INFO, " ? 0x%8X |", Entry->FwType)); + break; + } + + // + // FW Version (10 char UINT32 string plus table formatting) // + Lowest Supported Version (10 char UINT32 string plus table formatting) + // Capsule Flags (10 char UINT32 string plus table formatting) // + Last Attempt Version (10 char UINT32 string plus table formatting) // + Last Attempt Status (10 char UINT32 string plus table formatting) // + DEBUG ((DEBUG_INFO, + " 0x%8X | 0x%8X | 0x%8X | 0x%8X | 0x%8X |\n", + Entry->FwVersion, + Entry->LowestSupportedFwVersion, + Entry->CapsuleFlags, + Entry->LastAttemptVersion, + Entry->LastAttemptStatus + )); + + return EFI_SUCCESS; +} + +/** + Function to print the ESRT table to the debug console + + @param[in] Table - Pointer to the ESRT table **/ VOID EFIAPI +PrintTable ( + IN EFI_SYSTEM_RESOURCE_TABLE *Table + ) +{ + EFI_SYSTEM_RESOURCE_ENTRY *Entry; + UINTN Index; + + Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)(((UINT8 *)Table) + sizeof + (EFI_SYSTEM_RESOURCE_TABLE)); + + // + // Print ESRT table information + // + DEBUG ((DEBUG_INFO, "ESRT Table Information:\n")); if (Table == + NULL) { + DEBUG ((DEBUG_INFO, "ERROR: Invalid table pointer\n")); + return; + } + + DEBUG ((DEBUG_INFO, "+--------------------------------------------------------+\n")); + DEBUG ((DEBUG_INFO, "| Firmware Resource Count : 0x%08x |\n", Table->FwResourceCount)); + DEBUG ((DEBUG_INFO, "| Firmware Resource Count Max : 0x%08x |\n", Table->FwResourceCountMax)); + DEBUG ((DEBUG_INFO, "| Firmware Resource Entry Version : 0x%016x |\n", Table->FwResourceVersion)); + DEBUG ((DEBUG_INFO, + "+--------------------------------------------------------+\n")); + + // + // Print table entry information + // + DEBUG ((DEBUG_INFO, "ESRT Table Entries:\n")); if + (Table->FwResourceVersion != EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION) { + DEBUG ((DEBUG_INFO, "ERROR: Unsupported Resource Entry Version\n")); + return; + } + + DEBUG ((DEBUG_INFO, + "+--------------------------------------+--------------+------------") + ); DEBUG ((DEBUG_INFO, + "+------------+------------+------------+------------+\n")); + DEBUG ((DEBUG_INFO, "| | | ")); + DEBUG ((DEBUG_INFO, "| Lowest | | Last | Last |\n")); + DEBUG ((DEBUG_INFO, "| | Firmware | ")); + DEBUG ((DEBUG_INFO, "| Supported | Capsule | Attempted | Attempted |\n")); + DEBUG ((DEBUG_INFO, "| CLASS GUID | Type | Version ")); + DEBUG ((DEBUG_INFO, "| Version | Flags | Version | Status |\n")); + DEBUG ((DEBUG_INFO, + "+--------------------------------------+--------------+------------") + ); DEBUG ((DEBUG_INFO, + "+------------+------------+------------+------------+\n")); + + for (Index = 0; Index < Table->FwResourceCount; Index++) { + PrintOutEsrtEntry (&(Entry[Index])); } + + DEBUG ((DEBUG_INFO, +"+--------------------------------------+--------------+------------")) +; + DEBUG ((DEBUG_INFO, +"+------------+------------+------------+------------+\n")); +} + diff --git a/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf new file mode 100644 index 0000000000..6da5ce5b04 --- /dev/null +++ b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf @@ -0,0 +1,74 @@ +## @file +# Publishes ESRT table from Firmware Management Protocol instances # # +Copyright (c) 2016, Microsoft Corporation # Copyright (c) 2018, Intel +Corporation. All rights reserved.<BR> # # All rights reserved. +# Redistribution and use in source and binary forms, with or without # +modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +notice, # this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +notice, # this list of conditions and the following disclaimer in the +documentation # and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = EsrtFmpDxe + MODULE_UNI_FILE = EsrtFmpDxe.uni + FILE_GUID = FF626DA9-17EE-4949-A8B8-B10FA0044E9F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = EsrtFmpEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + EsrtFmp.c + EsrtFmpDebugPrint.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + DebugLib + PcdLib + +[Protocols] + gEfiFirmwareManagementProtocolGuid ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGuid ## +CONSUMES + +[Guids] + gEfiSystemResourceTableGuid ## PRODUCES + +[Depex] + TRUE + +[UserExtensions.TianoCore."ExtraFiles"] + EsrtFmpDxeExtra.uni diff --git a/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.uni b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.uni new file mode 100644 index 0000000000..fdad5b5bd9 --- /dev/null +++ b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.uni @@ -0,0 +1,19 @@ +// /** @file +// Publishes ESRT table from Firmware Management Protocol instances // +// Copyright (c) 2018, Intel Corporation. All rights reserved.<BR> // +// This program and the accompanying materials // are licensed and made +available under the terms and conditions of the BSD License // which +accompanies this distribution. The full text of the license may be +found at // http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" +BASIS, // WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "Publishes ESRT table from Firmware Management Protocol instances" + +#string STR_MODULE_DESCRIPTION #language en-US "This driver publishes the ESRT table from Firmware Management Protocol instances.<BR><BR>\n" + "The ESRT table is published when the Ready To Boot event is signaled.<BR>" diff --git a/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxeExtra.uni b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxeExtra.uni new file mode 100644 index 0000000000..2c6f6dab9c --- /dev/null +++ b/MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxeExtra.uni @@ -0,0 +1,18 @@ +// /** @file +// EsrtFmpDxe Localized Strings and Content // // Copyright (c) 2018, +Intel Corporation. All rights reserved.<BR> // // This program and the +accompanying materials // are licensed and made available under the +terms and conditions of the BSD License // which accompanies this +distribution. The full text of the license may be found at // +http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" +BASIS, // WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"ESRT FMP DXE Driver" -- 2.14.2.windows.3 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.