mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 11:13:53 +01:00 
			
		
		
		
	Skip error check if HardwareInstance is 0 as this either means that FmpVersion < 3 and not supported or, "A zero means the FMP provider is not able to determine a unique hardware instance number or a hardware instance number is not needed." per UEFI specification. As the FmpInstances are merged and HardwareInstance is not used remove error check in this case. Signed-off-by: Jeff Brasen <jbrasen@nvidia.com> Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
		
			
				
	
	
		
			567 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			567 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Publishes ESRT table from Firmware Management Protocol instances
 | |
| 
 | |
|   Copyright (c) 2016, Microsoft Corporation
 | |
|   Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
|   All rights reserved.
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #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>
 | |
| 
 | |
| ///
 | |
| /// 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.
 | |
| 
 | |
|  @param[in]  Table   Pointer to the ESRT table.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| PrintTable (
 | |
|   IN EFI_SYSTEM_RESOURCE_TABLE  *Table
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Install EFI System Resource Table into the UEFI Configuration Table
 | |
| 
 | |
|   @param[in] Table                  Pointer to the ESRT.
 | |
| 
 | |
|   @return  Status code.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| InstallEfiSystemResourceTableInUefiConfigurationTable (
 | |
|   IN EFI_SYSTEM_RESOURCE_TABLE  *Table
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
|   if (Table->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, Table);
 | |
|     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"));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   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 with
 | |
|   a given FMP descriptor.  If the GUID is already in the ESRT, then the ESRT
 | |
|   entry is updated.
 | |
| 
 | |
|   @param[in,out] Table                Pointer to the ESRT Table.
 | |
|   @param[in,out] HardwareInstances    Pointer to the GUID_HARDWAREINSTANCE_PAIR.
 | |
|   @param[in,out] NumberOfDescriptors  The number of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
 | |
|   @param[in]     FmpImageInfoBuf      Pointer to the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | |
|   @param[in]     FmpVersion           FMP Version.
 | |
| 
 | |
|   @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
 | |
| CreateEsrtEntry (
 | |
|   IN OUT EFI_SYSTEM_RESOURCE_TABLE      *Table,
 | |
|   IN OUT GUID_HARDWAREINSTANCE_PAIR     *HardwareInstances,
 | |
|   IN OUT UINT32                         *NumberOfDescriptors,
 | |
|   IN     EFI_FIRMWARE_IMAGE_DESCRIPTOR  *FmpImageInfoBuf,
 | |
|   IN     UINT32                         FmpVersion
 | |
|   )
 | |
| {
 | |
|   UINTN                      Index;
 | |
|   EFI_SYSTEM_RESOURCE_ENTRY  *Entry;
 | |
|   UINT64                     FmpHardwareInstance;
 | |
| 
 | |
|   FmpHardwareInstance = 0;
 | |
|   if (FmpVersion >= 3) {
 | |
|     FmpHardwareInstance = FmpImageInfoBuf->HardwareInstance;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check to see of FmpImageInfoBuf GUID/HardwareInstance is unique
 | |
|   // Skip if HardwareInstance is 0 as this is the case if FmpVersion < 3
 | |
|   // or the device can not create a unique ID per UEFI specification
 | |
|   //
 | |
|   if (FmpHardwareInstance != 0) {
 | |
|     for (Index = 0; Index < *NumberOfDescriptors; Index++) {
 | |
|       if (CompareGuid (&HardwareInstances[Index].ImageTypeGuid, &FmpImageInfoBuf->ImageTypeId)) {
 | |
|         if (HardwareInstances[Index].HardwareInstance == FmpHardwareInstance) {
 | |
|           DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Duplicate firmware image descriptor with GUID %g HardwareInstance:0x%x\n", &FmpImageInfoBuf->ImageTypeId, FmpHardwareInstance));
 | |
|           ASSERT (
 | |
|             !CompareGuid (&HardwareInstances[Index].ImageTypeGuid, &FmpImageInfoBuf->ImageTypeId) ||
 | |
|             HardwareInstances[Index].HardwareInstance != FmpHardwareInstance
 | |
|             );
 | |
|           return EFI_UNSUPPORTED;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Record new GUID/HardwareInstance pair
 | |
|   //
 | |
|   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));
 | |
| 
 | |
|   //
 | |
|   // Check to see if GUID is already in the ESRT table
 | |
|   //
 | |
|   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));
 | |
| 
 | |
|     //
 | |
|     // 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) {
 | |
|       //
 | |
|       // 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);
 | |
| 
 | |
|   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;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Increment the number of active ESRT Table Entries
 | |
|   //
 | |
|   Table->FwResourceCount++;
 | |
| 
 | |
|   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.
 | |
|   Create ESRT table, get the descriptors from FMP Instance and
 | |
|   create ESRT entries (ESRE).
 | |
| 
 | |
|   @return Pointer to the ESRT created.
 | |
| 
 | |
| **/
 | |
| EFI_SYSTEM_RESOURCE_TABLE *
 | |
| CreateFmpBasedEsrt (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                     Status;
 | |
|   UINTN                          NoProtocols;
 | |
|   VOID                           **Buffer;
 | |
|   UINTN                          Index;
 | |
|   UINT32                         FmpImageInfoDescriptorVer;
 | |
|   UINT8                          FmpImageInfoCount;
 | |
|   UINTN                          DescriptorSize;
 | |
|   UINT32                         NumberOfDescriptors;
 | |
|   EFI_FIRMWARE_IMAGE_DESCRIPTOR  *FmpImageInfoBuf;
 | |
|   EFI_FIRMWARE_IMAGE_DESCRIPTOR  *OrgFmpImageInfoBuf;
 | |
|   EFI_SYSTEM_RESOURCE_TABLE      *Table;
 | |
|   GUID_HARDWAREINSTANCE_PAIR     *HardwareInstances;
 | |
| 
 | |
|   Status             = EFI_SUCCESS;
 | |
|   NoProtocols        = 0;
 | |
|   Buffer             = NULL;
 | |
|   FmpImageInfoBuf    = NULL;
 | |
|   OrgFmpImageInfoBuf = NULL;
 | |
|   Table              = NULL;
 | |
|   HardwareInstances  = NULL;
 | |
| 
 | |
|   Status = EfiLocateProtocolBuffer (
 | |
|              &gEfiFirmwareManagementProtocolGuid,
 | |
|              &NoProtocols,
 | |
|              &Buffer
 | |
|              );
 | |
|   if (EFI_ERROR (Status) || (Buffer == NULL)) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // 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 (
 | |
|             (NumberOfDescriptors * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE)
 | |
|             );
 | |
|   if (Table == NULL) {
 | |
|     DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to allocate memory for ESRT.\n"));
 | |
|     FreePool (Buffer);
 | |
|     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->FwResourceCountMax = NumberOfDescriptors;
 | |
|   Table->FwResourceVersion  = EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION;
 | |
| 
 | |
|   NumberOfDescriptors = 0;
 | |
|   for (Index = 0; Index < NoProtocols; Index++) {
 | |
|     FmpImageInfoBuf = FmpGetFirmwareImageDescriptor (
 | |
|                         (EFI_FIRMWARE_MANAGEMENT_PROTOCOL *)Buffer[Index],
 | |
|                         &FmpImageInfoDescriptorVer,
 | |
|                         &FmpImageInfoCount,
 | |
|                         &DescriptorSize
 | |
|                         );
 | |
|     if (FmpImageInfoBuf == NULL) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Check each descriptor and read from the one specified
 | |
|     //
 | |
|     OrgFmpImageInfoBuf = FmpImageInfoBuf;
 | |
|     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 (Table, HardwareInstances, &NumberOfDescriptors, FmpImageInfoBuf, FmpImageInfoDescriptorVer);
 | |
|       }
 | |
| 
 | |
|       FmpImageInfoCount--;
 | |
|       //
 | |
|       // Increment the buffer pointer ahead by the size of the descriptor
 | |
|       //
 | |
|       FmpImageInfoBuf = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)(((UINT8 *)FmpImageInfoBuf) + DescriptorSize);
 | |
|     }
 | |
| 
 | |
|     FreePool (OrgFmpImageInfoBuf);
 | |
|     OrgFmpImageInfoBuf = NULL;
 | |
|   }
 | |
| 
 | |
|   FreePool (Buffer);
 | |
|   FreePool (HardwareInstances);
 | |
|   return Table;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                 Status;
 | |
|   EFI_SYSTEM_RESOURCE_TABLE  *Table;
 | |
| 
 | |
|   Table = CreateFmpBasedEsrt ();
 | |
|   if (Table != NULL) {
 | |
|     //
 | |
|     // Print table on debug builds
 | |
|     //
 | |
|     DEBUG_CODE_BEGIN ();
 | |
|     PrintTable (Table);
 | |
|     DEBUG_CODE_END ();
 | |
| 
 | |
|     Status = InstallEfiSystemResourceTableInUefiConfigurationTable (Table);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       FreePool (Table);
 | |
|     }
 | |
|   } else {
 | |
|     DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Can't install ESRT table because it is NULL. \n"));
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Close the event to prevent it be signalled again.
 | |
|   //
 | |
|   gBS->CloseEvent (Event);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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;
 | |
|   EFI_EVENT   EsrtReadyToBootEvent;
 | |
| 
 | |
|   //
 | |
|   // Register notify function to install ESRT on ReadyToBoot Event.
 | |
|   //
 | |
|   Status = EfiCreateEventReadyToBootEx (
 | |
|              TPL_CALLBACK,
 | |
|              EsrtReadyToBootEventNotify,
 | |
|              NULL,
 | |
|              &EsrtReadyToBootEvent
 | |
|              );
 | |
| 
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to register for ready to boot\n"));
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 |