Home | History | Annotate | Download | only in DxeCapsuleLibFmp
      1 /** @file
      2   DXE capsule library.
      3 
      4   Caution: This module requires additional review when modified.
      5   This module will have external input - capsule image.
      6   This external input must be validated carefully to avoid security issue like
      7   buffer overflow, integer overflow.
      8 
      9   SupportCapsuleImage(), ProcessCapsuleImage(), IsValidCapsuleHeader(),
     10   ValidateFmpCapsule(), DisplayCapsuleImage(), ConvertBmpToGopBlt() will
     11   receive untrusted input and do basic validation.
     12 
     13   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
     14   This program and the accompanying materials
     15   are licensed and made available under the terms and conditions of the BSD License
     16   which accompanies this distribution.  The full text of the license may be found at
     17   http://opensource.org/licenses/bsd-license.php
     18 
     19   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     20   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     21 
     22 **/
     23 
     24 #include <PiDxe.h>
     25 
     26 #include <IndustryStandard/Bmp.h>
     27 #include <IndustryStandard/WindowsUxCapsule.h>
     28 
     29 #include <Guid/FmpCapsule.h>
     30 #include <Guid/SystemResourceTable.h>
     31 #include <Guid/EventGroup.h>
     32 
     33 #include <Library/BaseLib.h>
     34 #include <Library/DebugLib.h>
     35 #include <Library/BaseMemoryLib.h>
     36 #include <Library/DxeServicesTableLib.h>
     37 #include <Library/UefiBootServicesTableLib.h>
     38 #include <Library/UefiRuntimeServicesTableLib.h>
     39 #include <Library/MemoryAllocationLib.h>
     40 #include <Library/CapsuleLib.h>
     41 #include <Library/DevicePathLib.h>
     42 #include <Library/UefiLib.h>
     43 #include <Library/PcdLib.h>
     44 
     45 #include <Protocol/GraphicsOutput.h>
     46 #include <Protocol/EsrtManagement.h>
     47 #include <Protocol/FirmwareManagement.h>
     48 #include <Protocol/DevicePath.h>
     49 
     50 EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable              = NULL;
     51 BOOLEAN                   mIsVirtualAddrConverted  = FALSE;
     52 BOOLEAN                   mDxeCapsuleLibEndOfDxe   = FALSE;
     53 
     54 /**
     55   Initialize capsule related variables.
     56 **/
     57 VOID
     58 InitCapsuleVariable (
     59   VOID
     60   );
     61 
     62 /**
     63   Record capsule status variable.
     64 
     65   @param[in] CapsuleHeader  The capsule image header
     66   @param[in] CapsuleStatus  The capsule process stauts
     67 
     68   @retval EFI_SUCCESS          The capsule status variable is recorded.
     69   @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
     70 **/
     71 EFI_STATUS
     72 RecordCapsuleStatusVariable (
     73   IN EFI_CAPSULE_HEADER                           *CapsuleHeader,
     74   IN EFI_STATUS                                   CapsuleStatus
     75   );
     76 
     77 /**
     78   Record FMP capsule status variable.
     79 
     80   @param[in] CapsuleHeader  The capsule image header
     81   @param[in] CapsuleStatus  The capsule process stauts
     82   @param[in] PayloadIndex   FMP payload index
     83   @param[in] ImageHeader    FMP image header
     84   @param[in] FmpDevicePath  DevicePath associated with the FMP producer
     85 
     86   @retval EFI_SUCCESS          The capsule status variable is recorded.
     87   @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
     88 **/
     89 EFI_STATUS
     90 RecordFmpCapsuleStatusVariable (
     91   IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
     92   IN EFI_STATUS                                    CapsuleStatus,
     93   IN UINTN                                         PayloadIndex,
     94   IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader,
     95   IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath OPTIONAL
     96   );
     97 
     98 /**
     99   Function indicate the current completion progress of the firmware
    100   update. Platform may override with own specific progress function.
    101 
    102   @param[in]  Completion    A value between 1 and 100 indicating the current completion progress of the firmware update
    103 
    104   @retval EFI_SUCESS    Input capsule is a correct FMP capsule.
    105 **/
    106 EFI_STATUS
    107 EFIAPI
    108 Update_Image_Progress (
    109   IN UINTN  Completion
    110   )
    111 {
    112   return EFI_SUCCESS;
    113 }
    114 
    115 /**
    116   Return if this CapsuleGuid is a FMP capsule GUID or not.
    117 
    118   @param[in] CapsuleGuid A pointer to EFI_GUID
    119 
    120   @retval TRUE  It is a FMP capsule GUID.
    121   @retval FALSE It is not a FMP capsule GUID.
    122 **/
    123 BOOLEAN
    124 IsFmpCapsuleGuid (
    125   IN EFI_GUID  *CapsuleGuid
    126   )
    127 {
    128   if (CompareGuid(&gEfiFmpCapsuleGuid, CapsuleGuid)) {
    129     return TRUE;
    130   }
    131 
    132   return FALSE;
    133 }
    134 
    135 /**
    136   Validate if it is valid capsule header
    137 
    138   Caution: This function may receive untrusted input.
    139 
    140   This function assumes the caller provided correct CapsuleHeader pointer
    141   and CapsuleSize.
    142 
    143   This function validates the fields in EFI_CAPSULE_HEADER.
    144 
    145   @param[in]  CapsuleHeader    Points to a capsule header.
    146   @param[in]  CapsuleSize      Size of the whole capsule image.
    147 
    148 **/
    149 BOOLEAN
    150 IsValidCapsuleHeader (
    151   IN EFI_CAPSULE_HEADER  *CapsuleHeader,
    152   IN UINT64              CapsuleSize
    153   )
    154 {
    155   if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {
    156     return FALSE;
    157   }
    158   if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
    159     return FALSE;
    160   }
    161   return TRUE;
    162 }
    163 
    164 /**
    165   Validate Fmp capsules layout.
    166 
    167   Caution: This function may receive untrusted input.
    168 
    169   This function assumes the caller validated the capsule by using
    170   IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
    171   The capsule buffer size is CapsuleHeader->CapsuleImageSize.
    172 
    173   This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
    174   and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
    175 
    176   This function need support nested FMP capsule.
    177 
    178   @param[in]   CapsuleHeader        Points to a capsule header.
    179   @param[out]  EmbeddedDriverCount  The EmbeddedDriverCount in the FMP capsule.
    180 
    181   @retval EFI_SUCESS             Input capsule is a correct FMP capsule.
    182   @retval EFI_INVALID_PARAMETER  Input capsule is not a correct FMP capsule.
    183 **/
    184 EFI_STATUS
    185 ValidateFmpCapsule (
    186   IN EFI_CAPSULE_HEADER  *CapsuleHeader,
    187   OUT UINT16             *EmbeddedDriverCount OPTIONAL
    188   )
    189 {
    190   EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
    191   UINT8                                        *EndOfCapsule;
    192   EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
    193   UINT8                                        *EndOfPayload;
    194   UINT64                                       *ItemOffsetList;
    195   UINT32                                       ItemNum;
    196   UINTN                                        Index;
    197   UINTN                                        FmpCapsuleSize;
    198   UINTN                                        FmpCapsuleHeaderSize;
    199   UINT64                                       FmpImageSize;
    200   UINTN                                        FmpImageHeaderSize;
    201 
    202   if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
    203     return ValidateFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), EmbeddedDriverCount);
    204   }
    205 
    206   if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
    207     DEBUG((DEBUG_ERROR, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));
    208     return EFI_INVALID_PARAMETER;
    209   }
    210 
    211   FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
    212   EndOfCapsule     = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;
    213   FmpCapsuleSize   = (UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader;
    214 
    215   if (FmpCapsuleSize < sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER)) {
    216     DEBUG((DEBUG_ERROR, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize));
    217     return EFI_INVALID_PARAMETER;
    218   }
    219 
    220   // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
    221   if (FmpCapsuleHeader->Version != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
    222     DEBUG((DEBUG_ERROR, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader->Version));
    223     return EFI_INVALID_PARAMETER;
    224   }
    225   ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
    226 
    227   // No overflow
    228   ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
    229 
    230   if ((FmpCapsuleSize - sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER))/sizeof(UINT64) < ItemNum) {
    231     DEBUG((DEBUG_ERROR, "ItemNum(0x%x) too big\n", ItemNum));
    232     return EFI_INVALID_PARAMETER;
    233   }
    234   FmpCapsuleHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER) + sizeof(UINT64)*ItemNum;
    235 
    236   // Check ItemOffsetList
    237   for (Index = 0; Index < ItemNum; Index++) {
    238     if (ItemOffsetList[Index] >= FmpCapsuleSize) {
    239       DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleSize));
    240       return EFI_INVALID_PARAMETER;
    241     }
    242     if (ItemOffsetList[Index] < FmpCapsuleHeaderSize) {
    243       DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleHeaderSize));
    244       return EFI_INVALID_PARAMETER;
    245     }
    246     //
    247     // All the address in ItemOffsetList must be stored in ascending order
    248     //
    249     if (Index > 0) {
    250       if (ItemOffsetList[Index] <= ItemOffsetList[Index - 1]) {
    251         DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index, ItemOffsetList[Index], Index, ItemOffsetList[Index - 1]));
    252         return EFI_INVALID_PARAMETER;
    253       }
    254     }
    255   }
    256 
    257   // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
    258   for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
    259     ImageHeader  = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
    260     if (Index == ItemNum - 1) {
    261       EndOfPayload = (UINT8 *)((UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader);
    262     } else {
    263       EndOfPayload = (UINT8 *)(UINTN)ItemOffsetList[Index+1];
    264     }
    265     FmpImageSize = (UINTN)EndOfPayload - ItemOffsetList[Index];
    266 
    267     if (FmpImageSize < OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance)) {
    268       DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize));
    269       return EFI_INVALID_PARAMETER;
    270     }
    271     FmpImageHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER);
    272     if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) ||
    273         (ImageHeader->Version < 1)) {
    274       DEBUG((DEBUG_ERROR, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader->Version));
    275       return EFI_INVALID_PARAMETER;
    276     }
    277     if (ImageHeader->Version < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
    278       FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
    279     }
    280 
    281     // No overflow
    282     if (FmpImageSize != (UINT64)FmpImageHeaderSize + (UINT64)ImageHeader->UpdateImageSize + (UINT64)ImageHeader->UpdateVendorCodeSize) {
    283       DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize, ImageHeader->UpdateImageSize, ImageHeader->UpdateVendorCodeSize));
    284       return EFI_INVALID_PARAMETER;
    285     }
    286   }
    287 
    288   if (ItemNum == 0) {
    289     //
    290     // No driver & payload element in FMP
    291     //
    292     EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1);
    293     if (EndOfPayload != EndOfCapsule) {
    294       DEBUG((DEBUG_ERROR, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload, EndOfCapsule));
    295       return EFI_INVALID_PARAMETER;
    296     }
    297     return EFI_UNSUPPORTED;
    298   }
    299 
    300   if (EmbeddedDriverCount != NULL) {
    301     *EmbeddedDriverCount = FmpCapsuleHeader->EmbeddedDriverCount;
    302   }
    303 
    304   return EFI_SUCCESS;
    305 }
    306 
    307 /**
    308   Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
    309   is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
    310   buffer is passed in it will be used if it is big enough.
    311 
    312   Caution: This function may receive untrusted input.
    313 
    314   @param[in]       BmpImage      Pointer to BMP file
    315   @param[in]       BmpImageSize  Number of bytes in BmpImage
    316   @param[in, out]  GopBlt        Buffer containing GOP version of BmpImage.
    317   @param[in, out]  GopBltSize    Size of GopBlt in bytes.
    318   @param[out]      PixelHeight   Height of GopBlt/BmpImage in pixels
    319   @param[out]      PixelWidth    Width of GopBlt/BmpImage in pixels
    320 
    321   @retval EFI_SUCCESS           GopBlt and GopBltSize are returned.
    322   @retval EFI_UNSUPPORTED       BmpImage is not a valid *.BMP image
    323   @retval EFI_BUFFER_TOO_SMALL  The passed in GopBlt buffer is not big enough.
    324                                 GopBltSize will contain the required size.
    325   @retval EFI_OUT_OF_RESOURCES  No enough buffer to allocate.
    326 
    327 **/
    328 STATIC
    329 EFI_STATUS
    330 ConvertBmpToGopBlt (
    331   IN     VOID      *BmpImage,
    332   IN     UINTN     BmpImageSize,
    333   IN OUT VOID      **GopBlt,
    334   IN OUT UINTN     *GopBltSize,
    335      OUT UINTN     *PixelHeight,
    336      OUT UINTN     *PixelWidth
    337   )
    338 {
    339   UINT8                         *Image;
    340   UINT8                         *ImageHeader;
    341   BMP_IMAGE_HEADER              *BmpHeader;
    342   BMP_COLOR_MAP                 *BmpColorMap;
    343   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
    344   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
    345   UINT64                        BltBufferSize;
    346   UINTN                         Index;
    347   UINTN                         Height;
    348   UINTN                         Width;
    349   UINTN                         ImageIndex;
    350   UINT32                        DataSizePerLine;
    351   BOOLEAN                       IsAllocated;
    352   UINT32                        ColorMapNum;
    353 
    354   if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {
    355     return EFI_INVALID_PARAMETER;
    356   }
    357 
    358   BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
    359 
    360   if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
    361     return EFI_UNSUPPORTED;
    362   }
    363 
    364   //
    365   // Doesn't support compress.
    366   //
    367   if (BmpHeader->CompressionType != 0) {
    368     return EFI_UNSUPPORTED;
    369   }
    370 
    371   //
    372   // Only support BITMAPINFOHEADER format.
    373   // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
    374   //
    375   if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {
    376     return EFI_UNSUPPORTED;
    377   }
    378 
    379   //
    380   // The data size in each line must be 4 byte alignment.
    381   //
    382   DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);
    383   BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);
    384   if (BltBufferSize > (UINT32) ~0) {
    385     return EFI_INVALID_PARAMETER;
    386   }
    387 
    388   if ((BmpHeader->Size != BmpImageSize) ||
    389       (BmpHeader->Size < BmpHeader->ImageOffset) ||
    390       (BmpHeader->Size - BmpHeader->ImageOffset !=  BmpHeader->PixelHeight * DataSizePerLine)) {
    391     return EFI_INVALID_PARAMETER;
    392   }
    393 
    394   //
    395   // Calculate Color Map offset in the image.
    396   //
    397   Image       = BmpImage;
    398   BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
    399   if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
    400     return EFI_INVALID_PARAMETER;
    401   }
    402 
    403   if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
    404     switch (BmpHeader->BitPerPixel) {
    405       case 1:
    406         ColorMapNum = 2;
    407         break;
    408       case 4:
    409         ColorMapNum = 16;
    410         break;
    411       case 8:
    412         ColorMapNum = 256;
    413         break;
    414       default:
    415         ColorMapNum = 0;
    416         break;
    417       }
    418     //
    419     // BMP file may has padding data between the bmp header section and the bmp data section.
    420     //
    421     if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {
    422       return EFI_INVALID_PARAMETER;
    423     }
    424   }
    425 
    426   //
    427   // Calculate graphics image data address in the image
    428   //
    429   Image         = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
    430   ImageHeader   = Image;
    431 
    432   //
    433   // Calculate the BltBuffer needed size.
    434   //
    435   BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
    436   //
    437   // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
    438   //
    439   if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
    440     return EFI_UNSUPPORTED;
    441   }
    442   BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
    443 
    444   IsAllocated   = FALSE;
    445   if (*GopBlt == NULL) {
    446     //
    447     // GopBlt is not allocated by caller.
    448     //
    449     *GopBltSize = (UINTN) BltBufferSize;
    450     *GopBlt     = AllocatePool (*GopBltSize);
    451     IsAllocated = TRUE;
    452     if (*GopBlt == NULL) {
    453       return EFI_OUT_OF_RESOURCES;
    454     }
    455   } else {
    456     //
    457     // GopBlt has been allocated by caller.
    458     //
    459     if (*GopBltSize < (UINTN) BltBufferSize) {
    460       *GopBltSize = (UINTN) BltBufferSize;
    461       return EFI_BUFFER_TOO_SMALL;
    462     }
    463   }
    464 
    465   *PixelWidth   = BmpHeader->PixelWidth;
    466   *PixelHeight  = BmpHeader->PixelHeight;
    467 
    468   //
    469   // Convert image from BMP to Blt buffer format
    470   //
    471   BltBuffer = *GopBlt;
    472   for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
    473     Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
    474     for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
    475       switch (BmpHeader->BitPerPixel) {
    476       case 1:
    477         //
    478         // Convert 1-bit (2 colors) BMP to 24-bit color
    479         //
    480         for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
    481           Blt->Red    = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
    482           Blt->Green  = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
    483           Blt->Blue   = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
    484           Blt++;
    485           Width++;
    486         }
    487 
    488         Blt--;
    489         Width--;
    490         break;
    491 
    492       case 4:
    493         //
    494         // Convert 4-bit (16 colors) BMP Palette to 24-bit color
    495         //
    496         Index       = (*Image) >> 4;
    497         Blt->Red    = BmpColorMap[Index].Red;
    498         Blt->Green  = BmpColorMap[Index].Green;
    499         Blt->Blue   = BmpColorMap[Index].Blue;
    500         if (Width < (BmpHeader->PixelWidth - 1)) {
    501           Blt++;
    502           Width++;
    503           Index       = (*Image) & 0x0f;
    504           Blt->Red    = BmpColorMap[Index].Red;
    505           Blt->Green  = BmpColorMap[Index].Green;
    506           Blt->Blue   = BmpColorMap[Index].Blue;
    507         }
    508         break;
    509 
    510       case 8:
    511         //
    512         // Convert 8-bit (256 colors) BMP Palette to 24-bit color
    513         //
    514         Blt->Red    = BmpColorMap[*Image].Red;
    515         Blt->Green  = BmpColorMap[*Image].Green;
    516         Blt->Blue   = BmpColorMap[*Image].Blue;
    517         break;
    518 
    519       case 24:
    520         //
    521         // It is 24-bit BMP.
    522         //
    523         Blt->Blue   = *Image++;
    524         Blt->Green  = *Image++;
    525         Blt->Red    = *Image;
    526         break;
    527 
    528       case 32:
    529         //
    530         // it is 32-bit BMP. Skip pixel's highest byte
    531         //
    532         Blt->Blue  = *Image++;
    533         Blt->Green = *Image++;
    534         Blt->Red   = *Image++;
    535         break;
    536 
    537       default:
    538         //
    539         // Other bit format BMP is not supported.
    540         //
    541         if (IsAllocated) {
    542           FreePool (*GopBlt);
    543           *GopBlt = NULL;
    544         }
    545         return EFI_UNSUPPORTED;
    546       };
    547 
    548     }
    549 
    550     ImageIndex = (UINTN) (Image - ImageHeader);
    551     if ((ImageIndex % 4) != 0) {
    552       //
    553       // Bmp Image starts each row on a 32-bit boundary!
    554       //
    555       Image = Image + (4 - (ImageIndex % 4));
    556     }
    557   }
    558 
    559   return EFI_SUCCESS;
    560 }
    561 
    562 
    563 /**
    564   Those capsules supported by the firmwares.
    565 
    566   Caution: This function may receive untrusted input.
    567 
    568   @param[in]  CapsuleHeader    Points to a capsule header.
    569 
    570   @retval EFI_SUCESS       Input capsule is supported by firmware.
    571   @retval EFI_UNSUPPORTED  Input capsule is not supported by the firmware.
    572 **/
    573 EFI_STATUS
    574 DisplayCapsuleImage (
    575   IN EFI_CAPSULE_HEADER  *CapsuleHeader
    576   )
    577 {
    578   DISPLAY_DISPLAY_PAYLOAD       *ImagePayload;
    579   UINTN                         PayloadSize;
    580   EFI_STATUS                    Status;
    581   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
    582   UINTN                         BltSize;
    583   UINTN                         Height;
    584   UINTN                         Width;
    585   EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;
    586 
    587   ImagePayload = (DISPLAY_DISPLAY_PAYLOAD *)(CapsuleHeader + 1);
    588   PayloadSize = (UINTN)(CapsuleHeader->CapsuleImageSize - sizeof(EFI_CAPSULE_HEADER));
    589 
    590   if (ImagePayload->Version != 1) {
    591     return EFI_UNSUPPORTED;
    592   }
    593   if (CalculateCheckSum8((UINT8 *)CapsuleHeader, CapsuleHeader->CapsuleImageSize) != 0) {
    594     return EFI_UNSUPPORTED;
    595   }
    596   //
    597   // Only Support Bitmap by now
    598   //
    599   if (ImagePayload->ImageType != 0) {
    600     return EFI_UNSUPPORTED;
    601   }
    602 
    603   //
    604   // Try to open GOP
    605   //
    606   Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
    607   if (EFI_ERROR (Status)) {
    608     Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&GraphicsOutput);
    609     if (EFI_ERROR(Status)) {
    610       return EFI_UNSUPPORTED;
    611     }
    612   }
    613 
    614   if (GraphicsOutput->Mode->Mode != ImagePayload->Mode) {
    615     return EFI_UNSUPPORTED;
    616   }
    617 
    618   Blt = NULL;
    619   Width = 0;
    620   Height = 0;
    621   Status = ConvertBmpToGopBlt (
    622              ImagePayload + 1,
    623              PayloadSize - sizeof(DISPLAY_DISPLAY_PAYLOAD),
    624              (VOID **)&Blt,
    625              &BltSize,
    626              &Height,
    627              &Width
    628              );
    629 
    630   if (EFI_ERROR (Status)) {
    631     return Status;
    632   }
    633 
    634   Status = GraphicsOutput->Blt (
    635                              GraphicsOutput,
    636                              Blt,
    637                              EfiBltBufferToVideo,
    638                              0,
    639                              0,
    640                              (UINTN) ImagePayload->OffsetX,
    641                              (UINTN) ImagePayload->OffsetY,
    642                              Width,
    643                              Height,
    644                              Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
    645                              );
    646 
    647   FreePool(Blt);
    648 
    649   return Status;
    650 }
    651 
    652 /**
    653   Dump FMP information.
    654 
    655   @param[in] ImageInfoSize       The size of ImageInfo, in bytes.
    656   @param[in] ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
    657   @param[in] DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
    658   @param[in] DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
    659   @param[in] DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
    660   @param[in] PackageVersion      The version of package.
    661   @param[in] PackageVersionName  The version name of package.
    662 **/
    663 VOID
    664 DumpFmpImageInfo (
    665   IN UINTN                           ImageInfoSize,
    666   IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
    667   IN UINT32                          DescriptorVersion,
    668   IN UINT8                           DescriptorCount,
    669   IN UINTN                           DescriptorSize,
    670   IN UINT32                          PackageVersion,
    671   IN CHAR16                          *PackageVersionName
    672   )
    673 {
    674   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
    675   UINTN                                         Index;
    676 
    677   DEBUG((DEBUG_VERBOSE, "  DescriptorVersion  - 0x%x\n", DescriptorVersion));
    678   DEBUG((DEBUG_VERBOSE, "  DescriptorCount    - 0x%x\n", DescriptorCount));
    679   DEBUG((DEBUG_VERBOSE, "  DescriptorSize     - 0x%x\n", DescriptorSize));
    680   DEBUG((DEBUG_VERBOSE, "  PackageVersion     - 0x%x\n", PackageVersion));
    681   DEBUG((DEBUG_VERBOSE, "  PackageVersionName - %s\n\n", PackageVersionName));
    682   CurrentImageInfo = ImageInfo;
    683   for (Index = 0; Index < DescriptorCount; Index++) {
    684     DEBUG((DEBUG_VERBOSE, "  ImageDescriptor (%d)\n", Index));
    685     DEBUG((DEBUG_VERBOSE, "    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex));
    686     DEBUG((DEBUG_VERBOSE, "    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId));
    687     DEBUG((DEBUG_VERBOSE, "    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId));
    688     DEBUG((DEBUG_VERBOSE, "    ImageIdName                 - %s\n", CurrentImageInfo->ImageIdName));
    689     DEBUG((DEBUG_VERBOSE, "    Version                     - 0x%x\n", CurrentImageInfo->Version));
    690     DEBUG((DEBUG_VERBOSE, "    VersionName                 - %s\n", CurrentImageInfo->VersionName));
    691     DEBUG((DEBUG_VERBOSE, "    Size                        - 0x%x\n", CurrentImageInfo->Size));
    692     DEBUG((DEBUG_VERBOSE, "    AttributesSupported         - 0x%lx\n", CurrentImageInfo->AttributesSupported));
    693     DEBUG((DEBUG_VERBOSE, "    AttributesSetting           - 0x%lx\n", CurrentImageInfo->AttributesSetting));
    694     DEBUG((DEBUG_VERBOSE, "    Compatibilities             - 0x%lx\n", CurrentImageInfo->Compatibilities));
    695     if (DescriptorVersion > 1) {
    696       DEBUG((DEBUG_VERBOSE, "    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion));
    697       if (DescriptorVersion > 2) {
    698         DEBUG((DEBUG_VERBOSE, "    LastAttemptVersion          - 0x%x\n", CurrentImageInfo->LastAttemptVersion));
    699         DEBUG((DEBUG_VERBOSE, "    LastAttemptStatus           - 0x%x\n", CurrentImageInfo->LastAttemptStatus));
    700         DEBUG((DEBUG_VERBOSE, "    HardwareInstance            - 0x%lx\n", CurrentImageInfo->HardwareInstance));
    701       }
    702     }
    703     //
    704     // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
    705     //
    706     CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
    707   }
    708 }
    709 
    710 /**
    711   Dump a non-nested FMP capsule.
    712 
    713   @param[in]  CapsuleHeader  A pointer to CapsuleHeader
    714 **/
    715 VOID
    716 DumpFmpCapsule (
    717   IN EFI_CAPSULE_HEADER                *CapsuleHeader
    718   )
    719 {
    720   EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
    721   EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader;
    722   UINTN                                         Index;
    723   UINT64                                        *ItemOffsetList;
    724 
    725   FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
    726 
    727   DEBUG((DEBUG_VERBOSE, "FmpCapsule:\n"));
    728   DEBUG((DEBUG_VERBOSE, "  Version                - 0x%x\n", FmpCapsuleHeader->Version));
    729   DEBUG((DEBUG_VERBOSE, "  EmbeddedDriverCount    - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount));
    730   DEBUG((DEBUG_VERBOSE, "  PayloadItemCount       - 0x%x\n", FmpCapsuleHeader->PayloadItemCount));
    731 
    732   ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
    733   for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
    734     DEBUG((DEBUG_VERBOSE, "  ItemOffsetList[%d]      - 0x%lx\n", Index, ItemOffsetList[Index]));
    735   }
    736   for (; Index < (UINTN)(FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount); Index++) {
    737     DEBUG((DEBUG_VERBOSE, "  ItemOffsetList[%d]      - 0x%lx\n", Index, ItemOffsetList[Index]));
    738     ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
    739 
    740     DEBUG((DEBUG_VERBOSE, "  ImageHeader:\n"));
    741     DEBUG((DEBUG_VERBOSE, "    Version                - 0x%x\n", ImageHeader->Version));
    742     DEBUG((DEBUG_VERBOSE, "    UpdateImageTypeId      - %g\n", &ImageHeader->UpdateImageTypeId));
    743     DEBUG((DEBUG_VERBOSE, "    UpdateImageIndex       - 0x%x\n", ImageHeader->UpdateImageIndex));
    744     DEBUG((DEBUG_VERBOSE, "    UpdateImageSize        - 0x%x\n", ImageHeader->UpdateImageSize));
    745     DEBUG((DEBUG_VERBOSE, "    UpdateVendorCodeSize   - 0x%x\n", ImageHeader->UpdateVendorCodeSize));
    746     if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
    747       DEBUG((DEBUG_VERBOSE, "    UpdateHardwareInstance - 0x%lx\n", ImageHeader->UpdateHardwareInstance));
    748     }
    749   }
    750 }
    751 
    752 /**
    753   Dump all FMP information.
    754 **/
    755 VOID
    756 DumpAllFmpInfo (
    757   VOID
    758   )
    759 {
    760   EFI_STATUS                                    Status;
    761   EFI_HANDLE                                    *HandleBuffer;
    762   UINTN                                         NumberOfHandles;
    763   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
    764   UINTN                                         Index;
    765   UINTN                                         ImageInfoSize;
    766   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
    767   UINT32                                        FmpImageInfoDescriptorVer;
    768   UINT8                                         FmpImageInfoCount;
    769   UINTN                                         DescriptorSize;
    770   UINT32                                        PackageVersion;
    771   CHAR16                                        *PackageVersionName;
    772 
    773   Status = gBS->LocateHandleBuffer (
    774                   ByProtocol,
    775                   &gEfiFirmwareManagementProtocolGuid,
    776                   NULL,
    777                   &NumberOfHandles,
    778                   &HandleBuffer
    779                   );
    780   if (EFI_ERROR(Status)) {
    781     return ;
    782   }
    783 
    784   for (Index = 0; Index < NumberOfHandles; Index++) {
    785     Status = gBS->HandleProtocol(
    786                     HandleBuffer[Index],
    787                     &gEfiFirmwareManagementProtocolGuid,
    788                     (VOID **)&Fmp
    789                     );
    790     if (EFI_ERROR(Status)) {
    791       continue;
    792     }
    793 
    794     ImageInfoSize = 0;
    795     Status = Fmp->GetImageInfo (
    796                     Fmp,
    797                     &ImageInfoSize,
    798                     NULL,
    799                     NULL,
    800                     NULL,
    801                     NULL,
    802                     NULL,
    803                     NULL
    804                     );
    805     if (Status != EFI_BUFFER_TOO_SMALL) {
    806       continue;
    807     }
    808 
    809     FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
    810     if (FmpImageInfoBuf == NULL) {
    811       continue;
    812     }
    813 
    814     PackageVersionName = NULL;
    815     Status = Fmp->GetImageInfo (
    816                     Fmp,
    817                     &ImageInfoSize,               // ImageInfoSize
    818                     FmpImageInfoBuf,              // ImageInfo
    819                     &FmpImageInfoDescriptorVer,   // DescriptorVersion
    820                     &FmpImageInfoCount,           // DescriptorCount
    821                     &DescriptorSize,              // DescriptorSize
    822                     &PackageVersion,              // PackageVersion
    823                     &PackageVersionName           // PackageVersionName
    824                     );
    825     if (EFI_ERROR(Status)) {
    826       FreePool(FmpImageInfoBuf);
    827       continue;
    828     }
    829 
    830     DEBUG((DEBUG_INFO, "FMP (%d) ImageInfo:\n", Index));
    831     DumpFmpImageInfo(
    832       ImageInfoSize,               // ImageInfoSize
    833       FmpImageInfoBuf,             // ImageInfo
    834       FmpImageInfoDescriptorVer,   // DescriptorVersion
    835       FmpImageInfoCount,           // DescriptorCount
    836       DescriptorSize,              // DescriptorSize
    837       PackageVersion,              // PackageVersion
    838       PackageVersionName           // PackageVersionName
    839       );
    840 
    841     if (PackageVersionName != NULL) {
    842       FreePool(PackageVersionName);
    843     }
    844 
    845     FreePool(FmpImageInfoBuf);
    846   }
    847 
    848   return ;
    849 }
    850 
    851 /**
    852   Get FMP handle by ImageTypeId and HardwareInstance.
    853 
    854   @param[in]     UpdateImageTypeId       Used to identify device firmware targeted by this update.
    855   @param[in]     UpdateHardwareInstance  The HardwareInstance to target with this update.
    856   @param[in,out] NoHandles               The number of handles returned in Buffer.
    857   @param[out]    Buffer[out]             A pointer to the buffer to return the requested array of handles.
    858 
    859   @retval EFI_SUCCESS            The array of handles was returned in Buffer, and the number of
    860                                  handles in Buffer was returned in NoHandles.
    861   @retval EFI_NOT_FOUND          No handles match the search.
    862   @retval EFI_OUT_OF_RESOURCES   There is not enough pool memory to store the matching results.
    863 **/
    864 EFI_STATUS
    865 GetFmpHandleBufferByType (
    866   IN     EFI_GUID                     *UpdateImageTypeId,
    867   IN     UINT64                       UpdateHardwareInstance,
    868   IN OUT UINTN                        *NoHandles,
    869   OUT    EFI_HANDLE                   **Buffer
    870   )
    871 {
    872   EFI_STATUS                                    Status;
    873   EFI_HANDLE                                    *HandleBuffer;
    874   UINTN                                         NumberOfHandles;
    875   EFI_HANDLE                                    *MatchedHandleBuffer;
    876   UINTN                                         MatchedNumberOfHandles;
    877   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
    878   UINTN                                         Index;
    879   UINTN                                         ImageInfoSize;
    880   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
    881   UINT32                                        FmpImageInfoDescriptorVer;
    882   UINT8                                         FmpImageInfoCount;
    883   UINTN                                         DescriptorSize;
    884   UINT32                                        PackageVersion;
    885   CHAR16                                        *PackageVersionName;
    886   UINTN                                         Index2;
    887   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *TempFmpImageInfo;
    888 
    889   *NoHandles = 0;
    890   *Buffer = NULL;
    891 
    892   Status = gBS->LocateHandleBuffer (
    893                   ByProtocol,
    894                   &gEfiFirmwareManagementProtocolGuid,
    895                   NULL,
    896                   &NumberOfHandles,
    897                   &HandleBuffer
    898                   );
    899   if (EFI_ERROR(Status)) {
    900     return Status;
    901   }
    902 
    903   MatchedNumberOfHandles = 0;
    904   MatchedHandleBuffer = AllocateZeroPool (sizeof(EFI_HANDLE) * NumberOfHandles);
    905   if (MatchedHandleBuffer == NULL) {
    906     FreePool (HandleBuffer);
    907     return EFI_OUT_OF_RESOURCES;
    908   }
    909 
    910   for (Index = 0; Index < NumberOfHandles; Index++) {
    911     Status = gBS->HandleProtocol(
    912                     HandleBuffer[Index],
    913                     &gEfiFirmwareManagementProtocolGuid,
    914                     (VOID **)&Fmp
    915                     );
    916     if (EFI_ERROR(Status)) {
    917       continue;
    918     }
    919 
    920     ImageInfoSize = 0;
    921     Status = Fmp->GetImageInfo (
    922                     Fmp,
    923                     &ImageInfoSize,
    924                     NULL,
    925                     NULL,
    926                     NULL,
    927                     NULL,
    928                     NULL,
    929                     NULL
    930                     );
    931     if (Status != EFI_BUFFER_TOO_SMALL) {
    932       continue;
    933     }
    934 
    935     FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
    936     if (FmpImageInfoBuf == NULL) {
    937       continue;
    938     }
    939 
    940     PackageVersionName = NULL;
    941     Status = Fmp->GetImageInfo (
    942                     Fmp,
    943                     &ImageInfoSize,               // ImageInfoSize
    944                     FmpImageInfoBuf,              // ImageInfo
    945                     &FmpImageInfoDescriptorVer,   // DescriptorVersion
    946                     &FmpImageInfoCount,           // DescriptorCount
    947                     &DescriptorSize,              // DescriptorSize
    948                     &PackageVersion,              // PackageVersion
    949                     &PackageVersionName           // PackageVersionName
    950                     );
    951     if (EFI_ERROR(Status)) {
    952       FreePool(FmpImageInfoBuf);
    953       continue;
    954     }
    955 
    956     if (PackageVersionName != NULL) {
    957       FreePool(PackageVersionName);
    958     }
    959 
    960     TempFmpImageInfo = FmpImageInfoBuf;
    961     for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {
    962       //
    963       // Check if this FMP instance matches
    964       //
    965       if (CompareGuid(UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId)) {
    966         if ((UpdateHardwareInstance == 0) ||
    967             ((FmpImageInfoDescriptorVer >= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) &&
    968              (UpdateHardwareInstance == TempFmpImageInfo->HardwareInstance))) {
    969           MatchedHandleBuffer[MatchedNumberOfHandles] = HandleBuffer[Index];
    970           MatchedNumberOfHandles++;
    971           break;
    972         }
    973       }
    974       TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);
    975     }
    976     FreePool(FmpImageInfoBuf);
    977   }
    978 
    979   if (MatchedNumberOfHandles == 0) {
    980     return EFI_NOT_FOUND;
    981   }
    982 
    983   *NoHandles = MatchedNumberOfHandles;
    984   *Buffer = MatchedHandleBuffer;
    985 
    986   return EFI_SUCCESS;
    987 }
    988 
    989 /**
    990   Return FmpImageInfoDescriptorVer by an FMP handle.
    991 
    992   @param[in]  Handle   A FMP handle.
    993 
    994   @return FmpImageInfoDescriptorVer associated with the FMP.
    995 **/
    996 UINT32
    997 GetFmpImageInfoDescriptorVer (
    998   IN EFI_HANDLE                                   Handle
    999   )
   1000 {
   1001   EFI_STATUS                                    Status;
   1002   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
   1003   UINTN                                         ImageInfoSize;
   1004   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
   1005   UINT32                                        FmpImageInfoDescriptorVer;
   1006   UINT8                                         FmpImageInfoCount;
   1007   UINTN                                         DescriptorSize;
   1008   UINT32                                        PackageVersion;
   1009   CHAR16                                        *PackageVersionName;
   1010 
   1011   Status = gBS->HandleProtocol(
   1012                   Handle,
   1013                   &gEfiFirmwareManagementProtocolGuid,
   1014                   (VOID **)&Fmp
   1015                   );
   1016   if (EFI_ERROR(Status)) {
   1017     return 0;
   1018   }
   1019 
   1020   ImageInfoSize = 0;
   1021   Status = Fmp->GetImageInfo (
   1022                   Fmp,
   1023                   &ImageInfoSize,
   1024                   NULL,
   1025                   NULL,
   1026                   NULL,
   1027                   NULL,
   1028                   NULL,
   1029                   NULL
   1030                   );
   1031   if (Status != EFI_BUFFER_TOO_SMALL) {
   1032     return 0;
   1033   }
   1034 
   1035   FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
   1036   if (FmpImageInfoBuf == NULL) {
   1037     return 0;
   1038   }
   1039 
   1040   PackageVersionName = NULL;
   1041   Status = Fmp->GetImageInfo (
   1042                   Fmp,
   1043                   &ImageInfoSize,               // ImageInfoSize
   1044                   FmpImageInfoBuf,              // ImageInfo
   1045                   &FmpImageInfoDescriptorVer,   // DescriptorVersion
   1046                   &FmpImageInfoCount,           // DescriptorCount
   1047                   &DescriptorSize,              // DescriptorSize
   1048                   &PackageVersion,              // PackageVersion
   1049                   &PackageVersionName           // PackageVersionName
   1050                   );
   1051   if (EFI_ERROR(Status)) {
   1052     FreePool(FmpImageInfoBuf);
   1053     return 0;
   1054   }
   1055   return FmpImageInfoDescriptorVer;
   1056 }
   1057 
   1058 /**
   1059   Set FMP image data.
   1060 
   1061   @param[in]  Handle        A FMP handle.
   1062   @param[in]  ImageHeader   The payload image header.
   1063   @param[in]  PayloadIndex  The index of the payload.
   1064 
   1065   @return The status of FMP->SetImage.
   1066 **/
   1067 EFI_STATUS
   1068 SetFmpImageData (
   1069   IN EFI_HANDLE                                   Handle,
   1070   IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,
   1071   IN UINTN                                        PayloadIndex
   1072   )
   1073 {
   1074   EFI_STATUS                                    Status;
   1075   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
   1076   UINT8                                         *Image;
   1077   VOID                                          *VendorCode;
   1078   CHAR16                                        *AbortReason;
   1079 
   1080   Status = gBS->HandleProtocol(
   1081                   Handle,
   1082                   &gEfiFirmwareManagementProtocolGuid,
   1083                   (VOID **)&Fmp
   1084                   );
   1085   if (EFI_ERROR(Status)) {
   1086     return Status;
   1087   }
   1088 
   1089   if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
   1090     Image = (UINT8 *)(ImageHeader + 1);
   1091   } else {
   1092     //
   1093     // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
   1094     // Header should exclude UpdateHardwareInstance field
   1095     //
   1096     Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
   1097   }
   1098 
   1099   if (ImageHeader->UpdateVendorCodeSize == 0) {
   1100     VendorCode = NULL;
   1101   } else {
   1102     VendorCode = Image + ImageHeader->UpdateImageSize;
   1103   }
   1104   AbortReason = NULL;
   1105   DEBUG((DEBUG_INFO, "Fmp->SetImage ...\n"));
   1106   DEBUG((DEBUG_INFO, "ImageTypeId - %g, ", &ImageHeader->UpdateImageTypeId));
   1107   DEBUG((DEBUG_INFO, "PayloadIndex - 0x%x, ", PayloadIndex));
   1108   DEBUG((DEBUG_INFO, "ImageIndex - 0x%x ", ImageHeader->UpdateImageIndex));
   1109   if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
   1110     DEBUG((DEBUG_INFO, "(UpdateHardwareInstance - 0x%x)", ImageHeader->UpdateHardwareInstance));
   1111   }
   1112   DEBUG((DEBUG_INFO, "\n"));
   1113   Status = Fmp->SetImage(
   1114                   Fmp,
   1115                   ImageHeader->UpdateImageIndex,          // ImageIndex
   1116                   Image,                                  // Image
   1117                   ImageHeader->UpdateImageSize,           // ImageSize
   1118                   VendorCode,                             // VendorCode
   1119                   Update_Image_Progress,                  // Progress
   1120                   &AbortReason                            // AbortReason
   1121                   );
   1122   DEBUG((DEBUG_INFO, "Fmp->SetImage - %r\n", Status));
   1123   if (AbortReason != NULL) {
   1124     DEBUG ((DEBUG_ERROR, "%s\n", AbortReason));
   1125     FreePool(AbortReason);
   1126   }
   1127 
   1128   return Status;
   1129 }
   1130 
   1131 /**
   1132   Start a UEFI image in the FMP payload.
   1133 
   1134   @param[in]  ImageBuffer   A pointer to the memory location containing a copy of the image to be loaded..
   1135   @param[in]  ImageSize     The size in bytes of ImageBuffer.
   1136 
   1137   @return The status of gBS->LoadImage and gBS->StartImage.
   1138 **/
   1139 EFI_STATUS
   1140 StartFmpImage (
   1141   IN VOID   *ImageBuffer,
   1142   IN UINTN  ImageSize
   1143   )
   1144 {
   1145   MEMMAP_DEVICE_PATH                            MemMapNode;
   1146   EFI_STATUS                                    Status;
   1147   EFI_HANDLE                                    ImageHandle;
   1148   EFI_DEVICE_PATH_PROTOCOL                      *DriverDevicePath;
   1149   UINTN                                         ExitDataSize;
   1150 
   1151   SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));
   1152   MemMapNode.Header.Type     = HARDWARE_DEVICE_PATH;
   1153   MemMapNode.Header.SubType  = HW_MEMMAP_DP;
   1154   MemMapNode.MemoryType      = EfiBootServicesCode;
   1155   MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBuffer;
   1156   MemMapNode.EndingAddress   = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)ImageBuffer + ImageSize - 1);
   1157 
   1158   DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);
   1159   if (DriverDevicePath == NULL) {
   1160     return EFI_OUT_OF_RESOURCES;
   1161   }
   1162 
   1163   DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage ...\n"));
   1164   Status = gBS->LoadImage(
   1165                   FALSE,
   1166                   gImageHandle,
   1167                   DriverDevicePath,
   1168                   ImageBuffer,
   1169                   ImageSize,
   1170                   &ImageHandle
   1171                   );
   1172   DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage - %r\n", Status));
   1173   if (EFI_ERROR(Status)) {
   1174     FreePool(DriverDevicePath);
   1175     return Status;
   1176   }
   1177 
   1178   DEBUG((DEBUG_INFO, "FmpCapsule: StartImage ...\n"));
   1179   Status = gBS->StartImage(
   1180                   ImageHandle,
   1181                   &ExitDataSize,
   1182                   NULL
   1183                   );
   1184   DEBUG((DEBUG_INFO, "FmpCapsule: StartImage - %r\n", Status));
   1185   if (EFI_ERROR(Status)) {
   1186     DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));
   1187   }
   1188 
   1189   FreePool(DriverDevicePath);
   1190   return Status;
   1191 }
   1192 
   1193 /**
   1194   Record FMP capsule status.
   1195 
   1196   @param[in]  Handle        A FMP handle.
   1197   @param[in] CapsuleHeader  The capsule image header
   1198   @param[in] CapsuleStatus  The capsule process stauts
   1199   @param[in] PayloadIndex   FMP payload index
   1200   @param[in] ImageHeader    FMP image header
   1201 **/
   1202 VOID
   1203 RecordFmpCapsuleStatus (
   1204   IN EFI_HANDLE                                    Handle,  OPTIONAL
   1205   IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
   1206   IN EFI_STATUS                                    CapsuleStatus,
   1207   IN UINTN                                         PayloadIndex,
   1208   IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader
   1209   )
   1210 {
   1211   EFI_STATUS                                    Status;
   1212   EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath;
   1213   UINT32                                        FmpImageInfoDescriptorVer;
   1214   EFI_STATUS                                    StatusEsrt;
   1215   ESRT_MANAGEMENT_PROTOCOL                      *EsrtProtocol;
   1216   EFI_SYSTEM_RESOURCE_ENTRY                     EsrtEntry;
   1217 
   1218   FmpDevicePath = NULL;
   1219   if (Handle != NULL) {
   1220     gBS->HandleProtocol(
   1221            Handle,
   1222            &gEfiDevicePathProtocolGuid,
   1223            (VOID **)&FmpDevicePath
   1224            );
   1225   }
   1226 
   1227   RecordFmpCapsuleStatusVariable (
   1228     CapsuleHeader,
   1229     CapsuleStatus,
   1230     PayloadIndex,
   1231     ImageHeader,
   1232     FmpDevicePath
   1233     );
   1234 
   1235   //
   1236   // Update corresponding ESRT entry LastAttemp Status
   1237   //
   1238   Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
   1239   if (EFI_ERROR (Status)) {
   1240     return ;
   1241   }
   1242 
   1243   if (Handle == NULL) {
   1244     return ;
   1245   }
   1246 
   1247   //
   1248   // Update EsrtEntry For V1, V2 FMP instance.
   1249   // V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
   1250   //
   1251   FmpImageInfoDescriptorVer = GetFmpImageInfoDescriptorVer (Handle);
   1252   if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) {
   1253     StatusEsrt = EsrtProtocol->GetEsrtEntry(&ImageHeader->UpdateImageTypeId, &EsrtEntry);
   1254     if (!EFI_ERROR(StatusEsrt)){
   1255       if (!EFI_ERROR(CapsuleStatus)) {
   1256         EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
   1257       } else {
   1258         EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
   1259       }
   1260       EsrtEntry.LastAttemptVersion = 0;
   1261       EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);
   1262     }
   1263   }
   1264 }
   1265 
   1266 /**
   1267   Process Firmware management protocol data capsule.
   1268 
   1269   This function assumes the caller validated the capsule by using
   1270   ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
   1271   EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
   1272   EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
   1273 
   1274   This function need support nested FMP capsule.
   1275 
   1276   @param[in]   CapsuleHeader         Points to a capsule header.
   1277 
   1278   @retval EFI_SUCESS            Process Capsule Image successfully.
   1279   @retval EFI_UNSUPPORTED       Capsule image is not supported by the firmware.
   1280   @retval EFI_VOLUME_CORRUPTED  FV volume in the capsule is corrupted.
   1281   @retval EFI_OUT_OF_RESOURCES  Not enough memory.
   1282   @retval EFI_NOT_READY         No FMP protocol to handle this FMP capsule.
   1283 **/
   1284 EFI_STATUS
   1285 ProcessFmpCapsuleImage (
   1286   IN EFI_CAPSULE_HEADER  *CapsuleHeader
   1287   )
   1288 {
   1289   EFI_STATUS                                    Status;
   1290   EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
   1291   EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader;
   1292   UINT64                                        *ItemOffsetList;
   1293   UINT32                                        ItemNum;
   1294   UINTN                                         Index;
   1295   EFI_HANDLE                                    *HandleBuffer;
   1296   UINTN                                         NumberOfHandles;
   1297   UINTN                                         DriverLen;
   1298   UINT64                                        UpdateHardwareInstance;
   1299   UINTN                                         Index2;
   1300   BOOLEAN                                       NotReady;
   1301   BOOLEAN                                       Abort;
   1302 
   1303   if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
   1304     return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));
   1305   }
   1306 
   1307   NotReady = FALSE;
   1308   Abort = FALSE;
   1309 
   1310   DumpFmpCapsule(CapsuleHeader);
   1311 
   1312   FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
   1313 
   1314   if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
   1315     return EFI_INVALID_PARAMETER;
   1316   }
   1317   ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
   1318 
   1319   ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
   1320 
   1321   //
   1322   // capsule in which driver count and payload count are both zero is not processed.
   1323   //
   1324   if (ItemNum == 0) {
   1325     return EFI_SUCCESS;
   1326   }
   1327 
   1328   //
   1329   // 1. Try to load & start all the drivers within capsule
   1330   //
   1331   for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
   1332     if ((FmpCapsuleHeader->PayloadItemCount == 0) &&
   1333         (Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1)) {
   1334       //
   1335       // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
   1336       //
   1337       DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];
   1338     } else {
   1339       DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];
   1340     }
   1341 
   1342     Status = StartFmpImage (
   1343                (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],
   1344                DriverLen
   1345                );
   1346     if (EFI_ERROR(Status)) {
   1347       DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));
   1348       return Status;
   1349     }
   1350   }
   1351 
   1352   //
   1353   // 2. Route payload to right FMP instance
   1354   //
   1355   DEBUG((DEBUG_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));
   1356 
   1357   DumpAllFmpInfo ();
   1358 
   1359   //
   1360   // Check all the payload entry in capsule payload list
   1361   //
   1362   for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
   1363     ImageHeader  = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
   1364 
   1365     UpdateHardwareInstance = 0;
   1366     if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
   1367       UpdateHardwareInstance = ImageHeader->UpdateHardwareInstance;
   1368     }
   1369 
   1370     Status = GetFmpHandleBufferByType (
   1371                &ImageHeader->UpdateImageTypeId,
   1372                UpdateHardwareInstance,
   1373                &NumberOfHandles,
   1374                &HandleBuffer
   1375                );
   1376     if (EFI_ERROR(Status)) {
   1377       NotReady = TRUE;
   1378       RecordFmpCapsuleStatus (
   1379         NULL,
   1380         CapsuleHeader,
   1381         EFI_NOT_READY,
   1382         Index - FmpCapsuleHeader->EmbeddedDriverCount,
   1383         ImageHeader
   1384         );
   1385       continue;
   1386     }
   1387 
   1388     for (Index2 = 0; Index2 < NumberOfHandles; Index2++) {
   1389       if (Abort) {
   1390         RecordFmpCapsuleStatus (
   1391           HandleBuffer[Index2],
   1392           CapsuleHeader,
   1393           EFI_ABORTED,
   1394           Index - FmpCapsuleHeader->EmbeddedDriverCount,
   1395           ImageHeader
   1396           );
   1397         continue;
   1398       }
   1399 
   1400       Status = SetFmpImageData (
   1401                  HandleBuffer[Index2],
   1402                  ImageHeader,
   1403                  Index - FmpCapsuleHeader->EmbeddedDriverCount
   1404                  );
   1405       if (Status != EFI_SUCCESS) {
   1406         Abort = TRUE;
   1407       }
   1408 
   1409       RecordFmpCapsuleStatus (
   1410         HandleBuffer[Index2],
   1411         CapsuleHeader,
   1412         Status,
   1413         Index - FmpCapsuleHeader->EmbeddedDriverCount,
   1414         ImageHeader
   1415         );
   1416     }
   1417     if (HandleBuffer != NULL) {
   1418       FreePool(HandleBuffer);
   1419     }
   1420   }
   1421 
   1422   if (NotReady) {
   1423     return EFI_NOT_READY;
   1424   }
   1425 
   1426   //
   1427   // always return SUCCESS to indicate this capsule is processed.
   1428   // The status of SetImage is recorded in capsule result variable.
   1429   //
   1430   return EFI_SUCCESS;
   1431 }
   1432 
   1433 /**
   1434   Return if there is a FMP header below capsule header.
   1435 
   1436   @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
   1437 
   1438   @retval TRUE  There is a FMP header below capsule header.
   1439   @retval FALSE There is not a FMP header below capsule header
   1440 **/
   1441 BOOLEAN
   1442 IsNestedFmpCapsule (
   1443   IN EFI_CAPSULE_HEADER         *CapsuleHeader
   1444   )
   1445 {
   1446   EFI_STATUS                 Status;
   1447   EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
   1448   EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
   1449   UINTN                      Index;
   1450   BOOLEAN                    EsrtGuidFound;
   1451   EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
   1452   UINTN                      NestedCapsuleSize;
   1453   ESRT_MANAGEMENT_PROTOCOL   *EsrtProtocol;
   1454   EFI_SYSTEM_RESOURCE_ENTRY  Entry;
   1455 
   1456   EsrtGuidFound = FALSE;
   1457 
   1458   //
   1459   // Check ESRT protocol
   1460   //
   1461   Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
   1462   if (!EFI_ERROR(Status)) {
   1463     Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &Entry);
   1464     if (!EFI_ERROR(Status)) {
   1465       EsrtGuidFound = TRUE;
   1466     }
   1467   }
   1468 
   1469   //
   1470   // Check ESRT configuration table
   1471   //
   1472   if (!EsrtGuidFound) {
   1473     Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
   1474     if (!EFI_ERROR(Status)) {
   1475       ASSERT (Esrt != NULL);
   1476       EsrtEntry = (VOID *)(Esrt + 1);
   1477       for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
   1478         if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
   1479           EsrtGuidFound = TRUE;
   1480           break;
   1481         }
   1482       }
   1483     }
   1484   }
   1485   if (!EsrtGuidFound) {
   1486     return FALSE;
   1487   }
   1488 
   1489   //
   1490   // Check nested capsule header
   1491   // FMP GUID after ESRT one
   1492   //
   1493   NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
   1494   NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize - (UINTN)NestedCapsuleHeader;
   1495   if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
   1496     return FALSE;
   1497   }
   1498   if (!IsValidCapsuleHeader(NestedCapsuleHeader, NestedCapsuleSize)) {
   1499     return FALSE;
   1500   }
   1501   if (!IsFmpCapsuleGuid(&NestedCapsuleHeader->CapsuleGuid)) {
   1502     return FALSE;
   1503   }
   1504   DEBUG ((DEBUG_INFO, "IsNestedFmpCapsule\n"));
   1505   return TRUE;
   1506 }
   1507 
   1508 /**
   1509   Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
   1510 
   1511   @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
   1512 
   1513   @retval TRUE  It is a system FMP.
   1514   @retval FALSE It is a device FMP.
   1515 **/
   1516 BOOLEAN
   1517 IsFmpCapsule (
   1518   IN EFI_CAPSULE_HEADER         *CapsuleHeader
   1519   )
   1520 {
   1521   if (IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
   1522     return TRUE;
   1523   }
   1524   if (IsNestedFmpCapsule(CapsuleHeader)) {
   1525     return TRUE;
   1526   }
   1527   return FALSE;
   1528 }
   1529 
   1530 /**
   1531   Those capsules supported by the firmwares.
   1532 
   1533   Caution: This function may receive untrusted input.
   1534 
   1535   @param[in]  CapsuleHeader    Points to a capsule header.
   1536 
   1537   @retval EFI_SUCESS       Input capsule is supported by firmware.
   1538   @retval EFI_UNSUPPORTED  Input capsule is not supported by the firmware.
   1539   @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
   1540 **/
   1541 EFI_STATUS
   1542 EFIAPI
   1543 SupportCapsuleImage (
   1544   IN EFI_CAPSULE_HEADER  *CapsuleHeader
   1545   )
   1546 {
   1547   //
   1548   // check Display Capsule Guid
   1549   //
   1550   if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
   1551     return EFI_SUCCESS;
   1552   }
   1553 
   1554   if (IsFmpCapsule(CapsuleHeader)) {
   1555     //
   1556     // Check layout of FMP capsule
   1557     //
   1558     return ValidateFmpCapsule(CapsuleHeader, NULL);
   1559   }
   1560   DEBUG((DEBUG_ERROR, "Unknown Capsule Guid - %g\n", &CapsuleHeader->CapsuleGuid));
   1561   return EFI_UNSUPPORTED;
   1562 }
   1563 
   1564 /**
   1565   The firmware implements to process the capsule image.
   1566 
   1567   Caution: This function may receive untrusted input.
   1568 
   1569   @param[in]  CapsuleHeader         Points to a capsule header.
   1570 
   1571   @retval EFI_SUCESS            Process Capsule Image successfully.
   1572   @retval EFI_UNSUPPORTED       Capsule image is not supported by the firmware.
   1573   @retval EFI_VOLUME_CORRUPTED  FV volume in the capsule is corrupted.
   1574   @retval EFI_OUT_OF_RESOURCES  Not enough memory.
   1575 **/
   1576 EFI_STATUS
   1577 EFIAPI
   1578 ProcessCapsuleImage (
   1579   IN EFI_CAPSULE_HEADER  *CapsuleHeader
   1580   )
   1581 {
   1582   EFI_STATUS                   Status;
   1583 
   1584   if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {
   1585     RecordCapsuleStatusVariable(CapsuleHeader, EFI_UNSUPPORTED);
   1586     return EFI_UNSUPPORTED;
   1587   }
   1588 
   1589   //
   1590   // Display image in firmware update display capsule
   1591   //
   1592   if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
   1593     DEBUG((DEBUG_INFO, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
   1594     Status = DisplayCapsuleImage(CapsuleHeader);
   1595     RecordCapsuleStatusVariable(CapsuleHeader, Status);
   1596     return Status;
   1597   }
   1598 
   1599   //
   1600   // Check FMP capsule layout
   1601   //
   1602   if (IsFmpCapsule (CapsuleHeader)) {
   1603     DEBUG((DEBUG_INFO, "ProcessCapsuleImage for FmpCapsule ...\n"));
   1604     DEBUG((DEBUG_INFO, "ValidateFmpCapsule ...\n"));
   1605     Status = ValidateFmpCapsule(CapsuleHeader, NULL);
   1606     DEBUG((DEBUG_INFO, "ValidateFmpCapsule - %r\n", Status));
   1607     if (EFI_ERROR(Status)) {
   1608       RecordCapsuleStatusVariable(CapsuleHeader, Status);
   1609       return Status;
   1610     }
   1611 
   1612     //
   1613     // Press EFI FMP Capsule
   1614     //
   1615     DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));
   1616     Status = ProcessFmpCapsuleImage(CapsuleHeader);
   1617     DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
   1618 
   1619     return Status;
   1620   }
   1621 
   1622   return EFI_UNSUPPORTED;
   1623 }
   1624 
   1625 /**
   1626   Callback function executed when the EndOfDxe event group is signaled.
   1627 
   1628   @param[in] Event      Event whose notification function is being invoked.
   1629   @param[in] Context    The pointer to the notification function's context, which
   1630                         is implementation-dependent.
   1631 **/
   1632 VOID
   1633 EFIAPI
   1634 DxeCapsuleLibEndOfDxe (
   1635   IN EFI_EVENT  Event,
   1636   IN VOID       *Context
   1637   )
   1638 {
   1639   mDxeCapsuleLibEndOfDxe = TRUE;
   1640 }
   1641 
   1642 /**
   1643   The constructor function.
   1644 
   1645   @param[in]  ImageHandle   The firmware allocated handle for the EFI image.
   1646   @param[in]  SystemTable   A pointer to the EFI System Table.
   1647 
   1648   @retval EFI_SUCCESS   The constructor successfully .
   1649 **/
   1650 EFI_STATUS
   1651 EFIAPI
   1652 DxeCapsuleLibConstructor (
   1653   IN EFI_HANDLE         ImageHandle,
   1654   IN EFI_SYSTEM_TABLE   *SystemTable
   1655   )
   1656 {
   1657   EFI_EVENT     EndOfDxeEvent;
   1658   EFI_STATUS    Status;
   1659 
   1660   Status = gBS->CreateEventEx (
   1661                   EVT_NOTIFY_SIGNAL,
   1662                   TPL_CALLBACK,
   1663                   DxeCapsuleLibEndOfDxe,
   1664                   NULL,
   1665                   &gEfiEndOfDxeEventGroupGuid,
   1666                   &EndOfDxeEvent
   1667                   );
   1668   ASSERT_EFI_ERROR (Status);
   1669 
   1670   InitCapsuleVariable();
   1671 
   1672   return EFI_SUCCESS;
   1673 }
   1674