REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			1695 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1695 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  DXE capsule library.
 | 
						|
 | 
						|
  Caution: This module requires additional review when modified.
 | 
						|
  This module will have external input - capsule image.
 | 
						|
  This external input must be validated carefully to avoid security issue like
 | 
						|
  buffer overflow, integer overflow.
 | 
						|
 | 
						|
  SupportCapsuleImage(), ProcessCapsuleImage(), IsValidCapsuleHeader(),
 | 
						|
  ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted input and
 | 
						|
  performs basic validation.
 | 
						|
 | 
						|
  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <PiDxe.h>
 | 
						|
 | 
						|
#include <IndustryStandard/WindowsUxCapsule.h>
 | 
						|
 | 
						|
#include <Guid/FmpCapsule.h>
 | 
						|
#include <Guid/SystemResourceTable.h>
 | 
						|
#include <Guid/EventGroup.h>
 | 
						|
 | 
						|
#include <Library/BaseLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/DxeServicesTableLib.h>
 | 
						|
#include <Library/UefiBootServicesTableLib.h>
 | 
						|
#include <Library/UefiRuntimeServicesTableLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Library/CapsuleLib.h>
 | 
						|
#include <Library/DevicePathLib.h>
 | 
						|
#include <Library/UefiLib.h>
 | 
						|
#include <Library/BmpSupportLib.h>
 | 
						|
 | 
						|
#include <Protocol/GraphicsOutput.h>
 | 
						|
#include <Protocol/EsrtManagement.h>
 | 
						|
#include <Protocol/FirmwareManagement.h>
 | 
						|
#include <Protocol/FirmwareManagementProgress.h>
 | 
						|
#include <Protocol/DevicePath.h>
 | 
						|
 | 
						|
EFI_SYSTEM_RESOURCE_TABLE  *mEsrtTable             = NULL;
 | 
						|
BOOLEAN                    mIsVirtualAddrConverted = FALSE;
 | 
						|
 | 
						|
BOOLEAN    mDxeCapsuleLibEndOfDxe      = FALSE;
 | 
						|
EFI_EVENT  mDxeCapsuleLibEndOfDxeEvent = NULL;
 | 
						|
 | 
						|
EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL  *mFmpProgress = NULL;
 | 
						|
 | 
						|
/**
 | 
						|
  Initialize capsule related variables.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
InitCapsuleVariable (
 | 
						|
  VOID
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Record capsule status variable.
 | 
						|
 | 
						|
  @param[in] CapsuleHeader  The capsule image header
 | 
						|
  @param[in] CapsuleStatus  The capsule process stauts
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          The capsule status variable is recorded.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
RecordCapsuleStatusVariable (
 | 
						|
  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
 | 
						|
  IN EFI_STATUS          CapsuleStatus
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Record FMP capsule status variable.
 | 
						|
 | 
						|
  @param[in] CapsuleHeader  The capsule image header
 | 
						|
  @param[in] CapsuleStatus  The capsule process stauts
 | 
						|
  @param[in] PayloadIndex   FMP payload index
 | 
						|
  @param[in] ImageHeader    FMP image header
 | 
						|
  @param[in] FmpDevicePath  DevicePath associated with the FMP producer
 | 
						|
  @param[in] CapFileName    Capsule file name
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          The capsule status variable is recorded.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
RecordFmpCapsuleStatusVariable (
 | 
						|
  IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
 | 
						|
  IN EFI_STATUS                                    CapsuleStatus,
 | 
						|
  IN UINTN                                         PayloadIndex,
 | 
						|
  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath  OPTIONAL,
 | 
						|
  IN CHAR16                                        *CapFileName    OPTIONAL
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Function indicate the current completion progress of the firmware
 | 
						|
  update. Platform may override with own specific progress function.
 | 
						|
 | 
						|
  @param[in]  Completion  A value between 1 and 100 indicating the current
 | 
						|
                          completion progress of the firmware update
 | 
						|
 | 
						|
  @retval EFI_SUCESS             The capsule update progress was updated.
 | 
						|
  @retval EFI_INVALID_PARAMETER  Completion is greater than 100%.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UpdateImageProgress (
 | 
						|
  IN UINTN  Completion
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Return if this capsule is a capsule name capsule, based upon CapsuleHeader.
 | 
						|
 | 
						|
  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
 | 
						|
 | 
						|
  @retval TRUE  It is a capsule name capsule.
 | 
						|
  @retval FALSE It is not a capsule name capsule.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsCapsuleNameCapsule (
 | 
						|
  IN EFI_CAPSULE_HEADER  *CapsuleHeader
 | 
						|
  )
 | 
						|
{
 | 
						|
  return CompareGuid (&CapsuleHeader->CapsuleGuid, &gEdkiiCapsuleOnDiskNameGuid);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return if this CapsuleGuid is a FMP capsule GUID or not.
 | 
						|
 | 
						|
  @param[in] CapsuleGuid A pointer to EFI_GUID
 | 
						|
 | 
						|
  @retval TRUE  It is a FMP capsule GUID.
 | 
						|
  @retval FALSE It is not a FMP capsule GUID.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsFmpCapsuleGuid (
 | 
						|
  IN EFI_GUID  *CapsuleGuid
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (CompareGuid (&gEfiFmpCapsuleGuid, CapsuleGuid)) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Validate if it is valid capsule header
 | 
						|
 | 
						|
  Caution: This function may receive untrusted input.
 | 
						|
 | 
						|
  This function assumes the caller provided correct CapsuleHeader pointer
 | 
						|
  and CapsuleSize.
 | 
						|
 | 
						|
  This function validates the fields in EFI_CAPSULE_HEADER.
 | 
						|
 | 
						|
  @param[in]  CapsuleHeader    Points to a capsule header.
 | 
						|
  @param[in]  CapsuleSize      Size of the whole capsule image.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsValidCapsuleHeader (
 | 
						|
  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
 | 
						|
  IN UINT64              CapsuleSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Validate Fmp capsules layout.
 | 
						|
 | 
						|
  Caution: This function may receive untrusted input.
 | 
						|
 | 
						|
  This function assumes the caller validated the capsule by using
 | 
						|
  IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
 | 
						|
  The capsule buffer size is CapsuleHeader->CapsuleImageSize.
 | 
						|
 | 
						|
  This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
 | 
						|
  and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
 | 
						|
 | 
						|
  This function need support nested FMP capsule.
 | 
						|
 | 
						|
  @param[in]   CapsuleHeader        Points to a capsule header.
 | 
						|
  @param[out]  EmbeddedDriverCount  The EmbeddedDriverCount in the FMP capsule.
 | 
						|
 | 
						|
  @retval EFI_SUCESS             Input capsule is a correct FMP capsule.
 | 
						|
  @retval EFI_INVALID_PARAMETER  Input capsule is not a correct FMP capsule.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ValidateFmpCapsule (
 | 
						|
  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
 | 
						|
  OUT UINT16             *EmbeddedDriverCount OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
 | 
						|
  UINT8                                         *EndOfCapsule;
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader;
 | 
						|
  UINT8                                         *EndOfPayload;
 | 
						|
  UINT64                                        *ItemOffsetList;
 | 
						|
  UINT32                                        ItemNum;
 | 
						|
  UINTN                                         Index;
 | 
						|
  UINTN                                         FmpCapsuleSize;
 | 
						|
  UINTN                                         FmpCapsuleHeaderSize;
 | 
						|
  UINT64                                        FmpImageSize;
 | 
						|
  UINTN                                         FmpImageHeaderSize;
 | 
						|
 | 
						|
  if (!IsFmpCapsuleGuid (&CapsuleHeader->CapsuleGuid)) {
 | 
						|
    return ValidateFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), EmbeddedDriverCount);
 | 
						|
  }
 | 
						|
 | 
						|
  if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
 | 
						|
  EndOfCapsule     = (UINT8 *)CapsuleHeader + CapsuleHeader->CapsuleImageSize;
 | 
						|
  FmpCapsuleSize   = (UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader;
 | 
						|
 | 
						|
  if (FmpCapsuleSize < sizeof (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize));
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
 | 
						|
  if (FmpCapsuleHeader->Version != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader->Version));
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
 | 
						|
 | 
						|
  // No overflow
 | 
						|
  ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
 | 
						|
 | 
						|
  if ((FmpCapsuleSize - sizeof (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER))/sizeof (UINT64) < ItemNum) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "ItemNum(0x%x) too big\n", ItemNum));
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  FmpCapsuleHeaderSize = sizeof (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER) + sizeof (UINT64)*ItemNum;
 | 
						|
 | 
						|
  // Check ItemOffsetList
 | 
						|
  for (Index = 0; Index < ItemNum; Index++) {
 | 
						|
    if (ItemOffsetList[Index] >= FmpCapsuleSize) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleSize));
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ItemOffsetList[Index] < FmpCapsuleHeaderSize) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleHeaderSize));
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // All the address in ItemOffsetList must be stored in ascending order
 | 
						|
    //
 | 
						|
    if (Index > 0) {
 | 
						|
      if (ItemOffsetList[Index] <= ItemOffsetList[Index - 1]) {
 | 
						|
        DEBUG ((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index, ItemOffsetList[Index], Index - 1, ItemOffsetList[Index - 1]));
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
 | 
						|
  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
 | 
						|
    ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
 | 
						|
    if (Index == ItemNum - 1) {
 | 
						|
      EndOfPayload = (UINT8 *)((UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader);
 | 
						|
    } else {
 | 
						|
      EndOfPayload = (UINT8 *)(UINTN)ItemOffsetList[Index+1];
 | 
						|
    }
 | 
						|
 | 
						|
    FmpImageSize = (UINTN)EndOfPayload - ItemOffsetList[Index];
 | 
						|
 | 
						|
    FmpImageHeaderSize = sizeof (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER);
 | 
						|
    if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) ||
 | 
						|
        (ImageHeader->Version < 1))
 | 
						|
    {
 | 
						|
      DEBUG ((DEBUG_ERROR, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader->Version));
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ImageHeader->Version == 1) {
 | 
						|
      FmpImageHeaderSize = OFFSET_OF (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
 | 
						|
    } else if (ImageHeader->Version == 2) {
 | 
						|
      FmpImageHeaderSize = OFFSET_OF (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, ImageCapsuleSupport);
 | 
						|
    }
 | 
						|
 | 
						|
    if (FmpImageSize < FmpImageHeaderSize) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "FmpImageSize(0x%lx) < FmpImageHeaderSize(0x%x)\n", FmpImageSize, FmpImageHeaderSize));
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    // No overflow
 | 
						|
    if (FmpImageSize != (UINT64)FmpImageHeaderSize + (UINT64)ImageHeader->UpdateImageSize + (UINT64)ImageHeader->UpdateVendorCodeSize) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize, ImageHeader->UpdateImageSize, ImageHeader->UpdateVendorCodeSize));
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (ItemNum == 0) {
 | 
						|
    //
 | 
						|
    // No driver & payload element in FMP
 | 
						|
    //
 | 
						|
    EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1);
 | 
						|
    if (EndOfPayload != EndOfCapsule) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload, EndOfCapsule));
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EmbeddedDriverCount != NULL) {
 | 
						|
    *EmbeddedDriverCount = FmpCapsuleHeader->EmbeddedDriverCount;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Those capsules supported by the firmwares.
 | 
						|
 | 
						|
  Caution: This function may receive untrusted input.
 | 
						|
 | 
						|
  @param[in]  CapsuleHeader    Points to a capsule header.
 | 
						|
 | 
						|
  @retval EFI_SUCESS       Input capsule is supported by firmware.
 | 
						|
  @retval EFI_UNSUPPORTED  Input capsule is not supported by the firmware.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DisplayCapsuleImage (
 | 
						|
  IN EFI_CAPSULE_HEADER  *CapsuleHeader
 | 
						|
  )
 | 
						|
{
 | 
						|
  DISPLAY_DISPLAY_PAYLOAD        *ImagePayload;
 | 
						|
  UINTN                          PayloadSize;
 | 
						|
  EFI_STATUS                     Status;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *Blt;
 | 
						|
  UINTN                          BltSize;
 | 
						|
  UINTN                          Height;
 | 
						|
  UINTN                          Width;
 | 
						|
  EFI_GRAPHICS_OUTPUT_PROTOCOL   *GraphicsOutput;
 | 
						|
 | 
						|
  //
 | 
						|
  // UX capsule doesn't have extended header entries.
 | 
						|
  //
 | 
						|
  if (CapsuleHeader->HeaderSize != sizeof (EFI_CAPSULE_HEADER)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  ImagePayload = (DISPLAY_DISPLAY_PAYLOAD *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize);
 | 
						|
  //
 | 
						|
  // (CapsuleImageSize > HeaderSize) is guaranteed by IsValidCapsuleHeader().
 | 
						|
  //
 | 
						|
  PayloadSize = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Make sure the image payload at least contain the DISPLAY_DISPLAY_PAYLOAD header.
 | 
						|
  // Further size check is performed by the logic translating BMP to GOP BLT.
 | 
						|
  //
 | 
						|
  if (PayloadSize <= sizeof (DISPLAY_DISPLAY_PAYLOAD)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ImagePayload->Version != 1) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (CalculateCheckSum8 ((UINT8 *)CapsuleHeader, CapsuleHeader->CapsuleImageSize) != 0) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Only Support Bitmap by now
 | 
						|
  //
 | 
						|
  if (ImagePayload->ImageType != 0) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Try to open GOP
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = gBS->LocateProtocol (&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&GraphicsOutput);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (GraphicsOutput->Mode->Mode != ImagePayload->Mode) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  Blt    = NULL;
 | 
						|
  Width  = 0;
 | 
						|
  Height = 0;
 | 
						|
  Status = TranslateBmpToGopBlt (
 | 
						|
             ImagePayload + 1,
 | 
						|
             PayloadSize - sizeof (DISPLAY_DISPLAY_PAYLOAD),
 | 
						|
             &Blt,
 | 
						|
             &BltSize,
 | 
						|
             &Height,
 | 
						|
             &Width
 | 
						|
             );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = GraphicsOutput->Blt (
 | 
						|
                             GraphicsOutput,
 | 
						|
                             Blt,
 | 
						|
                             EfiBltBufferToVideo,
 | 
						|
                             0,
 | 
						|
                             0,
 | 
						|
                             (UINTN)ImagePayload->OffsetX,
 | 
						|
                             (UINTN)ImagePayload->OffsetY,
 | 
						|
                             Width,
 | 
						|
                             Height,
 | 
						|
                             Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
 | 
						|
                             );
 | 
						|
 | 
						|
  FreePool (Blt);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Dump FMP information.
 | 
						|
 | 
						|
  @param[in] ImageInfoSize       The size of ImageInfo, in bytes.
 | 
						|
  @param[in] ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | 
						|
  @param[in] DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | 
						|
  @param[in] DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | 
						|
  @param[in] DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
 | 
						|
  @param[in] PackageVersion      The version of package.
 | 
						|
  @param[in] PackageVersionName  The version name of package.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
DumpFmpImageInfo (
 | 
						|
  IN UINTN                          ImageInfoSize,
 | 
						|
  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR  *ImageInfo,
 | 
						|
  IN UINT32                         DescriptorVersion,
 | 
						|
  IN UINT8                          DescriptorCount,
 | 
						|
  IN UINTN                          DescriptorSize,
 | 
						|
  IN UINT32                         PackageVersion,
 | 
						|
  IN CHAR16                         *PackageVersionName
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FIRMWARE_IMAGE_DESCRIPTOR  *CurrentImageInfo;
 | 
						|
  UINTN                          Index;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "  DescriptorVersion  - 0x%x\n", DescriptorVersion));
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "  DescriptorCount    - 0x%x\n", DescriptorCount));
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "  DescriptorSize     - 0x%x\n", DescriptorSize));
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "  PackageVersion     - 0x%x\n", PackageVersion));
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "  PackageVersionName - %s\n\n", PackageVersionName));
 | 
						|
  CurrentImageInfo = ImageInfo;
 | 
						|
  for (Index = 0; Index < DescriptorCount; Index++) {
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "  ImageDescriptor (%d)\n", Index));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    ImageIdName                 - %s\n", CurrentImageInfo->ImageIdName));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    Version                     - 0x%x\n", CurrentImageInfo->Version));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    VersionName                 - %s\n", CurrentImageInfo->VersionName));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    Size                        - 0x%x\n", CurrentImageInfo->Size));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    AttributesSupported         - 0x%lx\n", CurrentImageInfo->AttributesSupported));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    AttributesSetting           - 0x%lx\n", CurrentImageInfo->AttributesSetting));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    Compatibilities             - 0x%lx\n", CurrentImageInfo->Compatibilities));
 | 
						|
    if (DescriptorVersion > 1) {
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion));
 | 
						|
      if (DescriptorVersion > 2) {
 | 
						|
        DEBUG ((DEBUG_VERBOSE, "    LastAttemptVersion          - 0x%x\n", CurrentImageInfo->LastAttemptVersion));
 | 
						|
        DEBUG ((DEBUG_VERBOSE, "    LastAttemptStatus           - 0x%x\n", CurrentImageInfo->LastAttemptStatus));
 | 
						|
        DEBUG ((DEBUG_VERBOSE, "    HardwareInstance            - 0x%lx\n", CurrentImageInfo->HardwareInstance));
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
 | 
						|
    //
 | 
						|
    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Dump a non-nested FMP capsule.
 | 
						|
 | 
						|
  @param[in]  CapsuleHeader  A pointer to CapsuleHeader
 | 
						|
**/
 | 
						|
VOID
 | 
						|
DumpFmpCapsule (
 | 
						|
  IN EFI_CAPSULE_HEADER  *CapsuleHeader
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader;
 | 
						|
  UINTN                                         Index;
 | 
						|
  UINT64                                        *ItemOffsetList;
 | 
						|
 | 
						|
  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
 | 
						|
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "FmpCapsule:\n"));
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "  Version                - 0x%x\n", FmpCapsuleHeader->Version));
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "  EmbeddedDriverCount    - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount));
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "  PayloadItemCount       - 0x%x\n", FmpCapsuleHeader->PayloadItemCount));
 | 
						|
 | 
						|
  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
 | 
						|
  for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "  ItemOffsetList[%d]      - 0x%lx\n", Index, ItemOffsetList[Index]));
 | 
						|
  }
 | 
						|
 | 
						|
  for ( ; Index < (UINT32)FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount; Index++) {
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "  ItemOffsetList[%d]      - 0x%lx\n", Index, ItemOffsetList[Index]));
 | 
						|
    ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
 | 
						|
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "  ImageHeader:\n"));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    Version                - 0x%x\n", ImageHeader->Version));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    UpdateImageTypeId      - %g\n", &ImageHeader->UpdateImageTypeId));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    UpdateImageIndex       - 0x%x\n", ImageHeader->UpdateImageIndex));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    UpdateImageSize        - 0x%x\n", ImageHeader->UpdateImageSize));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "    UpdateVendorCodeSize   - 0x%x\n", ImageHeader->UpdateVendorCodeSize));
 | 
						|
    if (ImageHeader->Version >= 2) {
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "    UpdateHardwareInstance - 0x%lx\n", ImageHeader->UpdateHardwareInstance));
 | 
						|
      if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
 | 
						|
        DEBUG ((DEBUG_VERBOSE, "    ImageCapsuleSupport    - 0x%lx\n", ImageHeader->ImageCapsuleSupport));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Dump all FMP information.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
DumpAllFmpInfo (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_HANDLE                        *HandleBuffer;
 | 
						|
  UINTN                             NumberOfHandles;
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;
 | 
						|
  UINTN                             Index;
 | 
						|
  UINTN                             ImageInfoSize;
 | 
						|
  EFI_FIRMWARE_IMAGE_DESCRIPTOR     *FmpImageInfoBuf;
 | 
						|
  UINT32                            FmpImageInfoDescriptorVer;
 | 
						|
  UINT8                             FmpImageInfoCount;
 | 
						|
  UINTN                             DescriptorSize;
 | 
						|
  UINT32                            PackageVersion;
 | 
						|
  CHAR16                            *PackageVersionName;
 | 
						|
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  ByProtocol,
 | 
						|
                  &gEfiFirmwareManagementProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &NumberOfHandles,
 | 
						|
                  &HandleBuffer
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < NumberOfHandles; Index++) {
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    HandleBuffer[Index],
 | 
						|
                    &gEfiFirmwareManagementProtocolGuid,
 | 
						|
                    (VOID **)&Fmp
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    ImageInfoSize = 0;
 | 
						|
    Status        = Fmp->GetImageInfo (
 | 
						|
                           Fmp,
 | 
						|
                           &ImageInfoSize,
 | 
						|
                           NULL,
 | 
						|
                           NULL,
 | 
						|
                           NULL,
 | 
						|
                           NULL,
 | 
						|
                           NULL,
 | 
						|
                           NULL
 | 
						|
                           );
 | 
						|
    if (Status != EFI_BUFFER_TOO_SMALL) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
 | 
						|
    if (FmpImageInfoBuf == NULL) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    PackageVersionName = NULL;
 | 
						|
    Status             = Fmp->GetImageInfo (
 | 
						|
                                Fmp,
 | 
						|
                                &ImageInfoSize,             // ImageInfoSize
 | 
						|
                                FmpImageInfoBuf,            // ImageInfo
 | 
						|
                                &FmpImageInfoDescriptorVer, // DescriptorVersion
 | 
						|
                                &FmpImageInfoCount,         // DescriptorCount
 | 
						|
                                &DescriptorSize,            // DescriptorSize
 | 
						|
                                &PackageVersion,            // PackageVersion
 | 
						|
                                &PackageVersionName         // PackageVersionName
 | 
						|
                                );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      FreePool (FmpImageInfoBuf);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    DEBUG ((DEBUG_INFO, "FMP (%d) ImageInfo:\n", Index));
 | 
						|
    DumpFmpImageInfo (
 | 
						|
      ImageInfoSize,               // ImageInfoSize
 | 
						|
      FmpImageInfoBuf,             // ImageInfo
 | 
						|
      FmpImageInfoDescriptorVer,   // DescriptorVersion
 | 
						|
      FmpImageInfoCount,           // DescriptorCount
 | 
						|
      DescriptorSize,              // DescriptorSize
 | 
						|
      PackageVersion,              // PackageVersion
 | 
						|
      PackageVersionName           // PackageVersionName
 | 
						|
      );
 | 
						|
 | 
						|
    if (PackageVersionName != NULL) {
 | 
						|
      FreePool (PackageVersionName);
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (FmpImageInfoBuf);
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (HandleBuffer);
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get FMP handle by ImageTypeId and HardwareInstance.
 | 
						|
 | 
						|
  @param[in]     UpdateImageTypeId       Used to identify device firmware targeted by this update.
 | 
						|
  @param[in]     UpdateHardwareInstance  The HardwareInstance to target with this update.
 | 
						|
  @param[out]    NoHandles               The number of handles returned in HandleBuf.
 | 
						|
  @param[out]    HandleBuf               A pointer to the buffer to return the requested array of handles.
 | 
						|
  @param[out]    ResetRequiredBuf        A pointer to the buffer to return reset required flag for
 | 
						|
                                         the requested array of handles.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The array of handles and their reset required flag were returned in
 | 
						|
                                 HandleBuf and ResetRequiredBuf, and the number of handles in HandleBuf
 | 
						|
                                 was returned in NoHandles.
 | 
						|
  @retval EFI_NOT_FOUND          No handles match the search.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   There is not enough pool memory to store the matching results.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetFmpHandleBufferByType (
 | 
						|
  IN     EFI_GUID    *UpdateImageTypeId,
 | 
						|
  IN     UINT64      UpdateHardwareInstance,
 | 
						|
  OUT    UINTN       *NoHandles  OPTIONAL,
 | 
						|
  OUT    EFI_HANDLE  **HandleBuf  OPTIONAL,
 | 
						|
  OUT    BOOLEAN     **ResetRequiredBuf OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_HANDLE                        *HandleBuffer;
 | 
						|
  UINTN                             NumberOfHandles;
 | 
						|
  EFI_HANDLE                        *MatchedHandleBuffer;
 | 
						|
  BOOLEAN                           *MatchedResetRequiredBuffer;
 | 
						|
  UINTN                             MatchedNumberOfHandles;
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;
 | 
						|
  UINTN                             Index;
 | 
						|
  UINTN                             ImageInfoSize;
 | 
						|
  EFI_FIRMWARE_IMAGE_DESCRIPTOR     *FmpImageInfoBuf;
 | 
						|
  UINT32                            FmpImageInfoDescriptorVer;
 | 
						|
  UINT8                             FmpImageInfoCount;
 | 
						|
  UINTN                             DescriptorSize;
 | 
						|
  UINT32                            PackageVersion;
 | 
						|
  CHAR16                            *PackageVersionName;
 | 
						|
  UINTN                             Index2;
 | 
						|
  EFI_FIRMWARE_IMAGE_DESCRIPTOR     *TempFmpImageInfo;
 | 
						|
 | 
						|
  if (NoHandles != NULL) {
 | 
						|
    *NoHandles = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if (HandleBuf != NULL) {
 | 
						|
    *HandleBuf = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ResetRequiredBuf != NULL) {
 | 
						|
    *ResetRequiredBuf = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  ByProtocol,
 | 
						|
                  &gEfiFirmwareManagementProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &NumberOfHandles,
 | 
						|
                  &HandleBuffer
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  MatchedNumberOfHandles = 0;
 | 
						|
 | 
						|
  MatchedHandleBuffer = NULL;
 | 
						|
  if (HandleBuf != NULL) {
 | 
						|
    MatchedHandleBuffer = AllocateZeroPool (sizeof (EFI_HANDLE) * NumberOfHandles);
 | 
						|
    if (MatchedHandleBuffer == NULL) {
 | 
						|
      FreePool (HandleBuffer);
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  MatchedResetRequiredBuffer = NULL;
 | 
						|
  if (ResetRequiredBuf != NULL) {
 | 
						|
    MatchedResetRequiredBuffer = AllocateZeroPool (sizeof (BOOLEAN) * NumberOfHandles);
 | 
						|
    if (MatchedResetRequiredBuffer == NULL) {
 | 
						|
      if (MatchedHandleBuffer != NULL) {
 | 
						|
        FreePool (MatchedHandleBuffer);
 | 
						|
      }
 | 
						|
 | 
						|
      FreePool (HandleBuffer);
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < NumberOfHandles; Index++) {
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    HandleBuffer[Index],
 | 
						|
                    &gEfiFirmwareManagementProtocolGuid,
 | 
						|
                    (VOID **)&Fmp
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    ImageInfoSize = 0;
 | 
						|
    Status        = Fmp->GetImageInfo (
 | 
						|
                           Fmp,
 | 
						|
                           &ImageInfoSize,
 | 
						|
                           NULL,
 | 
						|
                           NULL,
 | 
						|
                           NULL,
 | 
						|
                           NULL,
 | 
						|
                           NULL,
 | 
						|
                           NULL
 | 
						|
                           );
 | 
						|
    if (Status != EFI_BUFFER_TOO_SMALL) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
 | 
						|
    if (FmpImageInfoBuf == NULL) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    PackageVersionName = NULL;
 | 
						|
    Status             = Fmp->GetImageInfo (
 | 
						|
                                Fmp,
 | 
						|
                                &ImageInfoSize,             // ImageInfoSize
 | 
						|
                                FmpImageInfoBuf,            // ImageInfo
 | 
						|
                                &FmpImageInfoDescriptorVer, // DescriptorVersion
 | 
						|
                                &FmpImageInfoCount,         // DescriptorCount
 | 
						|
                                &DescriptorSize,            // DescriptorSize
 | 
						|
                                &PackageVersion,            // PackageVersion
 | 
						|
                                &PackageVersionName         // PackageVersionName
 | 
						|
                                );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      FreePool (FmpImageInfoBuf);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (PackageVersionName != NULL) {
 | 
						|
      FreePool (PackageVersionName);
 | 
						|
    }
 | 
						|
 | 
						|
    TempFmpImageInfo = FmpImageInfoBuf;
 | 
						|
    for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {
 | 
						|
      //
 | 
						|
      // Check if this FMP instance matches
 | 
						|
      //
 | 
						|
      if (CompareGuid (UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId)) {
 | 
						|
        if ((UpdateHardwareInstance == 0) ||
 | 
						|
            ((FmpImageInfoDescriptorVer >= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) &&
 | 
						|
             (UpdateHardwareInstance == TempFmpImageInfo->HardwareInstance)))
 | 
						|
        {
 | 
						|
          if (MatchedHandleBuffer != NULL) {
 | 
						|
            MatchedHandleBuffer[MatchedNumberOfHandles] = HandleBuffer[Index];
 | 
						|
          }
 | 
						|
 | 
						|
          if (MatchedResetRequiredBuffer != NULL) {
 | 
						|
            MatchedResetRequiredBuffer[MatchedNumberOfHandles] = (((TempFmpImageInfo->AttributesSupported &
 | 
						|
                                                                    IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0) &&
 | 
						|
                                                                  ((TempFmpImageInfo->AttributesSetting &
 | 
						|
                                                                    IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0));
 | 
						|
          }
 | 
						|
 | 
						|
          MatchedNumberOfHandles++;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (FmpImageInfoBuf);
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (HandleBuffer);
 | 
						|
 | 
						|
  if (MatchedNumberOfHandles == 0) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  if (NoHandles != NULL) {
 | 
						|
    *NoHandles = MatchedNumberOfHandles;
 | 
						|
  }
 | 
						|
 | 
						|
  if (HandleBuf != NULL) {
 | 
						|
    *HandleBuf = MatchedHandleBuffer;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ResetRequiredBuf != NULL) {
 | 
						|
    *ResetRequiredBuf = MatchedResetRequiredBuffer;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return FmpImageInfoDescriptorVer by an FMP handle.
 | 
						|
 | 
						|
  @param[in]  Handle   A FMP handle.
 | 
						|
 | 
						|
  @return FmpImageInfoDescriptorVer associated with the FMP.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
GetFmpImageInfoDescriptorVer (
 | 
						|
  IN EFI_HANDLE  Handle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;
 | 
						|
  UINTN                             ImageInfoSize;
 | 
						|
  EFI_FIRMWARE_IMAGE_DESCRIPTOR     *FmpImageInfoBuf;
 | 
						|
  UINT32                            FmpImageInfoDescriptorVer;
 | 
						|
  UINT8                             FmpImageInfoCount;
 | 
						|
  UINTN                             DescriptorSize;
 | 
						|
  UINT32                            PackageVersion;
 | 
						|
  CHAR16                            *PackageVersionName;
 | 
						|
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  Handle,
 | 
						|
                  &gEfiFirmwareManagementProtocolGuid,
 | 
						|
                  (VOID **)&Fmp
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  ImageInfoSize = 0;
 | 
						|
  Status        = Fmp->GetImageInfo (
 | 
						|
                         Fmp,
 | 
						|
                         &ImageInfoSize,
 | 
						|
                         NULL,
 | 
						|
                         NULL,
 | 
						|
                         NULL,
 | 
						|
                         NULL,
 | 
						|
                         NULL,
 | 
						|
                         NULL
 | 
						|
                         );
 | 
						|
  if (Status != EFI_BUFFER_TOO_SMALL) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
 | 
						|
  if (FmpImageInfoBuf == NULL) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  PackageVersionName = NULL;
 | 
						|
  Status             = Fmp->GetImageInfo (
 | 
						|
                              Fmp,
 | 
						|
                              &ImageInfoSize,             // ImageInfoSize
 | 
						|
                              FmpImageInfoBuf,            // ImageInfo
 | 
						|
                              &FmpImageInfoDescriptorVer, // DescriptorVersion
 | 
						|
                              &FmpImageInfoCount,         // DescriptorCount
 | 
						|
                              &DescriptorSize,            // DescriptorSize
 | 
						|
                              &PackageVersion,            // PackageVersion
 | 
						|
                              &PackageVersionName         // PackageVersionName
 | 
						|
                              );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool (FmpImageInfoBuf);
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return FmpImageInfoDescriptorVer;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set FMP image data.
 | 
						|
 | 
						|
  @param[in]  Handle        A FMP handle.
 | 
						|
  @param[in]  ImageHeader   The payload image header.
 | 
						|
  @param[in]  PayloadIndex  The index of the payload.
 | 
						|
 | 
						|
  @return The status of FMP->SetImage.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SetFmpImageData (
 | 
						|
  IN EFI_HANDLE                                    Handle,
 | 
						|
  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader,
 | 
						|
  IN UINTN                                         PayloadIndex
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                                     Status;
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_PROTOCOL               *Fmp;
 | 
						|
  UINT8                                          *Image;
 | 
						|
  VOID                                           *VendorCode;
 | 
						|
  CHAR16                                         *AbortReason;
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  ProgressCallback;
 | 
						|
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  Handle,
 | 
						|
                  &gEfiFirmwareManagementProtocolGuid,
 | 
						|
                  (VOID **)&Fmp
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Lookup Firmware Management Progress Protocol before SetImage() is called
 | 
						|
  // This is an optional protocol that may not be present on Handle.
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  Handle,
 | 
						|
                  &gEdkiiFirmwareManagementProgressProtocolGuid,
 | 
						|
                  (VOID **)&mFmpProgress
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    mFmpProgress = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
 | 
						|
    Image = (UINT8 *)(ImageHeader + 1);
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
 | 
						|
    // Header should exclude UpdateHardwareInstance field, and
 | 
						|
    // ImageCapsuleSupport field if version is 2.
 | 
						|
    //
 | 
						|
    if (ImageHeader->Version == 1) {
 | 
						|
      Image = (UINT8 *)ImageHeader + OFFSET_OF (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
 | 
						|
    } else {
 | 
						|
      Image = (UINT8 *)ImageHeader + OFFSET_OF (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, ImageCapsuleSupport);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (ImageHeader->UpdateVendorCodeSize == 0) {
 | 
						|
    VendorCode = NULL;
 | 
						|
  } else {
 | 
						|
    VendorCode = Image + ImageHeader->UpdateImageSize;
 | 
						|
  }
 | 
						|
 | 
						|
  AbortReason = NULL;
 | 
						|
  DEBUG ((DEBUG_INFO, "Fmp->SetImage ...\n"));
 | 
						|
  DEBUG ((DEBUG_INFO, "ImageTypeId - %g, ", &ImageHeader->UpdateImageTypeId));
 | 
						|
  DEBUG ((DEBUG_INFO, "PayloadIndex - 0x%x, ", PayloadIndex));
 | 
						|
  DEBUG ((DEBUG_INFO, "ImageIndex - 0x%x ", ImageHeader->UpdateImageIndex));
 | 
						|
  if (ImageHeader->Version >= 2) {
 | 
						|
    DEBUG ((DEBUG_INFO, "(UpdateHardwareInstance - 0x%x)", ImageHeader->UpdateHardwareInstance));
 | 
						|
    if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
 | 
						|
      DEBUG ((DEBUG_INFO, "(ImageCapsuleSupport - 0x%x)", ImageHeader->ImageCapsuleSupport));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "\n"));
 | 
						|
 | 
						|
  //
 | 
						|
  // Before calling SetImage(), reset the progress bar to 0%
 | 
						|
  //
 | 
						|
  ProgressCallback = UpdateImageProgress;
 | 
						|
  Status           = UpdateImageProgress (0);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ProgressCallback = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = Fmp->SetImage (
 | 
						|
                  Fmp,
 | 
						|
                  ImageHeader->UpdateImageIndex,          // ImageIndex
 | 
						|
                  Image,                                  // Image
 | 
						|
                  ImageHeader->UpdateImageSize,           // ImageSize
 | 
						|
                  VendorCode,                             // VendorCode
 | 
						|
                  ProgressCallback,                       // Progress
 | 
						|
                  &AbortReason                            // AbortReason
 | 
						|
                  );
 | 
						|
  //
 | 
						|
  // Set the progress bar to 100% after returning from SetImage()
 | 
						|
  //
 | 
						|
  if (ProgressCallback != NULL) {
 | 
						|
    UpdateImageProgress (100);
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "Fmp->SetImage - %r\n", Status));
 | 
						|
  if (AbortReason != NULL) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "%s\n", AbortReason));
 | 
						|
    FreePool (AbortReason);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Clear mFmpProgress after SetImage() returns
 | 
						|
  //
 | 
						|
  mFmpProgress = NULL;
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Start a UEFI image in the FMP payload.
 | 
						|
 | 
						|
  @param[in]  ImageBuffer   A pointer to the memory location containing a copy of the image to be loaded..
 | 
						|
  @param[in]  ImageSize     The size in bytes of ImageBuffer.
 | 
						|
 | 
						|
  @return The status of gBS->LoadImage and gBS->StartImage.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
StartFmpImage (
 | 
						|
  IN VOID   *ImageBuffer,
 | 
						|
  IN UINTN  ImageSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  MEMMAP_DEVICE_PATH        MemMapNode;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_HANDLE                ImageHandle;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DriverDevicePath;
 | 
						|
  UINTN                     ExitDataSize;
 | 
						|
 | 
						|
  SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));
 | 
						|
  MemMapNode.Header.Type     = HARDWARE_DEVICE_PATH;
 | 
						|
  MemMapNode.Header.SubType  = HW_MEMMAP_DP;
 | 
						|
  MemMapNode.MemoryType      = EfiBootServicesCode;
 | 
						|
  MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBuffer;
 | 
						|
  MemMapNode.EndingAddress   = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)ImageBuffer + ImageSize - 1);
 | 
						|
 | 
						|
  DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);
 | 
						|
  if (DriverDevicePath == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "FmpCapsule: LoadImage ...\n"));
 | 
						|
  Status = gBS->LoadImage (
 | 
						|
                  FALSE,
 | 
						|
                  gImageHandle,
 | 
						|
                  DriverDevicePath,
 | 
						|
                  ImageBuffer,
 | 
						|
                  ImageSize,
 | 
						|
                  &ImageHandle
 | 
						|
                  );
 | 
						|
  DEBUG ((DEBUG_INFO, "FmpCapsule: LoadImage - %r\n", Status));
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created
 | 
						|
    // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.
 | 
						|
    // If the caller doesn't have the option to defer the execution of an image, we should
 | 
						|
    // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.
 | 
						|
    //
 | 
						|
    if (Status == EFI_SECURITY_VIOLATION) {
 | 
						|
      gBS->UnloadImage (ImageHandle);
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (DriverDevicePath);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "FmpCapsule: StartImage ...\n"));
 | 
						|
  Status = gBS->StartImage (
 | 
						|
                  ImageHandle,
 | 
						|
                  &ExitDataSize,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  DEBUG ((DEBUG_INFO, "FmpCapsule: StartImage - %r\n", Status));
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (DriverDevicePath);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Record FMP capsule status.
 | 
						|
 | 
						|
  @param[in] Handle         A FMP handle.
 | 
						|
  @param[in] CapsuleHeader  The capsule image header
 | 
						|
  @param[in] CapsuleStatus  The capsule process stauts
 | 
						|
  @param[in] PayloadIndex   FMP payload index
 | 
						|
  @param[in] ImageHeader    FMP image header
 | 
						|
  @param[in] CapFileName    Capsule file name
 | 
						|
**/
 | 
						|
VOID
 | 
						|
RecordFmpCapsuleStatus (
 | 
						|
  IN EFI_HANDLE                                    Handle   OPTIONAL,
 | 
						|
  IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
 | 
						|
  IN EFI_STATUS                                    CapsuleStatus,
 | 
						|
  IN UINTN                                         PayloadIndex,
 | 
						|
  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader,
 | 
						|
  IN CHAR16                                        *CapFileName   OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                 Status;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL   *FmpDevicePath;
 | 
						|
  UINT32                     FmpImageInfoDescriptorVer;
 | 
						|
  EFI_STATUS                 StatusEsrt;
 | 
						|
  ESRT_MANAGEMENT_PROTOCOL   *EsrtProtocol;
 | 
						|
  EFI_SYSTEM_RESOURCE_ENTRY  EsrtEntry;
 | 
						|
 | 
						|
  FmpDevicePath = NULL;
 | 
						|
  if (Handle != NULL) {
 | 
						|
    gBS->HandleProtocol (
 | 
						|
           Handle,
 | 
						|
           &gEfiDevicePathProtocolGuid,
 | 
						|
           (VOID **)&FmpDevicePath
 | 
						|
           );
 | 
						|
  }
 | 
						|
 | 
						|
  RecordFmpCapsuleStatusVariable (
 | 
						|
    CapsuleHeader,
 | 
						|
    CapsuleStatus,
 | 
						|
    PayloadIndex,
 | 
						|
    ImageHeader,
 | 
						|
    FmpDevicePath,
 | 
						|
    CapFileName
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Update corresponding ESRT entry LastAttemp Status
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Handle == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Update EsrtEntry For V1, V2 FMP instance.
 | 
						|
  // V3 FMP ESRT cache will be synced up through SyncEsrtFmp interface
 | 
						|
  //
 | 
						|
  FmpImageInfoDescriptorVer = GetFmpImageInfoDescriptorVer (Handle);
 | 
						|
  if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) {
 | 
						|
    StatusEsrt = EsrtProtocol->GetEsrtEntry (&ImageHeader->UpdateImageTypeId, &EsrtEntry);
 | 
						|
    if (!EFI_ERROR (StatusEsrt)) {
 | 
						|
      if (!EFI_ERROR (CapsuleStatus)) {
 | 
						|
        EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
 | 
						|
      } else {
 | 
						|
        EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
 | 
						|
      }
 | 
						|
 | 
						|
      EsrtEntry.LastAttemptVersion = 0;
 | 
						|
      EsrtProtocol->UpdateEsrtEntry (&EsrtEntry);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Process Firmware management protocol data capsule.
 | 
						|
 | 
						|
  This function assumes the caller validated the capsule by using
 | 
						|
  ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
 | 
						|
 | 
						|
  This function need support nested FMP capsule.
 | 
						|
 | 
						|
  @param[in]  CapsuleHeader         Points to a capsule header.
 | 
						|
  @param[in]  CapFileName           Capsule file name.
 | 
						|
  @param[out] ResetRequired         Indicates whether reset is required or not.
 | 
						|
 | 
						|
  @retval EFI_SUCESS            Process Capsule Image successfully.
 | 
						|
  @retval EFI_UNSUPPORTED       Capsule image is not supported by the firmware.
 | 
						|
  @retval EFI_VOLUME_CORRUPTED  FV volume in the capsule is corrupted.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough memory.
 | 
						|
  @retval EFI_NOT_READY         No FMP protocol to handle this FMP capsule.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ProcessFmpCapsuleImage (
 | 
						|
  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
 | 
						|
  IN CHAR16              *CapFileName   OPTIONAL,
 | 
						|
  OUT BOOLEAN            *ResetRequired OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                                    Status;
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
 | 
						|
  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader;
 | 
						|
  UINT64                                        *ItemOffsetList;
 | 
						|
  UINT32                                        ItemNum;
 | 
						|
  UINTN                                         Index;
 | 
						|
  EFI_HANDLE                                    *HandleBuffer;
 | 
						|
  BOOLEAN                                       *ResetRequiredBuffer;
 | 
						|
  UINTN                                         NumberOfHandles;
 | 
						|
  UINTN                                         DriverLen;
 | 
						|
  UINT64                                        UpdateHardwareInstance;
 | 
						|
  UINTN                                         Index2;
 | 
						|
  BOOLEAN                                       NotReady;
 | 
						|
  BOOLEAN                                       Abort;
 | 
						|
 | 
						|
  if (!IsFmpCapsuleGuid (&CapsuleHeader->CapsuleGuid)) {
 | 
						|
    return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), CapFileName, ResetRequired);
 | 
						|
  }
 | 
						|
 | 
						|
  NotReady = FALSE;
 | 
						|
  Abort    = FALSE;
 | 
						|
 | 
						|
  DumpFmpCapsule (CapsuleHeader);
 | 
						|
 | 
						|
  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
 | 
						|
 | 
						|
  if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
 | 
						|
 | 
						|
  ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
 | 
						|
 | 
						|
  //
 | 
						|
  // capsule in which driver count and payload count are both zero is not processed.
 | 
						|
  //
 | 
						|
  if (ItemNum == 0) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 1. Try to load & start all the drivers within capsule
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
 | 
						|
    if ((FmpCapsuleHeader->PayloadItemCount == 0) &&
 | 
						|
        (Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1))
 | 
						|
    {
 | 
						|
      //
 | 
						|
      // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
 | 
						|
      //
 | 
						|
      DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];
 | 
						|
    } else {
 | 
						|
      DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];
 | 
						|
    }
 | 
						|
 | 
						|
    Status = StartFmpImage (
 | 
						|
               (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],
 | 
						|
               DriverLen
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 2. Route payload to right FMP instance
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));
 | 
						|
 | 
						|
  DumpAllFmpInfo ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Check all the payload entry in capsule payload list
 | 
						|
  //
 | 
						|
  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
 | 
						|
    ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
 | 
						|
 | 
						|
    UpdateHardwareInstance = 0;
 | 
						|
    ///
 | 
						|
    /// UpdateHardwareInstance field was added in Version 2
 | 
						|
    ///
 | 
						|
    if (ImageHeader->Version >= 2) {
 | 
						|
      UpdateHardwareInstance = ImageHeader->UpdateHardwareInstance;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = GetFmpHandleBufferByType (
 | 
						|
               &ImageHeader->UpdateImageTypeId,
 | 
						|
               UpdateHardwareInstance,
 | 
						|
               &NumberOfHandles,
 | 
						|
               &HandleBuffer,
 | 
						|
               &ResetRequiredBuffer
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status) ||
 | 
						|
        (HandleBuffer == NULL) ||
 | 
						|
        (ResetRequiredBuffer == NULL))
 | 
						|
    {
 | 
						|
      NotReady = TRUE;
 | 
						|
      RecordFmpCapsuleStatus (
 | 
						|
        NULL,
 | 
						|
        CapsuleHeader,
 | 
						|
        EFI_NOT_READY,
 | 
						|
        Index - FmpCapsuleHeader->EmbeddedDriverCount,
 | 
						|
        ImageHeader,
 | 
						|
        CapFileName
 | 
						|
        );
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    for (Index2 = 0; Index2 < NumberOfHandles; Index2++) {
 | 
						|
      if (Abort) {
 | 
						|
        RecordFmpCapsuleStatus (
 | 
						|
          HandleBuffer[Index2],
 | 
						|
          CapsuleHeader,
 | 
						|
          EFI_ABORTED,
 | 
						|
          Index - FmpCapsuleHeader->EmbeddedDriverCount,
 | 
						|
          ImageHeader,
 | 
						|
          CapFileName
 | 
						|
          );
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      Status = SetFmpImageData (
 | 
						|
                 HandleBuffer[Index2],
 | 
						|
                 ImageHeader,
 | 
						|
                 Index - FmpCapsuleHeader->EmbeddedDriverCount
 | 
						|
                 );
 | 
						|
      if (Status != EFI_SUCCESS) {
 | 
						|
        Abort = TRUE;
 | 
						|
      } else {
 | 
						|
        if (ResetRequired != NULL) {
 | 
						|
          *ResetRequired |= ResetRequiredBuffer[Index2];
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      RecordFmpCapsuleStatus (
 | 
						|
        HandleBuffer[Index2],
 | 
						|
        CapsuleHeader,
 | 
						|
        Status,
 | 
						|
        Index - FmpCapsuleHeader->EmbeddedDriverCount,
 | 
						|
        ImageHeader,
 | 
						|
        CapFileName
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    if (HandleBuffer != NULL) {
 | 
						|
      FreePool (HandleBuffer);
 | 
						|
    }
 | 
						|
 | 
						|
    if (ResetRequiredBuffer != NULL) {
 | 
						|
      FreePool (ResetRequiredBuffer);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (NotReady) {
 | 
						|
    return EFI_NOT_READY;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // always return SUCCESS to indicate this capsule is processed.
 | 
						|
  // The status of SetImage is recorded in capsule result variable.
 | 
						|
  //
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return if there is a FMP header below capsule header.
 | 
						|
 | 
						|
  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
 | 
						|
 | 
						|
  @retval TRUE  There is a FMP header below capsule header.
 | 
						|
  @retval FALSE There is not a FMP header below capsule header
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsNestedFmpCapsule (
 | 
						|
  IN EFI_CAPSULE_HEADER  *CapsuleHeader
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                 Status;
 | 
						|
  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
 | 
						|
  UINTN                      Index;
 | 
						|
  BOOLEAN                    EsrtGuidFound;
 | 
						|
  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
 | 
						|
  UINTN                      NestedCapsuleSize;
 | 
						|
  ESRT_MANAGEMENT_PROTOCOL   *EsrtProtocol;
 | 
						|
  EFI_SYSTEM_RESOURCE_ENTRY  Entry;
 | 
						|
 | 
						|
  EsrtGuidFound = FALSE;
 | 
						|
  if (mIsVirtualAddrConverted) {
 | 
						|
    if (mEsrtTable != NULL) {
 | 
						|
      EsrtEntry = (EFI_SYSTEM_RESOURCE_ENTRY *)(mEsrtTable + 1);
 | 
						|
      for (Index = 0; Index < mEsrtTable->FwResourceCount; Index++, EsrtEntry++) {
 | 
						|
        if (CompareGuid (&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
 | 
						|
          EsrtGuidFound = TRUE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Check ESRT protocol
 | 
						|
    //
 | 
						|
    Status = gBS->LocateProtocol (&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      Status = EsrtProtocol->GetEsrtEntry (&CapsuleHeader->CapsuleGuid, &Entry);
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        EsrtGuidFound = TRUE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Check Firmware Management Protocols
 | 
						|
    //
 | 
						|
    if (!EsrtGuidFound) {
 | 
						|
      Status = GetFmpHandleBufferByType (
 | 
						|
                 &CapsuleHeader->CapsuleGuid,
 | 
						|
                 0,
 | 
						|
                 NULL,
 | 
						|
                 NULL,
 | 
						|
                 NULL
 | 
						|
                 );
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        EsrtGuidFound = TRUE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!EsrtGuidFound) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check nested capsule header
 | 
						|
  // FMP GUID after ESRT one
 | 
						|
  //
 | 
						|
  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
 | 
						|
  NestedCapsuleSize   = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize - (UINTN)NestedCapsuleHeader;
 | 
						|
  if (NestedCapsuleSize < sizeof (EFI_CAPSULE_HEADER)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!IsValidCapsuleHeader (NestedCapsuleHeader, NestedCapsuleSize)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!IsFmpCapsuleGuid (&NestedCapsuleHeader->CapsuleGuid)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "IsNestedFmpCapsule\n"));
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
 | 
						|
 | 
						|
  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
 | 
						|
 | 
						|
  @retval TRUE  It is a system FMP.
 | 
						|
  @retval FALSE It is a device FMP.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsFmpCapsule (
 | 
						|
  IN EFI_CAPSULE_HEADER  *CapsuleHeader
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (IsFmpCapsuleGuid (&CapsuleHeader->CapsuleGuid)) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (IsNestedFmpCapsule (CapsuleHeader)) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Those capsules supported by the firmwares.
 | 
						|
 | 
						|
  Caution: This function may receive untrusted input.
 | 
						|
 | 
						|
  @param[in]  CapsuleHeader    Points to a capsule header.
 | 
						|
 | 
						|
  @retval EFI_SUCESS       Input capsule is supported by firmware.
 | 
						|
  @retval EFI_UNSUPPORTED  Input capsule is not supported by the firmware.
 | 
						|
  @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SupportCapsuleImage (
 | 
						|
  IN EFI_CAPSULE_HEADER  *CapsuleHeader
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // check Display Capsule Guid
 | 
						|
  //
 | 
						|
  if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check capsule file name capsule
 | 
						|
  //
 | 
						|
  if (IsCapsuleNameCapsule (CapsuleHeader)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (IsFmpCapsule (CapsuleHeader)) {
 | 
						|
    //
 | 
						|
    // Fake capsule header is valid case in QueryCapsuleCpapbilities().
 | 
						|
    //
 | 
						|
    if (CapsuleHeader->HeaderSize == CapsuleHeader->CapsuleImageSize) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Check layout of FMP capsule
 | 
						|
    //
 | 
						|
    return ValidateFmpCapsule (CapsuleHeader, NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_ERROR, "Unknown Capsule Guid - %g\n", &CapsuleHeader->CapsuleGuid));
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The firmware implements to process the capsule image.
 | 
						|
 | 
						|
  Caution: This function may receive untrusted input.
 | 
						|
 | 
						|
  @param[in]  CapsuleHeader         Points to a capsule header.
 | 
						|
  @param[in]  CapFileName           Capsule file name.
 | 
						|
  @param[out] ResetRequired         Indicates whether reset is required or not.
 | 
						|
 | 
						|
  @retval EFI_SUCESS            Process Capsule Image successfully.
 | 
						|
  @retval EFI_UNSUPPORTED       Capsule image is not supported by the firmware.
 | 
						|
  @retval EFI_VOLUME_CORRUPTED  FV volume in the capsule is corrupted.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough memory.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ProcessThisCapsuleImage (
 | 
						|
  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
 | 
						|
  IN CHAR16              *CapFileName   OPTIONAL,
 | 
						|
  OUT BOOLEAN            *ResetRequired OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {
 | 
						|
    RecordCapsuleStatusVariable (CapsuleHeader, EFI_UNSUPPORTED);
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Display image in firmware update display capsule
 | 
						|
  //
 | 
						|
  if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
 | 
						|
    DEBUG ((DEBUG_INFO, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
 | 
						|
    Status = DisplayCapsuleImage (CapsuleHeader);
 | 
						|
    RecordCapsuleStatusVariable (CapsuleHeader, Status);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check FMP capsule layout
 | 
						|
  //
 | 
						|
  if (IsFmpCapsule (CapsuleHeader)) {
 | 
						|
    DEBUG ((DEBUG_INFO, "ProcessCapsuleImage for FmpCapsule ...\n"));
 | 
						|
    DEBUG ((DEBUG_INFO, "ValidateFmpCapsule ...\n"));
 | 
						|
    Status = ValidateFmpCapsule (CapsuleHeader, NULL);
 | 
						|
    DEBUG ((DEBUG_INFO, "ValidateFmpCapsule - %r\n", Status));
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      RecordCapsuleStatusVariable (CapsuleHeader, Status);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Process EFI FMP Capsule
 | 
						|
    //
 | 
						|
    DEBUG ((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));
 | 
						|
    Status = ProcessFmpCapsuleImage (CapsuleHeader, CapFileName, ResetRequired);
 | 
						|
    DEBUG ((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
 | 
						|
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The firmware implements to process the capsule image.
 | 
						|
 | 
						|
  Caution: This function may receive untrusted input.
 | 
						|
 | 
						|
  @param[in]  CapsuleHeader         Points to a capsule header.
 | 
						|
 | 
						|
  @retval EFI_SUCESS            Process Capsule Image successfully.
 | 
						|
  @retval EFI_UNSUPPORTED       Capsule image is not supported by the firmware.
 | 
						|
  @retval EFI_VOLUME_CORRUPTED  FV volume in the capsule is corrupted.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Not enough memory.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ProcessCapsuleImage (
 | 
						|
  IN EFI_CAPSULE_HEADER  *CapsuleHeader
 | 
						|
  )
 | 
						|
{
 | 
						|
  return ProcessThisCapsuleImage (CapsuleHeader, NULL, NULL);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Callback function executed when the EndOfDxe event group is signaled.
 | 
						|
 | 
						|
  @param[in] Event      Event whose notification function is being invoked.
 | 
						|
  @param[in] Context    The pointer to the notification function's context, which
 | 
						|
                        is implementation-dependent.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
DxeCapsuleLibEndOfDxe (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  mDxeCapsuleLibEndOfDxe = TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The constructor function.
 | 
						|
 | 
						|
  @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 constructor successfully .
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
DxeCapsuleLibConstructor (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  Status = gBS->CreateEventEx (
 | 
						|
                  EVT_NOTIFY_SIGNAL,
 | 
						|
                  TPL_CALLBACK,
 | 
						|
                  DxeCapsuleLibEndOfDxe,
 | 
						|
                  NULL,
 | 
						|
                  &gEfiEndOfDxeEventGroupGuid,
 | 
						|
                  &mDxeCapsuleLibEndOfDxeEvent
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  InitCapsuleVariable ();
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The destructor function closes the End of DXE event.
 | 
						|
 | 
						|
  @param  ImageHandle   The firmware allocated handle for the EFI image.
 | 
						|
  @param  SystemTable   A pointer to the EFI System Table.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   The destructor completed successfully.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
DxeCapsuleLibDestructor (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Close the End of DXE event.
 | 
						|
  //
 | 
						|
  Status = gBS->CloseEvent (mDxeCapsuleLibEndOfDxeEvent);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |