mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-31 01:35:30 +00:00 
			
		
		
		
	 d2a160304e
			
		
	
	
		d2a160304e
		
	
	
	
	
		
			
			This instance handles Microsoft UX capsule, UEFI defined FMP capsule. This instance should not assume any capsule image format. Cc: Feng Tian <feng.tian@intel.com> Cc: Star Zeng <star.zeng@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Liming Gao <liming.gao@intel.com> Cc: Chao Zhang <chao.b.zhang@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao <jiewen.yao@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> Reviewed-by: Michael Kinney <michael.d.kinney@intel.com> Tested-by: Michael Kinney <michael.d.kinney@intel.com>
		
			
				
	
	
		
			1365 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1365 lines
		
	
	
		
			48 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(), DisplayCapsuleImage(), ConvertBmpToGopBlt() will
 | |
|   receive untrusted input and do basic validation.
 | |
| 
 | |
|   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <PiDxe.h>
 | |
| 
 | |
| #include <IndustryStandard/Bmp.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/PcdLib.h>
 | |
| 
 | |
| #include <Protocol/GraphicsOutput.h>
 | |
| #include <Protocol/EsrtManagement.h>
 | |
| #include <Protocol/FirmwareManagement.h>
 | |
| #include <Protocol/DevicePath.h>
 | |
| 
 | |
| BOOLEAN            mAreAllImagesProcessed;
 | |
| 
 | |
| EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable              = NULL;
 | |
| BOOLEAN                   mIsVirtualAddrConverted  = FALSE;
 | |
| BOOLEAN                   mDxeCapsuleLibEndOfDxe   = FALSE;
 | |
| 
 | |
| /**
 | |
|   Initialize capsule related variables.
 | |
| **/
 | |
| VOID
 | |
| InitCapsuleVariable (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Check if this FMP capsule is processed.
 | |
| 
 | |
|   @param[in] CapsuleHeader  The capsule image header
 | |
|   @param[in] PayloadIndex   FMP payload index
 | |
|   @param[in] ImageHeader    FMP image header
 | |
| 
 | |
|   @retval TRUE  This FMP capsule is processed.
 | |
|   @retval FALSE This FMP capsule is not processed.
 | |
| **/
 | |
| BOOLEAN
 | |
| IsFmpCapsuleProcessed (
 | |
|   IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
 | |
|   IN UINTN                                         PayloadIndex,
 | |
|   IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   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
 | |
| 
 | |
|   @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
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   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    Input capsule is a correct FMP capsule.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Update_Image_Progress (
 | |
|   IN UINTN  Completion
 | |
|   )
 | |
| {
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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, 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];
 | |
| 
 | |
|     if (FmpImageSize < OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance)) {
 | |
|       DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize));
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|     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 < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
 | |
|       FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
 | |
|     }
 | |
| 
 | |
|     // 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;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
 | |
|   is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
 | |
|   buffer is passed in it will be used if it is big enough.
 | |
| 
 | |
|   Caution: This function may receive untrusted input.
 | |
| 
 | |
|   @param[in]       BmpImage      Pointer to BMP file
 | |
|   @param[in]       BmpImageSize  Number of bytes in BmpImage
 | |
|   @param[in, out]  GopBlt        Buffer containing GOP version of BmpImage.
 | |
|   @param[in, out]  GopBltSize    Size of GopBlt in bytes.
 | |
|   @param[out]      PixelHeight   Height of GopBlt/BmpImage in pixels
 | |
|   @param[out]      PixelWidth    Width of GopBlt/BmpImage in pixels
 | |
| 
 | |
|   @retval EFI_SUCCESS           GopBlt and GopBltSize are returned.
 | |
|   @retval EFI_UNSUPPORTED       BmpImage is not a valid *.BMP image
 | |
|   @retval EFI_BUFFER_TOO_SMALL  The passed in GopBlt buffer is not big enough.
 | |
|                                 GopBltSize will contain the required size.
 | |
|   @retval EFI_OUT_OF_RESOURCES  No enough buffer to allocate.
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ConvertBmpToGopBlt (
 | |
|   IN     VOID      *BmpImage,
 | |
|   IN     UINTN     BmpImageSize,
 | |
|   IN OUT VOID      **GopBlt,
 | |
|   IN OUT UINTN     *GopBltSize,
 | |
|      OUT UINTN     *PixelHeight,
 | |
|      OUT UINTN     *PixelWidth
 | |
|   )
 | |
| {
 | |
|   UINT8                         *Image;
 | |
|   UINT8                         *ImageHeader;
 | |
|   BMP_IMAGE_HEADER              *BmpHeader;
 | |
|   BMP_COLOR_MAP                 *BmpColorMap;
 | |
|   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
 | |
|   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
 | |
|   UINT64                        BltBufferSize;
 | |
|   UINTN                         Index;
 | |
|   UINTN                         Height;
 | |
|   UINTN                         Width;
 | |
|   UINTN                         ImageIndex;
 | |
|   UINT32                        DataSizePerLine;
 | |
|   BOOLEAN                       IsAllocated;
 | |
|   UINT32                        ColorMapNum;
 | |
| 
 | |
|   if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
 | |
| 
 | |
|   if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Doesn't support compress.
 | |
|   //
 | |
|   if (BmpHeader->CompressionType != 0) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Only support BITMAPINFOHEADER format.
 | |
|   // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
 | |
|   //
 | |
|   if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // The data size in each line must be 4 byte alignment.
 | |
|   //
 | |
|   DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);
 | |
|   BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);
 | |
|   if (BltBufferSize > (UINT32) ~0) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if ((BmpHeader->Size != BmpImageSize) ||
 | |
|       (BmpHeader->Size < BmpHeader->ImageOffset) ||
 | |
|       (BmpHeader->Size - BmpHeader->ImageOffset !=  BmpHeader->PixelHeight * DataSizePerLine)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Calculate Color Map offset in the image.
 | |
|   //
 | |
|   Image       = BmpImage;
 | |
|   BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
 | |
|   if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
 | |
|     switch (BmpHeader->BitPerPixel) {
 | |
|       case 1:
 | |
|         ColorMapNum = 2;
 | |
|         break;
 | |
|       case 4:
 | |
|         ColorMapNum = 16;
 | |
|         break;
 | |
|       case 8:
 | |
|         ColorMapNum = 256;
 | |
|         break;
 | |
|       default:
 | |
|         ColorMapNum = 0;
 | |
|         break;
 | |
|       }
 | |
|     //
 | |
|     // BMP file may has padding data between the bmp header section and the bmp data section.
 | |
|     //
 | |
|     if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Calculate graphics image data address in the image
 | |
|   //
 | |
|   Image         = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
 | |
|   ImageHeader   = Image;
 | |
| 
 | |
|   //
 | |
|   // Calculate the BltBuffer needed size.
 | |
|   //
 | |
|   BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
 | |
|   //
 | |
|   // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
 | |
|   //
 | |
|   if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
|   BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | |
| 
 | |
|   IsAllocated   = FALSE;
 | |
|   if (*GopBlt == NULL) {
 | |
|     //
 | |
|     // GopBlt is not allocated by caller.
 | |
|     //
 | |
|     *GopBltSize = (UINTN) BltBufferSize;
 | |
|     *GopBlt     = AllocatePool (*GopBltSize);
 | |
|     IsAllocated = TRUE;
 | |
|     if (*GopBlt == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|   } else {
 | |
|     //
 | |
|     // GopBlt has been allocated by caller.
 | |
|     //
 | |
|     if (*GopBltSize < (UINTN) BltBufferSize) {
 | |
|       *GopBltSize = (UINTN) BltBufferSize;
 | |
|       return EFI_BUFFER_TOO_SMALL;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   *PixelWidth   = BmpHeader->PixelWidth;
 | |
|   *PixelHeight  = BmpHeader->PixelHeight;
 | |
| 
 | |
|   //
 | |
|   // Convert image from BMP to Blt buffer format
 | |
|   //
 | |
|   BltBuffer = *GopBlt;
 | |
|   for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
 | |
|     Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
 | |
|     for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
 | |
|       switch (BmpHeader->BitPerPixel) {
 | |
|       case 1:
 | |
|         //
 | |
|         // Convert 1-bit (2 colors) BMP to 24-bit color
 | |
|         //
 | |
|         for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
 | |
|           Blt->Red    = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
 | |
|           Blt->Green  = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
 | |
|           Blt->Blue   = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
 | |
|           Blt++;
 | |
|           Width++;
 | |
|         }
 | |
| 
 | |
|         Blt--;
 | |
|         Width--;
 | |
|         break;
 | |
| 
 | |
|       case 4:
 | |
|         //
 | |
|         // Convert 4-bit (16 colors) BMP Palette to 24-bit color
 | |
|         //
 | |
|         Index       = (*Image) >> 4;
 | |
|         Blt->Red    = BmpColorMap[Index].Red;
 | |
|         Blt->Green  = BmpColorMap[Index].Green;
 | |
|         Blt->Blue   = BmpColorMap[Index].Blue;
 | |
|         if (Width < (BmpHeader->PixelWidth - 1)) {
 | |
|           Blt++;
 | |
|           Width++;
 | |
|           Index       = (*Image) & 0x0f;
 | |
|           Blt->Red    = BmpColorMap[Index].Red;
 | |
|           Blt->Green  = BmpColorMap[Index].Green;
 | |
|           Blt->Blue   = BmpColorMap[Index].Blue;
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|       case 8:
 | |
|         //
 | |
|         // Convert 8-bit (256 colors) BMP Palette to 24-bit color
 | |
|         //
 | |
|         Blt->Red    = BmpColorMap[*Image].Red;
 | |
|         Blt->Green  = BmpColorMap[*Image].Green;
 | |
|         Blt->Blue   = BmpColorMap[*Image].Blue;
 | |
|         break;
 | |
| 
 | |
|       case 24:
 | |
|         //
 | |
|         // It is 24-bit BMP.
 | |
|         //
 | |
|         Blt->Blue   = *Image++;
 | |
|         Blt->Green  = *Image++;
 | |
|         Blt->Red    = *Image;
 | |
|         break;
 | |
| 
 | |
|       case 32:
 | |
|         //
 | |
|         // it is 32-bit BMP. Skip pixel's highest byte
 | |
|         //
 | |
|         Blt->Blue  = *Image++;
 | |
|         Blt->Green = *Image++;
 | |
|         Blt->Red   = *Image++;
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         //
 | |
|         // Other bit format BMP is not supported.
 | |
|         //
 | |
|         if (IsAllocated) {
 | |
|           FreePool (*GopBlt);
 | |
|           *GopBlt = NULL;
 | |
|         }
 | |
|         return EFI_UNSUPPORTED;
 | |
|       };
 | |
| 
 | |
|     }
 | |
| 
 | |
|     ImageIndex = (UINTN) (Image - ImageHeader);
 | |
|     if ((ImageIndex % 4) != 0) {
 | |
|       //
 | |
|       // Bmp Image starts each row on a 32-bit boundary!
 | |
|       //
 | |
|       Image = Image + (4 - (ImageIndex % 4));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   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;
 | |
| 
 | |
|   ImagePayload = (DISPLAY_DISPLAY_PAYLOAD *)(CapsuleHeader + 1);
 | |
|   PayloadSize = (UINTN)(CapsuleHeader->CapsuleImageSize - sizeof(EFI_CAPSULE_HEADER));
 | |
| 
 | |
|   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 = ConvertBmpToGopBlt (
 | |
|              ImagePayload + 1,
 | |
|              PayloadSize - sizeof(DISPLAY_DISPLAY_PAYLOAD),
 | |
|              (VOID **)&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 < (UINTN)(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 >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
 | |
|       DEBUG((DEBUG_VERBOSE, "    UpdateHardwareInstance - 0x%lx\n", ImageHeader->UpdateHardwareInstance));
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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]  AreAllImagesProcessed If all the FMP images in the capsule are processed.
 | |
| 
 | |
|   @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
 | |
| ProcessFmpCapsuleImage (
 | |
|   IN EFI_CAPSULE_HEADER  *CapsuleHeader,
 | |
|   OUT BOOLEAN            *AreAllImagesProcessed
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                                    Status;
 | |
|   EFI_STATUS                                    StatusEsrt;
 | |
|   EFI_STATUS                                    StatusRet;
 | |
|   EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
 | |
|   EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader;
 | |
|   UINT8                                         *Image;
 | |
|   EFI_HANDLE                                    ImageHandle;
 | |
|   UINT64                                        *ItemOffsetList;
 | |
|   UINT32                                        ItemNum;
 | |
|   UINTN                                         Index;
 | |
|   UINTN                                         ExitDataSize;
 | |
|   EFI_HANDLE                                    *HandleBuffer;
 | |
|   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
 | |
|   UINTN                                         NumberOfHandles;
 | |
|   UINTN                                         DescriptorSize;
 | |
|   UINT8                                         FmpImageInfoCount;
 | |
|   UINT32                                        FmpImageInfoDescriptorVer;
 | |
|   UINTN                                         ImageInfoSize;
 | |
|   UINT32                                        PackageVersion;
 | |
|   CHAR16                                        *PackageVersionName;
 | |
|   CHAR16                                        *AbortReason;
 | |
|   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
 | |
|   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *TempFmpImageInfo;
 | |
|   UINTN                                         DriverLen;
 | |
|   UINTN                                         Index1;
 | |
|   UINTN                                         Index2;
 | |
|   MEMMAP_DEVICE_PATH                            MemMapNode;
 | |
|   EFI_DEVICE_PATH_PROTOCOL                      *DriverDevicePath;
 | |
|   ESRT_MANAGEMENT_PROTOCOL                      *EsrtProtocol;
 | |
|   EFI_SYSTEM_RESOURCE_ENTRY                     EsrtEntry;
 | |
|   VOID                                          *VendorCode;
 | |
| 
 | |
|   if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
 | |
|     return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), AreAllImagesProcessed);
 | |
|   }
 | |
| 
 | |
|   ASSERT(AreAllImagesProcessed != NULL);
 | |
| 
 | |
|   Status           = EFI_SUCCESS;
 | |
|   StatusRet        = EFI_NOT_FOUND;
 | |
|   HandleBuffer     = NULL;
 | |
|   ExitDataSize     = 0;
 | |
|   DriverDevicePath = NULL;
 | |
|   EsrtProtocol     = NULL;
 | |
|   *AreAllImagesProcessed = 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) {
 | |
|     *AreAllImagesProcessed = TRUE;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Update corresponding ESRT entry LastAttemp Status
 | |
|   //
 | |
|   Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     EsrtProtocol = NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // 1. Try to load & start all the drivers within capsule
 | |
|   //
 | |
|   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)CapsuleHeader;
 | |
|   MemMapNode.EndingAddress   = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)CapsuleHeader + CapsuleHeader->CapsuleImageSize - 1);
 | |
| 
 | |
|   DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);
 | |
|   if (DriverDevicePath == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   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];
 | |
|     }
 | |
| 
 | |
|     DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage ...\n"));
 | |
|     Status = gBS->LoadImage(
 | |
|                     FALSE,
 | |
|                     gImageHandle,
 | |
|                     DriverDevicePath,
 | |
|                     (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],
 | |
|                     DriverLen,
 | |
|                     &ImageHandle
 | |
|                     );
 | |
|     DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage - %r\n", Status));
 | |
|     if (EFI_ERROR(Status)) {
 | |
|       StatusRet = Status;
 | |
|       goto EXIT;
 | |
|     }
 | |
| 
 | |
|     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));
 | |
|       StatusRet = Status;
 | |
|       goto EXIT;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // 2. Route payload to right FMP instance
 | |
|   //
 | |
|   DEBUG((DEBUG_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));
 | |
| 
 | |
|   Status = gBS->LocateHandleBuffer (
 | |
|                   ByProtocol,
 | |
|                   &gEfiFirmwareManagementProtocolGuid,
 | |
|                   NULL,
 | |
|                   &NumberOfHandles,
 | |
|                   &HandleBuffer
 | |
|                   );
 | |
| 
 | |
|   if (!EFI_ERROR(Status)) {
 | |
|     for(Index1 = 0; Index1 < NumberOfHandles; Index1++) {
 | |
|       Status = gBS->HandleProtocol(
 | |
|                       HandleBuffer[Index1],
 | |
|                       &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 = NULL;
 | |
|       FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
 | |
|       if (FmpImageInfoBuf == NULL) {
 | |
|         StatusRet = EFI_OUT_OF_RESOURCES;
 | |
|         goto EXIT;
 | |
|       }
 | |
| 
 | |
|       PackageVersionName = NULL;
 | |
|       Status = Fmp->GetImageInfo (
 | |
|                       Fmp,
 | |
|                       &ImageInfoSize,               // ImageInfoSize
 | |
|                       FmpImageInfoBuf,              // ImageInfo
 | |
|                       &FmpImageInfoDescriptorVer,   // DescriptorVersion
 | |
|                       &FmpImageInfoCount,           // DescriptorCount
 | |
|                       &DescriptorSize,              // DescriptorSize
 | |
|                       &PackageVersion,              // PackageVersion
 | |
|                       &PackageVersionName           // PackageVersionName
 | |
|                       );
 | |
| 
 | |
|       //
 | |
|       // If FMP GetInformation interface failed, skip this resource
 | |
|       //
 | |
|       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);
 | |
|       }
 | |
| 
 | |
|       TempFmpImageInfo = FmpImageInfoBuf;
 | |
|       for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {
 | |
|         //
 | |
|         // 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]);
 | |
| 
 | |
|           if (IsFmpCapsuleProcessed(CapsuleHeader, Index - FmpCapsuleHeader->EmbeddedDriverCount, ImageHeader)) {
 | |
|             DEBUG((DEBUG_INFO, "FMP Capsule already processed (%g):", CapsuleHeader));
 | |
|             DEBUG((DEBUG_INFO, "ImageTypeId - %g, ", ImageHeader->UpdateImageTypeId));
 | |
|             DEBUG((DEBUG_INFO, "PayloadIndex - 0x%x, ImageIndex - 0x%x\n", Index - FmpCapsuleHeader->EmbeddedDriverCount, ImageHeader->UpdateImageIndex));
 | |
|             continue;
 | |
|           }
 | |
| 
 | |
|           if (CompareGuid(&ImageHeader->UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId) &&
 | |
|               ImageHeader->UpdateImageIndex == TempFmpImageInfo->ImageIndex) {
 | |
|             AbortReason = NULL;
 | |
|             if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
 | |
|               if(ImageHeader->UpdateHardwareInstance != 0){
 | |
|                 //
 | |
|                 // FMP Version is >=2 & UpdateHardwareInstance Skip 2 case
 | |
|                 //  1. FMP Image info Version < 3
 | |
|                 //  2. HardwareInstance doesn't match
 | |
|                 //
 | |
|                 if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION ||
 | |
|                    ImageHeader->UpdateHardwareInstance != TempFmpImageInfo->HardwareInstance) {
 | |
|                   continue;
 | |
|                 }
 | |
|               }
 | |
|               Image = (UINT8 *)(ImageHeader + 1);
 | |
|             } else {
 | |
|               //
 | |
|               // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
 | |
|               // Header should exclude UpdateHardwareInstance field
 | |
|               //
 | |
|               Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
 | |
|             }
 | |
| 
 | |
|             if (ImageHeader->UpdateVendorCodeSize == 0) {
 | |
|               VendorCode = NULL;
 | |
|             } else {
 | |
|               VendorCode = Image + ImageHeader->UpdateImageSize;
 | |
|             }
 | |
|             DEBUG((DEBUG_INFO, "Fmp->SetImage ...\n"));
 | |
|             Status = Fmp->SetImage(
 | |
|                             Fmp,
 | |
|                             ImageHeader->UpdateImageIndex,          // ImageIndex
 | |
|                             Image,                                  // Image
 | |
|                             ImageHeader->UpdateImageSize,           // ImageSize
 | |
|                             VendorCode,                                   // VendorCode
 | |
|                             Update_Image_Progress,                  // Progress
 | |
|                             &AbortReason                            // AbortReason
 | |
|                             );
 | |
|             DEBUG((DEBUG_INFO, "Fmp->SetImage - %r\n", Status));
 | |
|             if (AbortReason != NULL) {
 | |
|               DEBUG ((DEBUG_ERROR, "%s\n", AbortReason));
 | |
|               FreePool(AbortReason);
 | |
|             }
 | |
|             RecordFmpCapsuleStatusVariable(
 | |
|               CapsuleHeader,                                 // CapsuleGuid
 | |
|               Status,                                        // CapsuleStatus
 | |
|               Index - FmpCapsuleHeader->EmbeddedDriverCount, // PayloadIndex
 | |
|               ImageHeader                                    // ImageHeader
 | |
|               );
 | |
|             if (StatusRet != EFI_SUCCESS) {
 | |
|               StatusRet = Status;
 | |
|             }
 | |
|             //
 | |
|             // Update EsrtEntry For V1, V2 FMP instance. V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
 | |
|             //
 | |
|             if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION && EsrtProtocol != NULL) {
 | |
|                StatusEsrt = EsrtProtocol->GetEsrtEntry(&TempFmpImageInfo->ImageTypeId, &EsrtEntry);
 | |
|                if (!EFI_ERROR(StatusEsrt)){
 | |
|                  if (!EFI_ERROR(Status)) {
 | |
|                    EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
 | |
|                  } else {
 | |
|                    EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
 | |
|                  }
 | |
|                  EsrtEntry.LastAttemptVersion = 0;
 | |
|                  EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);
 | |
|                }
 | |
|              }
 | |
|           }
 | |
|         }
 | |
|         //
 | |
|         // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
 | |
|         //
 | |
|         TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);
 | |
|       }
 | |
|       FreePool(FmpImageInfoBuf);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // final check for AreAllImagesProcessed
 | |
|   //
 | |
|   *AreAllImagesProcessed = TRUE;
 | |
|   for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
 | |
|     ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
 | |
| 
 | |
|     if (!IsFmpCapsuleProcessed(CapsuleHeader, Index - FmpCapsuleHeader->EmbeddedDriverCount, ImageHeader)) {
 | |
|       *AreAllImagesProcessed = FALSE;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| EXIT:
 | |
| 
 | |
|   if (HandleBuffer != NULL) {
 | |
|     FreePool(HandleBuffer);
 | |
|   }
 | |
| 
 | |
|   if (DriverDevicePath != NULL) {
 | |
|     FreePool(DriverDevicePath);
 | |
|   }
 | |
| 
 | |
|   return StatusRet;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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_TABLE  *Esrt;
 | |
|   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;
 | |
| 
 | |
|   //
 | |
|   // 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 ESRT configuration table
 | |
|   //
 | |
|   if (!EsrtGuidFound) {
 | |
|     Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
 | |
|     if (!EFI_ERROR(Status)) {
 | |
|       ASSERT (Esrt != NULL);
 | |
|       EsrtEntry = (VOID *)(Esrt + 1);
 | |
|       for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
 | |
|         if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
 | |
|           EsrtGuidFound = TRUE;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   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;
 | |
|   }
 | |
| 
 | |
|   if (IsFmpCapsule(CapsuleHeader)) {
 | |
|     //
 | |
|     // 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.
 | |
| 
 | |
|   @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
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                   Status;
 | |
|   BOOLEAN                      AreAllImagesProcessed;
 | |
| 
 | |
|   if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {
 | |
|     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)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Press EFI FMP Capsule
 | |
|     //
 | |
|     DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));
 | |
|     Status = ProcessFmpCapsuleImage(CapsuleHeader, &AreAllImagesProcessed);
 | |
|     DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
 | |
| 
 | |
|     if (!AreAllImagesProcessed) {
 | |
|       mAreAllImagesProcessed = FALSE;
 | |
|     }
 | |
| 
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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_EVENT     EndOfDxeEvent;
 | |
|   EFI_STATUS    Status;
 | |
| 
 | |
|   Status = gBS->CreateEventEx (
 | |
|                   EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_CALLBACK,
 | |
|                   DxeCapsuleLibEndOfDxe,
 | |
|                   NULL,
 | |
|                   &gEfiEndOfDxeEventGroupGuid,
 | |
|                   &EndOfDxeEvent
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   InitCapsuleVariable();
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |