Home | History | Annotate | Download | only in CapsuleApp
      1 /** @file
      2   Dump Capsule image information.
      3 
      4   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include <PiDxe.h>
     16 #include <Library/BaseLib.h>
     17 #include <Library/DebugLib.h>
     18 #include <Library/BaseMemoryLib.h>
     19 #include <Library/MemoryAllocationLib.h>
     20 #include <Library/UefiBootServicesTableLib.h>
     21 #include <Library/UefiRuntimeServicesTableLib.h>
     22 #include <Library/UefiLib.h>
     23 #include <Library/PrintLib.h>
     24 #include <Protocol/FirmwareManagement.h>
     25 #include <Guid/ImageAuthentication.h>
     26 #include <Guid/CapsuleReport.h>
     27 #include <Guid/SystemResourceTable.h>
     28 #include <Guid/FmpCapsule.h>
     29 #include <IndustryStandard/WindowsUxCapsule.h>
     30 
     31 /**
     32   Read a file.
     33 
     34   @param[in]  FileName        The file to be read.
     35   @param[out] BufferSize      The file buffer size
     36   @param[out] Buffer          The file buffer
     37 
     38   @retval EFI_SUCCESS    Read file successfully
     39   @retval EFI_NOT_FOUND  File not found
     40 **/
     41 EFI_STATUS
     42 ReadFileToBuffer (
     43   IN  CHAR16                               *FileName,
     44   OUT UINTN                                *BufferSize,
     45   OUT VOID                                 **Buffer
     46   );
     47 
     48 /**
     49   Write a file.
     50 
     51   @param[in] FileName        The file to be written.
     52   @param[in] BufferSize      The file buffer size
     53   @param[in] Buffer          The file buffer
     54 
     55   @retval EFI_SUCCESS    Write file successfully
     56 **/
     57 EFI_STATUS
     58 WriteFileFromBuffer (
     59   IN  CHAR16                               *FileName,
     60   IN  UINTN                                BufferSize,
     61   IN  VOID                                 *Buffer
     62   );
     63 
     64 /**
     65   Dump UX capsule information.
     66 
     67   @param[in] CapsuleHeader      The UX capsule header
     68 **/
     69 VOID
     70 DumpUxCapsule (
     71   IN EFI_CAPSULE_HEADER  *CapsuleHeader
     72   )
     73 {
     74   EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
     75   DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
     76   Print(L"[UxCapusule]\n");
     77   Print(L"CapsuleHeader:\n");
     78   Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
     79   Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
     80   Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
     81   Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule->CapsuleHeader.CapsuleImageSize);
     82   Print(L"ImagePayload:\n");
     83   Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
     84   Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
     85   Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
     86   Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
     87   Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
     88   Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
     89 }
     90 
     91 /**
     92   Dump FMP image authentication information.
     93 
     94   @param[in] Image      The FMP capsule image
     95   @param[in] ImageSize  The size of the FMP capsule image in bytes.
     96 
     97   @return the size of FMP authentication.
     98 **/
     99 UINTN
    100 DumpImageAuthentication (
    101   IN VOID   *Image,
    102   IN UINTN  ImageSize
    103   )
    104 {
    105   EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
    106 
    107   ImageAuthentication = Image;
    108   if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
    109       CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertTypeRsa2048Sha256Guid)) {
    110     Print(L"[ImageAuthentication]\n");
    111     Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
    112     Print(L"WIN_CERTIFICATE:\n");
    113     Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
    114     Print(L"  wRevision        - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wRevision);
    115     Print(L"  wCertificateType - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wCertificateType);
    116     Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
    117     return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication->AuthInfo.Hdr.dwLength;
    118   } else {
    119     return 0;
    120   }
    121 }
    122 
    123 /**
    124   Dump a non-nested FMP capsule.
    125 
    126   @param[in]  CapsuleHeader  A pointer to CapsuleHeader
    127 **/
    128 VOID
    129 DumpFmpCapsule (
    130   IN EFI_CAPSULE_HEADER  *CapsuleHeader
    131   )
    132 {
    133   EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
    134   UINT64                                        *ItemOffsetList;
    135   UINTN                                         Index;
    136   UINTN                                         Count;
    137   EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
    138 
    139   Print(L"[FmpCapusule]\n");
    140   Print(L"CapsuleHeader:\n");
    141   Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
    142   Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
    143   Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
    144   Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
    145 
    146   FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
    147   ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
    148   Print(L"FmpHeader:\n");
    149   Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
    150   Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
    151   Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
    152   Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
    153   for (Index = 0; Index < Count; Index++) {
    154     Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
    155   }
    156 
    157   for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
    158     Print(L"FmpPayload[%d] ImageHeader:\n", Index);
    159     FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
    160     Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
    161     Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
    162     Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
    163     Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
    164     Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
    165     if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
    166       Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader->UpdateHardwareInstance);
    167     }
    168   }
    169 }
    170 
    171 /**
    172   Return if there is a FMP header below capsule header.
    173 
    174   @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
    175 
    176   @retval TRUE  There is a FMP header below capsule header.
    177   @retval FALSE There is not a FMP header below capsule header
    178 **/
    179 BOOLEAN
    180 IsNestedFmpCapsule (
    181   IN EFI_CAPSULE_HEADER         *CapsuleHeader
    182   )
    183 {
    184   EFI_STATUS                 Status;
    185   EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
    186   EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
    187   UINTN                      Index;
    188   BOOLEAN                    EsrtGuidFound;
    189   EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
    190   UINTN                      NestedCapsuleSize;
    191 
    192   //
    193   // Check ESRT
    194   //
    195   EsrtGuidFound = FALSE;
    196   Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
    197   if (!EFI_ERROR(Status)) {
    198     ASSERT (Esrt != NULL);
    199     EsrtEntry = (VOID *)(Esrt + 1);
    200     for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
    201       if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
    202         EsrtGuidFound = TRUE;
    203         break;
    204       }
    205     }
    206   }
    207 
    208   if (!EsrtGuidFound) {
    209     return FALSE;
    210   }
    211 
    212   //
    213   // Check nested capsule header
    214   // FMP GUID after ESRT one
    215   //
    216   NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
    217   NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize - (UINTN)NestedCapsuleHeader;
    218   if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
    219     return FALSE;
    220   }
    221   if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
    222     return FALSE;
    223   }
    224   return TRUE;
    225 }
    226 
    227 /**
    228   Dump capsule information
    229 
    230   @param[in] CapsuleName  The name of the capsule image.
    231 
    232   @retval EFI_SUCCESS            The capsule information is dumped.
    233   @retval EFI_UNSUPPORTED        Input parameter is not valid.
    234 **/
    235 EFI_STATUS
    236 DumpCapsule (
    237   IN CHAR16                                        *CapsuleName
    238   )
    239 {
    240   VOID                                          *Buffer;
    241   UINTN                                         FileSize;
    242   EFI_CAPSULE_HEADER                            *CapsuleHeader;
    243   EFI_STATUS                                    Status;
    244 
    245   Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
    246   if (EFI_ERROR(Status)) {
    247     Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
    248     goto Done;
    249   }
    250 
    251   CapsuleHeader = Buffer;
    252   if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
    253     DumpUxCapsule(CapsuleHeader);
    254     Status = EFI_SUCCESS;
    255     goto Done;
    256   }
    257 
    258   if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
    259     DumpFmpCapsule(CapsuleHeader);
    260   }
    261   if (IsNestedFmpCapsule(CapsuleHeader)) {
    262     Print(L"[NestedCapusule]\n");
    263     Print(L"CapsuleHeader:\n");
    264     Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
    265     Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
    266     Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
    267     Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
    268     DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));
    269   }
    270 
    271 Done:
    272   FreePool(Buffer);
    273   return Status;
    274 }
    275 
    276 /**
    277   Dump capsule status variable.
    278 
    279   @retval EFI_SUCCESS            The capsule status variable is dumped.
    280   @retval EFI_UNSUPPORTED        Input parameter is not valid.
    281 **/
    282 EFI_STATUS
    283 DmpCapsuleStatusVariable (
    284   VOID
    285   )
    286 {
    287   EFI_STATUS                          Status;
    288   UINT32                              Index;
    289   CHAR16                              CapsuleVarName[20];
    290   CHAR16                              *TempVarName;
    291   EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
    292   EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
    293   UINTN                               CapsuleFileNameSize;
    294   CHAR16                              CapsuleIndexData[12];
    295   CHAR16                              *CapsuleIndex;
    296   CHAR16                              *CapsuleFileName;
    297   CHAR16                              *CapsuleTarget;
    298 
    299   Status = GetVariable2(
    300              L"CapsuleMax",
    301              &gEfiCapsuleReportGuid,
    302              (VOID **)&CapsuleIndex,
    303              NULL
    304              );
    305   if (!EFI_ERROR(Status)) {
    306     ASSERT (CapsuleIndex != NULL);
    307     CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
    308     CapsuleIndexData[11] = 0;
    309     Print(L"CapsuleMax - %s\n", CapsuleIndexData);
    310     FreePool(CapsuleIndex);
    311   }
    312   Status = GetVariable2(
    313              L"CapsuleLast",
    314              &gEfiCapsuleReportGuid,
    315              (VOID **)&CapsuleIndex,
    316              NULL
    317              );
    318   if (!EFI_ERROR(Status)) {
    319     ASSERT (CapsuleIndex != NULL);
    320     CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
    321     CapsuleIndexData[11] = 0;
    322     Print(L"CapsuleLast - %s\n", CapsuleIndexData);
    323     FreePool(CapsuleIndex);
    324   }
    325 
    326 
    327   StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]), L"Capsule");
    328   TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
    329   Index = 0;
    330 
    331   while (TRUE) {
    332     UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
    333 
    334     Status = GetVariable2 (
    335                CapsuleVarName,
    336                &gEfiCapsuleReportGuid,
    337                (VOID **) &CapsuleResult,
    338                NULL
    339                );
    340     if (Status == EFI_NOT_FOUND) {
    341       break;
    342     } else if (EFI_ERROR(Status)) {
    343       continue;
    344     }
    345     ASSERT (CapsuleResult != NULL);
    346 
    347     //
    348     // display capsule process status
    349     //
    350     if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
    351       Print (L"CapsuleName: %s\n", CapsuleVarName);
    352       Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
    353       Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
    354       Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
    355     }
    356 
    357     if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
    358       if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) * 2) {
    359         CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
    360         Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
    361         Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
    362         Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp->UpdateImageIndex);
    363         Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp->UpdateImageTypeId);
    364         CapsuleFileName = (CHAR16 *)(CapsuleResultFmp + 1);
    365         Print(L"  Capsule FMP CapsuleFileName: \"%s\"\n", CapsuleFileName);
    366         CapsuleFileNameSize = StrSize(CapsuleFileName);
    367         CapsuleTarget = (CHAR16 *)((UINTN)CapsuleFileName + CapsuleFileNameSize);
    368         Print(L"  Capsule FMP CapsuleTarget: \"%s\"\n", CapsuleTarget);
    369       }
    370     }
    371 
    372     FreePool(CapsuleResult);
    373 
    374     Index++;
    375     if (Index > 0xFFFF) {
    376       break;
    377     }
    378   }
    379 
    380   return EFI_SUCCESS;
    381 }
    382 
    383 CHAR8 *mFwTypeString[] = {
    384   "Unknown",
    385   "SystemFirmware",
    386   "DeviceFirmware",
    387   "UefiDriver",
    388 };
    389 
    390 CHAR8 *mLastAttemptStatusString[] = {
    391   "Success",
    392   "Error: Unsuccessful",
    393   "Error: Insufficient Resources",
    394   "Error: Incorrect Version",
    395   "Error: Invalid Format",
    396   "Error: Auth Error",
    397   "Error: Power Event AC",
    398   "Error: Power Event Battery",
    399 };
    400 
    401 /**
    402   Convert FwType to a string.
    403 
    404   @param[in] FwType  FwType in ESRT
    405 
    406   @return a string for FwType.
    407 **/
    408 CHAR8 *
    409 FwTypeToString (
    410   IN UINT32  FwType
    411   )
    412 {
    413   if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
    414     return mFwTypeString[FwType];
    415   } else {
    416     return "Invalid";
    417   }
    418 }
    419 
    420 /**
    421   Convert LastAttemptStatus to a string.
    422 
    423   @param[in] LastAttemptStatus  LastAttemptStatus in FMP or ESRT
    424 
    425   @return a string for LastAttemptStatus.
    426 **/
    427 CHAR8 *
    428 LastAttemptStatusToString (
    429   IN UINT32  LastAttemptStatus
    430   )
    431 {
    432   if (LastAttemptStatus < sizeof(mLastAttemptStatusString) / sizeof(mLastAttemptStatusString[0])) {
    433     return mLastAttemptStatusString[LastAttemptStatus];
    434   } else {
    435     return "Error: Unknown";
    436   }
    437 }
    438 
    439 /**
    440   Dump ESRT entry.
    441 
    442   @param[in] EsrtEntry  ESRT entry
    443 **/
    444 VOID
    445 DumpEsrtEntry (
    446   IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
    447   )
    448 {
    449   Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
    450   Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType, FwTypeToString(EsrtEntry->FwType));
    451   Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
    452   Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
    453   Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
    454   Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
    455   Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
    456   Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_INITIATE_RESET);
    457   Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
    458   Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus, LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
    459 }
    460 
    461 /**
    462   Dump ESRT table.
    463 
    464   @param[in] Esrt  ESRT table
    465 **/
    466 VOID
    467 DumpEsrt (
    468   IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
    469   )
    470 {
    471   UINTN                      Index;
    472   EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
    473 
    474   if (Esrt == NULL) {
    475     return ;
    476   }
    477 
    478   Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
    479   Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
    480   Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
    481   Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
    482 
    483   EsrtEntry = (VOID *)(Esrt + 1);
    484   for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
    485     Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
    486     DumpEsrtEntry(EsrtEntry);
    487     EsrtEntry++;
    488   }
    489 }
    490 
    491 /**
    492   Dump ESRT info.
    493 **/
    494 VOID
    495 DumpEsrtData (
    496   VOID
    497   )
    498 {
    499   EFI_STATUS                 Status;
    500   EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
    501 
    502   Print(L"##############\n");
    503   Print(L"# ESRT TABLE #\n");
    504   Print(L"##############\n");
    505 
    506   Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
    507   if (EFI_ERROR(Status)) {
    508     Print(L"ESRT - %r\n", Status);
    509     return;
    510   }
    511   DumpEsrt(Esrt);
    512   Print(L"\n");
    513 }
    514 
    515 /**
    516   Dump FMP information.
    517 
    518   @param[in] ImageInfoSize       The size of ImageInfo, in bytes.
    519   @param[in] ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
    520   @param[in] DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
    521   @param[in] DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
    522   @param[in] DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
    523   @param[in] PackageVersion      The version of package.
    524   @param[in] PackageVersionName  The version name of package.
    525 **/
    526 VOID
    527 DumpFmpImageInfo (
    528   IN UINTN                           ImageInfoSize,
    529   IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
    530   IN UINT32                          DescriptorVersion,
    531   IN UINT8                           DescriptorCount,
    532   IN UINTN                           DescriptorSize,
    533   IN UINT32                          PackageVersion,
    534   IN CHAR16                          *PackageVersionName
    535   )
    536 {
    537   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
    538   UINTN                                         Index;
    539 
    540   Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
    541   Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
    542   Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
    543   Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
    544   Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
    545   CurrentImageInfo = ImageInfo;
    546   for (Index = 0; Index < DescriptorCount; Index++) {
    547     Print(L"  ImageDescriptor (%d)\n", Index);
    548     Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
    549     Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
    550     Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
    551     Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo->ImageIdName);
    552     Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
    553     Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo->VersionName);
    554     Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
    555     Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo->AttributesSupported);
    556     Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
    557     Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
    558     Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
    559     Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
    560     Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
    561     Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo->AttributesSetting);
    562     Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
    563     Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
    564     Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
    565     Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
    566     Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
    567     Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo->Compatibilities);
    568     Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo->Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
    569     if (DescriptorVersion > 1) {
    570       Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion);
    571       if (DescriptorVersion > 2) {
    572         Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo->LastAttemptVersion);
    573         Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo->LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
    574         Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo->HardwareInstance);
    575       }
    576     }
    577     //
    578     // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
    579     //
    580     CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
    581   }
    582 }
    583 
    584 /**
    585   Dump FMP package information.
    586 
    587   @param[in] PackageVersion             The version of package.
    588   @param[in] PackageVersionName         The version name of package.
    589   @param[in] PackageVersionNameMaxLen   The maximum length of PackageVersionName.
    590   @param[in] AttributesSupported        Package attributes that are supported by this device.
    591   @param[in] AttributesSetting          Package attributes.
    592 **/
    593 VOID
    594 DumpFmpPackageInfo (
    595   IN UINT32                           PackageVersion,
    596   IN CHAR16                           *PackageVersionName,
    597   IN UINT32                           PackageVersionNameMaxLen,
    598   IN UINT64                           AttributesSupported,
    599   IN UINT64                           AttributesSetting
    600   )
    601 {
    602   Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
    603   Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
    604   Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
    605   Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
    606   Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
    607   Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
    608   Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
    609   Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
    610   Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
    611   Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
    612   Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
    613 }
    614 
    615 /**
    616   Dump FMP protocol info.
    617 **/
    618 VOID
    619 DumpFmpData (
    620   VOID
    621   )
    622 {
    623   EFI_STATUS                                    Status;
    624   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
    625   EFI_HANDLE                                    *HandleBuffer;
    626   UINTN                                         NumberOfHandles;
    627   UINTN                                         Index;
    628   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
    629   UINTN                                         ImageInfoSize;
    630   UINT32                                        FmpImageInfoDescriptorVer;
    631   UINT8                                         FmpImageInfoCount;
    632   UINTN                                         DescriptorSize;
    633   UINT32                                        PackageVersion;
    634   CHAR16                                        *PackageVersionName;
    635   UINT32                                        PackageVersionNameMaxLen;
    636   UINT64                                        AttributesSupported;
    637   UINT64                                        AttributesSetting;
    638 
    639   Print(L"############\n");
    640   Print(L"# FMP DATA #\n");
    641   Print(L"############\n");
    642   Status = gBS->LocateHandleBuffer (
    643                   ByProtocol,
    644                   &gEfiFirmwareManagementProtocolGuid,
    645                   NULL,
    646                   &NumberOfHandles,
    647                   &HandleBuffer
    648                   );
    649   if (EFI_ERROR(Status)) {
    650     Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
    651     return;
    652   }
    653 
    654   for (Index = 0; Index < NumberOfHandles; Index++) {
    655     Status = gBS->HandleProtocol(
    656                     HandleBuffer[Index],
    657                     &gEfiFirmwareManagementProtocolGuid,
    658                     (VOID **)&Fmp
    659                     );
    660     if (EFI_ERROR(Status)) {
    661       continue;
    662     }
    663 
    664     ImageInfoSize = 0;
    665     Status = Fmp->GetImageInfo (
    666                     Fmp,
    667                     &ImageInfoSize,
    668                     NULL,
    669                     NULL,
    670                     NULL,
    671                     NULL,
    672                     NULL,
    673                     NULL
    674                     );
    675     if (Status != EFI_BUFFER_TOO_SMALL) {
    676       continue;
    677     }
    678 
    679     FmpImageInfoBuf = NULL;
    680     FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
    681     if (FmpImageInfoBuf == NULL) {
    682       Status = EFI_OUT_OF_RESOURCES;
    683       goto EXIT;
    684     }
    685 
    686     PackageVersionName = NULL;
    687     Status = Fmp->GetImageInfo (
    688                     Fmp,
    689                     &ImageInfoSize,               // ImageInfoSize
    690                     FmpImageInfoBuf,              // ImageInfo
    691                     &FmpImageInfoDescriptorVer,   // DescriptorVersion
    692                     &FmpImageInfoCount,           // DescriptorCount
    693                     &DescriptorSize,              // DescriptorSize
    694                     &PackageVersion,              // PackageVersion
    695                     &PackageVersionName           // PackageVersionName
    696                     );
    697 
    698     //
    699     // If FMP GetInformation interface failed, skip this resource
    700     //
    701     if (EFI_ERROR(Status)) {
    702       Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
    703       FreePool(FmpImageInfoBuf);
    704       continue;
    705     }
    706 
    707     Print(L"FMP (%d) ImageInfo:\n", Index);
    708     DumpFmpImageInfo(
    709       ImageInfoSize,               // ImageInfoSize
    710       FmpImageInfoBuf,             // ImageInfo
    711       FmpImageInfoDescriptorVer,   // DescriptorVersion
    712       FmpImageInfoCount,           // DescriptorCount
    713       DescriptorSize,              // DescriptorSize
    714       PackageVersion,              // PackageVersion
    715       PackageVersionName           // PackageVersionName
    716       );
    717 
    718     if (PackageVersionName != NULL) {
    719       FreePool(PackageVersionName);
    720     }
    721     FreePool(FmpImageInfoBuf);
    722 
    723     //
    724     // Get package info
    725     //
    726     PackageVersionName = NULL;
    727     Status = Fmp->GetPackageInfo (
    728                     Fmp,
    729                     &PackageVersion,              // PackageVersion
    730                     &PackageVersionName,          // PackageVersionName
    731                     &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
    732                     &AttributesSupported,         // AttributesSupported
    733                     &AttributesSetting            // AttributesSetting
    734                     );
    735     if (EFI_ERROR(Status)) {
    736       Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
    737     } else {
    738       Print(L"FMP (%d) ImageInfo:\n", Index);
    739       DumpFmpPackageInfo(
    740         PackageVersion,              // PackageVersion
    741         PackageVersionName,          // PackageVersionName
    742         PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
    743         AttributesSupported,         // AttributesSupported
    744         AttributesSetting            // AttributesSetting
    745         );
    746 
    747       if (PackageVersionName != NULL) {
    748         FreePool(PackageVersionName);
    749       }
    750     }
    751   }
    752   Print(L"\n");
    753 
    754 EXIT:
    755   FreePool(HandleBuffer);
    756 }
    757 
    758 /**
    759   Check if the ImageInfo includes the ImageTypeId.
    760 
    761   @param[in] ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
    762   @param[in] DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
    763   @param[in] DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
    764   @param[in] ImageTypeId         A unique GUID identifying the firmware image type.
    765 
    766   @return TRUE  This ImageInfo includes the ImageTypeId
    767   @return FALSE This ImageInfo does not include the ImageTypeId
    768 **/
    769 BOOLEAN
    770 IsThisFmpImageInfo (
    771   IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
    772   IN UINT8                           DescriptorCount,
    773   IN UINTN                           DescriptorSize,
    774   IN EFI_GUID                        *ImageTypeId
    775   )
    776 {
    777   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
    778   UINTN                                         Index;
    779 
    780   CurrentImageInfo = ImageInfo;
    781   for (Index = 0; Index < DescriptorCount; Index++) {
    782     if (CompareGuid (&CurrentImageInfo->ImageTypeId, ImageTypeId)) {
    783       return TRUE;
    784     }
    785     CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
    786   }
    787   return FALSE;
    788 }
    789 
    790 /**
    791   return the FMP whoes ImageInfo includes the ImageTypeId.
    792 
    793   @param[in] ImageTypeId         A unique GUID identifying the firmware image type.
    794 
    795   @return The FMP whoes ImageInfo includes the ImageTypeId
    796 **/
    797 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *
    798 FindFmpFromImageTypeId (
    799   IN EFI_GUID  *ImageTypeId
    800   )
    801 {
    802   EFI_STATUS                                    Status;
    803   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
    804   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *TargetFmp;
    805   EFI_HANDLE                                    *HandleBuffer;
    806   UINTN                                         NumberOfHandles;
    807   UINTN                                         Index;
    808   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
    809   UINTN                                         ImageInfoSize;
    810   UINT32                                        FmpImageInfoDescriptorVer;
    811   UINT8                                         FmpImageInfoCount;
    812   UINTN                                         DescriptorSize;
    813   UINT32                                        PackageVersion;
    814   CHAR16                                        *PackageVersionName;
    815 
    816   Status = gBS->LocateHandleBuffer (
    817                   ByProtocol,
    818                   &gEfiFirmwareManagementProtocolGuid,
    819                   NULL,
    820                   &NumberOfHandles,
    821                   &HandleBuffer
    822                   );
    823   if (EFI_ERROR(Status)) {
    824     Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
    825     return NULL;
    826   }
    827 
    828   TargetFmp = NULL;
    829   for (Index = 0; Index < NumberOfHandles; Index++) {
    830     Status = gBS->HandleProtocol(
    831                     HandleBuffer[Index],
    832                     &gEfiFirmwareManagementProtocolGuid,
    833                     (VOID **)&Fmp
    834                     );
    835     if (EFI_ERROR(Status)) {
    836       continue;
    837     }
    838 
    839     ImageInfoSize = 0;
    840     Status = Fmp->GetImageInfo (
    841                     Fmp,
    842                     &ImageInfoSize,
    843                     NULL,
    844                     NULL,
    845                     NULL,
    846                     NULL,
    847                     NULL,
    848                     NULL
    849                     );
    850     if (Status != EFI_BUFFER_TOO_SMALL) {
    851       continue;
    852     }
    853 
    854     FmpImageInfoBuf = NULL;
    855     FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
    856     if (FmpImageInfoBuf == NULL) {
    857       FreePool(HandleBuffer);
    858       Print(L"Out of resource\n");
    859       return NULL;
    860     }
    861 
    862     PackageVersionName = NULL;
    863     Status = Fmp->GetImageInfo (
    864                     Fmp,
    865                     &ImageInfoSize,               // ImageInfoSize
    866                     FmpImageInfoBuf,              // ImageInfo
    867                     &FmpImageInfoDescriptorVer,   // DescriptorVersion
    868                     &FmpImageInfoCount,           // DescriptorCount
    869                     &DescriptorSize,              // DescriptorSize
    870                     &PackageVersion,              // PackageVersion
    871                     &PackageVersionName           // PackageVersionName
    872                     );
    873 
    874     //
    875     // If FMP GetInformation interface failed, skip this resource
    876     //
    877     if (EFI_ERROR(Status)) {
    878       FreePool(FmpImageInfoBuf);
    879       continue;
    880     }
    881 
    882     if (PackageVersionName != NULL) {
    883       FreePool(PackageVersionName);
    884     }
    885 
    886     if (IsThisFmpImageInfo (FmpImageInfoBuf, FmpImageInfoCount, DescriptorSize, ImageTypeId)) {
    887       TargetFmp = Fmp;
    888     }
    889     FreePool(FmpImageInfoBuf);
    890     if (TargetFmp != NULL) {
    891       break;
    892     }
    893   }
    894   FreePool(HandleBuffer);
    895   return TargetFmp;
    896 }
    897 
    898 /**
    899   Dump FMP image data.
    900 
    901   @param[in]  ImageTypeId   The ImageTypeId of the FMP image.
    902                             It is used to identify the FMP protocol.
    903   @param[in]  ImageIndex    The ImageIndex of the FMP image.
    904                             It is the input parameter for FMP->GetImage().
    905   @param[in]  ImageName     The file name to hold the output FMP image.
    906 **/
    907 VOID
    908 DumpFmpImage (
    909   IN EFI_GUID  *ImageTypeId,
    910   IN UINTN     ImageIndex,
    911   IN CHAR16    *ImageName
    912   )
    913 {
    914   EFI_STATUS                                    Status;
    915   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
    916   VOID                                          *Image;
    917   UINTN                                         ImageSize;
    918 
    919   Fmp = FindFmpFromImageTypeId (ImageTypeId);
    920   if (Fmp == NULL) {
    921     Print(L"No FMP include ImageTypeId %g\n", ImageTypeId);
    922     return ;
    923   }
    924 
    925   if (ImageIndex > 0xFF) {
    926     Print(L"ImageIndex 0x%x too big\n", ImageIndex);
    927     return ;
    928   }
    929 
    930   Image = Fmp;
    931   ImageSize = 0;
    932   Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);
    933   if (Status != EFI_BUFFER_TOO_SMALL) {
    934     Print(L"Fmp->GetImage - %r\n", Status);
    935     return ;
    936   }
    937 
    938   Image = AllocatePool (ImageSize);
    939   if (Image == NULL) {
    940     Print(L"Allocate FmpImage 0x%x - %r\n", ImageSize, EFI_OUT_OF_RESOURCES);
    941     return ;
    942   }
    943 
    944   Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);
    945   if (EFI_ERROR(Status)) {
    946     Print(L"Fmp->GetImage - %r\n", Status);
    947     return ;
    948   }
    949 
    950   Status = WriteFileFromBuffer(ImageName, ImageSize, Image);
    951   Print(L"CapsuleApp: Dump %g ImageIndex (0x%x) to %s %r\n", ImageTypeId, ImageIndex, ImageName, Status);
    952 
    953   return ;
    954 }
    955