mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-11-04 02:40:26 +00: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;
 | 
						|
}
 |