]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Application / CapsuleApp / CapsuleDump.c
index 9291ba3af358d594a8a2ee4b245e0f4480442ffc..26ad60ce592e3bafa1bc9a7f1c885b9289a471a5 100644 (file)
@@ -1,48 +1,29 @@
 /** @file\r
   Dump Capsule image information.\r
 \r
-  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
-#include <PiDxe.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/PrintLib.h>\r
-#include <Protocol/FirmwareManagement.h>\r
-#include <Guid/ImageAuthentication.h>\r
-#include <Guid/CapsuleReport.h>\r
-#include <Guid/SystemResourceTable.h>\r
-#include <Guid/FmpCapsule.h>\r
-#include <IndustryStandard/WindowsUxCapsule.h>\r
+#include "CapsuleApp.h"\r
 \r
 /**\r
-  Read a file.\r
+  Validate if it is valid capsule header\r
+\r
+  This function assumes the caller provided correct CapsuleHeader pointer\r
+  and CapsuleSize.\r
+\r
+  This function validates the fields in EFI_CAPSULE_HEADER.\r
 \r
-  @param[in] FileName        The file to be read.\r
-  @param[in] BufferSize      The file buffer size\r
-  @param[in] Buffer          The file buffer\r
+  @param[in] CapsuleHeader  Points to a capsule header.\r
+  @param[in] CapsuleSize    Size of the whole capsule image.\r
 \r
-  @retval EFI_SUCCESS    Read file successfully\r
-  @retval EFI_NOT_FOUND  File not found\r
 **/\r
-EFI_STATUS\r
-ReadFileToBuffer (\r
-  IN  CHAR16                               *FileName,\r
-  OUT UINTN                                *BufferSize,\r
-  OUT VOID                                 **Buffer\r
+BOOLEAN\r
+IsValidCapsuleHeader (\r
+  IN EFI_CAPSULE_HEADER  *CapsuleHeader,\r
+  IN UINT64              CapsuleSize\r
   );\r
 \r
 /**\r
@@ -55,53 +36,22 @@ DumpUxCapsule (
   IN EFI_CAPSULE_HEADER  *CapsuleHeader\r
   )\r
 {\r
-  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;\r
-  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;\r
-  Print(L"[UxCapusule]\n");\r
-  Print(L"CapsuleHeader:\n");\r
-  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);\r
-  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);\r
-  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);\r
-  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule->CapsuleHeader.CapsuleImageSize);\r
-  Print(L"ImagePayload:\n");\r
-  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);\r
-  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);\r
-  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);\r
-  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);\r
-  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);\r
-  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);\r
-}\r
-\r
-/**\r
-  Dump FMP image authentication information.\r
+  EFI_DISPLAY_CAPSULE  *DisplayCapsule;\r
 \r
-  @param[in] Image      The FMP capsule image\r
-  @param[in] ImageSize  The size of the FMP capsule image in bytes.\r
-\r
-  @return the size of FMP authentication.\r
-**/\r
-UINTN\r
-DumpImageAuthentication (\r
-  IN VOID   *Image,\r
-  IN UINTN  ImageSize\r
-  )\r
-{\r
-  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;\r
-\r
-  ImageAuthentication = Image;\r
-  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||\r
-      CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertTypeRsa2048Sha256Guid)) {\r
-    Print(L"[ImageAuthentication]\n");\r
-    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);\r
-    Print(L"WIN_CERTIFICATE:\n");\r
-    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);\r
-    Print(L"  wRevision        - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wRevision);\r
-    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wCertificateType);\r
-    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);\r
-    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication->AuthInfo.Hdr.dwLength;\r
-  } else {\r
-    return 0;\r
-  }\r
+  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;\r
+  Print (L"[UxCapsule]\n");\r
+  Print (L"CapsuleHeader:\n");\r
+  Print (L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);\r
+  Print (L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);\r
+  Print (L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);\r
+  Print (L"  CapsuleImageSize - 0x%x\n", DisplayCapsule->CapsuleHeader.CapsuleImageSize);\r
+  Print (L"ImagePayload:\n");\r
+  Print (L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);\r
+  Print (L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);\r
+  Print (L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);\r
+  Print (L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);\r
+  Print (L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);\r
+  Print (L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);\r
 }\r
 \r
 /**\r
@@ -120,34 +70,37 @@ DumpFmpCapsule (
   UINTN                                         Count;\r
   EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;\r
 \r
-  Print(L"[FmpCapusule]\n");\r
-  Print(L"CapsuleHeader:\n");\r
-  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);\r
-  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);\r
-  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);\r
-  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);\r
+  Print (L"[FmpCapsule]\n");\r
+  Print (L"CapsuleHeader:\n");\r
+  Print (L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);\r
+  Print (L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);\r
+  Print (L"  Flags            - 0x%x\n", CapsuleHeader->Flags);\r
+  Print (L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);\r
 \r
   FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);\r
-  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);\r
-  Print(L"FmpHeader:\n");\r
-  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);\r
-  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);\r
-  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);\r
+  ItemOffsetList   = (UINT64 *)(FmpCapsuleHeader + 1);\r
+  Print (L"FmpHeader:\n");\r
+  Print (L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);\r
+  Print (L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);\r
+  Print (L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);\r
   Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;\r
   for (Index = 0; Index < Count; Index++) {\r
-    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);\r
+    Print (L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);\r
   }\r
 \r
   for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {\r
-    Print(L"FmpPayload[%d] ImageHeader:\n", Index);\r
+    Print (L"FmpPayload[%d] ImageHeader:\n", Index);\r
     FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);\r
-    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);\r
-    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);\r
-    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);\r
-    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);\r
-    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);\r
-    if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
-      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader->UpdateHardwareInstance);\r
+    Print (L"  Version                - 0x%x\n", FmpImageHeader->Version);\r
+    Print (L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);\r
+    Print (L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);\r
+    Print (L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);\r
+    Print (L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);\r
+    if (FmpImageHeader->Version >= 2) {\r
+      Print (L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader->UpdateHardwareInstance);\r
+      if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
+        Print (L"  ImageCapsuleSupport    - 0x%lx\n", FmpImageHeader->ImageCapsuleSupport);\r
+      }\r
     }\r
   }\r
 }\r
@@ -162,7 +115,7 @@ DumpFmpCapsule (
 **/\r
 BOOLEAN\r
 IsNestedFmpCapsule (\r
-  IN EFI_CAPSULE_HEADER         *CapsuleHeader\r
+  IN EFI_CAPSULE_HEADER  *CapsuleHeader\r
   )\r
 {\r
   EFI_STATUS                 Status;\r
@@ -177,12 +130,12 @@ IsNestedFmpCapsule (
   // Check ESRT\r
   //\r
   EsrtGuidFound = FALSE;\r
-  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);\r
-  if (!EFI_ERROR(Status)) {\r
+  Status        = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);\r
+  if (!EFI_ERROR (Status)) {\r
     ASSERT (Esrt != NULL);\r
     EsrtEntry = (VOID *)(Esrt + 1);\r
     for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {\r
-      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {\r
+      if (CompareGuid (&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {\r
         EsrtGuidFound = TRUE;\r
         break;\r
       }\r
@@ -198,13 +151,15 @@ IsNestedFmpCapsule (
   // FMP GUID after ESRT one\r
   //\r
   NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);\r
-  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize - (UINTN)NestedCapsuleHeader;\r
-  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {\r
+  NestedCapsuleSize   = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize- (UINTN)NestedCapsuleHeader;\r
+  if (NestedCapsuleSize < sizeof (EFI_CAPSULE_HEADER)) {\r
     return FALSE;\r
   }\r
-  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {\r
+\r
+  if (!CompareGuid (&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {\r
     return FALSE;\r
   }\r
+\r
   return TRUE;\r
 }\r
 \r
@@ -218,42 +173,53 @@ IsNestedFmpCapsule (
 **/\r
 EFI_STATUS\r
 DumpCapsule (\r
-  IN CHAR16                                        *CapsuleName\r
+  IN CHAR16  *CapsuleName\r
   )\r
 {\r
-  VOID                                          *Buffer;\r
-  UINTN                                         FileSize;\r
-  EFI_CAPSULE_HEADER                            *CapsuleHeader;\r
-  EFI_STATUS                                    Status;\r
-\r
-  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);\r
-  if (EFI_ERROR(Status)) {\r
-    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);\r
+  VOID                *Buffer;\r
+  UINTN               FileSize;\r
+  EFI_CAPSULE_HEADER  *CapsuleHeader;\r
+  EFI_STATUS          Status;\r
+\r
+  Buffer = NULL;\r
+  Status = ReadFileToBuffer (CapsuleName, &FileSize, &Buffer);\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);\r
+    goto Done;\r
+  }\r
+\r
+  if (!IsValidCapsuleHeader (Buffer, FileSize)) {\r
+    Print (L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);\r
+    Status = EFI_INVALID_PARAMETER;\r
     goto Done;\r
   }\r
 \r
   CapsuleHeader = Buffer;\r
-  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {\r
-    DumpUxCapsule(CapsuleHeader);\r
+  if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {\r
+    DumpUxCapsule (CapsuleHeader);\r
     Status = EFI_SUCCESS;\r
     goto Done;\r
   }\r
 \r
-  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {\r
-    DumpFmpCapsule(CapsuleHeader);\r
+  if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {\r
+    DumpFmpCapsule (CapsuleHeader);\r
   }\r
-  if (IsNestedFmpCapsule(CapsuleHeader)) {\r
-    Print(L"[NestedCapusule]\n");\r
-    Print(L"CapsuleHeader:\n");\r
-    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);\r
-    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);\r
-    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);\r
-    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);\r
-    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));\r
+\r
+  if (IsNestedFmpCapsule (CapsuleHeader)) {\r
+    Print (L"[NestedCapsule]\n");\r
+    Print (L"CapsuleHeader:\n");\r
+    Print (L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);\r
+    Print (L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);\r
+    Print (L"  Flags            - 0x%x\n", CapsuleHeader->Flags);\r
+    Print (L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);\r
+    DumpFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));\r
   }\r
 \r
 Done:\r
-  FreePool(Buffer);\r
+  if (Buffer != NULL) {\r
+    FreePool (Buffer);\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -264,7 +230,7 @@ Done:
   @retval EFI_UNSUPPORTED        Input parameter is not valid.\r
 **/\r
 EFI_STATUS\r
-DmpCapsuleStatusVariable (\r
+DumpCapsuleStatusVariable (\r
   VOID\r
   )\r
 {\r
@@ -277,81 +243,84 @@ DmpCapsuleStatusVariable (
   UINTN                               CapsuleFileNameSize;\r
   CHAR16                              CapsuleIndexData[12];\r
   CHAR16                              *CapsuleIndex;\r
+  CHAR16                              *CapsuleFileName;\r
+  CHAR16                              *CapsuleTarget;\r
 \r
-  Status = GetVariable2(\r
+  Status = GetVariable2 (\r
              L"CapsuleMax",\r
              &gEfiCapsuleReportGuid,\r
              (VOID **)&CapsuleIndex,\r
              NULL\r
              );\r
-  if (!EFI_ERROR(Status)) {\r
-    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));\r
+  if (!EFI_ERROR (Status)) {\r
+    ASSERT (CapsuleIndex != NULL);\r
+    CopyMem (CapsuleIndexData, CapsuleIndex, 11 * sizeof (CHAR16));\r
     CapsuleIndexData[11] = 0;\r
-    Print(L"CapsuleMax - %s\n", CapsuleIndexData);\r
-    FreePool(CapsuleIndex);\r
+    Print (L"CapsuleMax - %s\n", CapsuleIndexData);\r
+    FreePool (CapsuleIndex);\r
   }\r
-  Status = GetVariable2(\r
+\r
+  Status = GetVariable2 (\r
              L"CapsuleLast",\r
              &gEfiCapsuleReportGuid,\r
              (VOID **)&CapsuleIndex,\r
              NULL\r
              );\r
-  if (!EFI_ERROR(Status)) {\r
-    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));\r
+  if (!EFI_ERROR (Status)) {\r
+    ASSERT (CapsuleIndex != NULL);\r
+    CopyMem (CapsuleIndexData, CapsuleIndex, 11 * sizeof (CHAR16));\r
     CapsuleIndexData[11] = 0;\r
-    Print(L"CapsuleLast - %s\n", CapsuleIndexData);\r
-    FreePool(CapsuleIndex);\r
+    Print (L"CapsuleLast - %s\n", CapsuleIndexData);\r
+    FreePool (CapsuleIndex);\r
   }\r
 \r
-\r
-  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]), L"Capsule");\r
+  StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CapsuleVarName[0]), L"Capsule");\r
   TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
-  Index = 0;\r
+  Index       = 0;\r
 \r
   while (TRUE) {\r
-    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);\r
+    UnicodeSPrint (TempVarName, 5 * sizeof (CHAR16), L"%04x", Index);\r
 \r
     Status = GetVariable2 (\r
                CapsuleVarName,\r
                &gEfiCapsuleReportGuid,\r
-               (VOID **) &CapsuleResult,\r
+               (VOID **)&CapsuleResult,\r
                NULL\r
                );\r
     if (Status == EFI_NOT_FOUND) {\r
       break;\r
-    } else if (EFI_ERROR(Status)) {\r
+    } else if (EFI_ERROR (Status)) {\r
       continue;\r
     }\r
+\r
     ASSERT (CapsuleResult != NULL);\r
 \r
     //\r
     // display capsule process status\r
     //\r
-    if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {\r
+    if (CapsuleResult->VariableTotalSize >= sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {\r
       Print (L"CapsuleName: %s\n", CapsuleVarName);\r
       Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);\r
       Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);\r
       Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);\r
     }\r
 \r
-    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {\r
-      if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {\r
+    if (CompareGuid (&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {\r
+      if (CapsuleResult->VariableTotalSize >= sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof (CHAR16) * 2) {\r
         CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);\r
-        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);\r
-        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);\r
-        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp->UpdateImageIndex);\r
-        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp->UpdateImageTypeId);\r
-        if (CapsuleResult->VariableTotalSize > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {\r
-          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));\r
-          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));\r
-          if (CapsuleResult->VariableTotalSize > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapsuleFileNameSize) {\r
-            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp + 1) + CapsuleFileNameSize);\r
-          }\r
-        }\r
+        Print (L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);\r
+        Print (L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);\r
+        Print (L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp->UpdateImageIndex);\r
+        Print (L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp->UpdateImageTypeId);\r
+        CapsuleFileName = (CHAR16 *)(CapsuleResultFmp + 1);\r
+        Print (L"  Capsule FMP CapsuleFileName: \"%s\"\n", CapsuleFileName);\r
+        CapsuleFileNameSize = StrSize (CapsuleFileName);\r
+        CapsuleTarget       = (CHAR16 *)((UINTN)CapsuleFileName + CapsuleFileNameSize);\r
+        Print (L"  Capsule FMP CapsuleTarget: \"%s\"\n", CapsuleTarget);\r
       }\r
     }\r
 \r
-    FreePool(CapsuleResult);\r
+    FreePool (CapsuleResult);\r
 \r
     Index++;\r
     if (Index > 0xFFFF) {\r
@@ -362,14 +331,14 @@ DmpCapsuleStatusVariable (
   return EFI_SUCCESS;\r
 }\r
 \r
-CHAR8 *mFwTypeString[] = {\r
+CHAR8  *mFwTypeString[] = {\r
   "Unknown",\r
   "SystemFirmware",\r
   "DeviceFirmware",\r
   "UefiDriver",\r
 };\r
 \r
-CHAR8 *mLastAttemptStatusString[] = {\r
+CHAR8  *mLastAttemptStatusString[] = {\r
   "Success",\r
   "Error: Unsuccessful",\r
   "Error: Insufficient Resources",\r
@@ -378,6 +347,7 @@ CHAR8 *mLastAttemptStatusString[] = {
   "Error: Auth Error",\r
   "Error: Power Event AC",\r
   "Error: Power Event Battery",\r
+  "Error: Unsatisfied Dependencies",\r
 };\r
 \r
 /**\r
@@ -392,7 +362,7 @@ FwTypeToString (
   IN UINT32  FwType\r
   )\r
 {\r
-  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {\r
+  if (FwType < sizeof (mFwTypeString) / sizeof (mFwTypeString[0])) {\r
     return mFwTypeString[FwType];\r
   } else {\r
     return "Invalid";\r
@@ -411,7 +381,7 @@ LastAttemptStatusToString (
   IN UINT32  LastAttemptStatus\r
   )\r
 {\r
-  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) / sizeof(mLastAttemptStatusString[0])) {\r
+  if (LastAttemptStatus < sizeof (mLastAttemptStatusString) / sizeof (mLastAttemptStatusString[0])) {\r
     return mLastAttemptStatusString[LastAttemptStatus];\r
   } else {\r
     return "Error: Unknown";\r
@@ -428,16 +398,13 @@ DumpEsrtEntry (
   IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry\r
   )\r
 {\r
-  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);\r
-  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType, FwTypeToString(EsrtEntry->FwType));\r
-  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);\r
-  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);\r
-  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);\r
-  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET);\r
-  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);\r
-  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_INITIATE_RESET);\r
-  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);\r
-  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus, LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));\r
+  Print (L"  FwClass                  - %g\n", &EsrtEntry->FwClass);\r
+  Print (L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType, FwTypeToString (EsrtEntry->FwType));\r
+  Print (L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);\r
+  Print (L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);\r
+  Print (L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);\r
+  Print (L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);\r
+  Print (L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus, LastAttemptStatusToString (EsrtEntry->LastAttemptStatus));\r
 }\r
 \r
 /**\r
@@ -454,18 +421,18 @@ DumpEsrt (
   EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;\r
 \r
   if (Esrt == NULL) {\r
-    return ;\r
+    return;\r
   }\r
 \r
-  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");\r
-  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);\r
-  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);\r
-  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);\r
+  Print (L"EFI_SYSTEM_RESOURCE_TABLE:\n");\r
+  Print (L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);\r
+  Print (L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);\r
+  Print (L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);\r
 \r
   EsrtEntry = (VOID *)(Esrt + 1);\r
   for (Index = 0; Index < Esrt->FwResourceCount; Index++) {\r
-    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);\r
-    DumpEsrtEntry(EsrtEntry);\r
+    Print (L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);\r
+    DumpEsrtEntry (EsrtEntry);\r
     EsrtEntry++;\r
   }\r
 }\r
@@ -481,17 +448,558 @@ DumpEsrtData (
   EFI_STATUS                 Status;\r
   EFI_SYSTEM_RESOURCE_TABLE  *Esrt;\r
 \r
-  Print(L"##############\n");\r
-  Print(L"# ESRT TABLE #\n");\r
-  Print(L"##############\n");\r
+  Print (L"##############\n");\r
+  Print (L"# ESRT TABLE #\n");\r
+  Print (L"##############\n");\r
 \r
   Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);\r
-  if (EFI_ERROR(Status)) {\r
-    Print(L"ESRT - %r\n", Status);\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"ESRT - %r\n", Status);\r
     return;\r
   }\r
-  DumpEsrt(Esrt);\r
-  Print(L"\n");\r
+\r
+  DumpEsrt (Esrt);\r
+  Print (L"\n");\r
+}\r
+\r
+/**\r
+  Dump capsule information from CapsuleHeader\r
+\r
+  @param[in] CapsuleHeader       The CapsuleHeader of the capsule image.\r
+\r
+  @retval EFI_SUCCESS            The capsule information is dumped.\r
+\r
+**/\r
+EFI_STATUS\r
+DumpCapsuleFromBuffer (\r
+  IN EFI_CAPSULE_HEADER  *CapsuleHeader\r
+  )\r
+{\r
+  if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {\r
+    DumpUxCapsule (CapsuleHeader);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {\r
+    DumpFmpCapsule (CapsuleHeader);\r
+  }\r
+\r
+  if (IsNestedFmpCapsule (CapsuleHeader)) {\r
+    Print (L"[NestedCapusule]\n");\r
+    Print (L"CapsuleHeader:\n");\r
+    Print (L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);\r
+    Print (L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);\r
+    Print (L"  Flags            - 0x%x\n", CapsuleHeader->Flags);\r
+    Print (L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);\r
+    DumpFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This routine is called to upper case given unicode string.\r
+\r
+  @param[in]   Str              String to upper case\r
+\r
+  @retval upper cased string after process\r
+\r
+**/\r
+STATIC\r
+CHAR16 *\r
+UpperCaseString (\r
+  IN CHAR16  *Str\r
+  )\r
+{\r
+  CHAR16  *Cptr;\r
+\r
+  for (Cptr = Str; *Cptr != L'\0'; Cptr++) {\r
+    if ((L'a' <= *Cptr) && (*Cptr <= L'z')) {\r
+      *Cptr = *Cptr - L'a' + L'A';\r
+    }\r
+  }\r
+\r
+  return Str;\r
+}\r
+\r
+/**\r
+  This routine is used to return substring before period '.' or '\0'\r
+  Caller should respsonsible of substr space allocation & free\r
+\r
+  @param[in]   Str              String to check\r
+  @param[out]  SubStr           First part of string before period or '\0'\r
+  @param[out]  SubStrLen        Length of first part of string\r
+\r
+**/\r
+STATIC\r
+VOID\r
+GetSubStringBeforePeriod (\r
+  IN  CHAR16  *Str,\r
+  OUT CHAR16  *SubStr,\r
+  OUT UINTN   *SubStrLen\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Str[Index] != L'.' && Str[Index] != L'\0'; Index++) {\r
+    SubStr[Index] = Str[Index];\r
+  }\r
+\r
+  SubStr[Index] = L'\0';\r
+  *SubStrLen    = Index;\r
+}\r
+\r
+/**\r
+  This routine pad the string in tail with input character.\r
+\r
+  @param[in]   StrBuf            Str buffer to be padded, should be enough room for\r
+  @param[in]   PadLen            Expected padding length\r
+  @param[in]   Character         Character used to pad\r
+\r
+**/\r
+STATIC\r
+VOID\r
+PadStrInTail (\r
+  IN CHAR16  *StrBuf,\r
+  IN UINTN   PadLen,\r
+  IN CHAR16  Character\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; StrBuf[Index] != L'\0'; Index++) {\r
+  }\r
+\r
+  while (PadLen != 0) {\r
+    StrBuf[Index] = Character;\r
+    Index++;\r
+    PadLen--;\r
+  }\r
+\r
+  StrBuf[Index] = L'\0';\r
+}\r
+\r
+/**\r
+  This routine find the offset of the last period '.' of string. if No period exists\r
+  function FileNameExtension is set to L'\0'\r
+\r
+  @param[in]   FileName           File name to split between last period\r
+  @param[out]  FileNameFirst      First FileName before last period\r
+  @param[out]  FileNameExtension  FileName after last period\r
+\r
+**/\r
+STATIC\r
+VOID\r
+SplitFileNameExtension (\r
+  IN  CHAR16  *FileName,\r
+  OUT CHAR16  *FileNameFirst,\r
+  OUT CHAR16  *FileNameExtension\r
+  )\r
+{\r
+  UINTN  Index;\r
+  UINTN  StringLen;\r
+\r
+  StringLen = StrLen (FileName);\r
+  for (Index = StringLen; Index > 0 && FileName[Index] != L'.'; Index--) {\r
+  }\r
+\r
+  //\r
+  // No period exists. No FileName Extension\r
+  //\r
+  if ((Index == 0) && (FileName[Index] != L'.')) {\r
+    FileNameExtension[0] = L'\0';\r
+    Index                = StringLen;\r
+  } else {\r
+    StrCpyS (FileNameExtension, MAX_FILE_NAME_LEN, &FileName[Index+1]);\r
+  }\r
+\r
+  //\r
+  // Copy First file name\r
+  //\r
+  StrnCpyS (FileNameFirst, MAX_FILE_NAME_LEN, FileName, Index);\r
+  FileNameFirst[Index] = L'\0';\r
+}\r
+\r
+/**\r
+  The function is called by PerformQuickSort to sort file name in alphabet.\r
+\r
+  @param[in] Left            The pointer to first buffer.\r
+  @param[in] Right           The pointer to second buffer.\r
+\r
+  @retval 0                  Buffer1 equal to Buffer2.\r
+  @return <0                 Buffer1 is less than Buffer2.\r
+  @return >0                 Buffer1 is greater than Buffer2.\r
+\r
+**/\r
+INTN\r
+CompareFileNameInAlphabet (\r
+  IN VOID  *Left,\r
+  IN VOID  *Right\r
+  )\r
+{\r
+  EFI_FILE_INFO  *FileInfo1;\r
+  EFI_FILE_INFO  *FileInfo2;\r
+  CHAR16         FileName1[MAX_FILE_NAME_SIZE];\r
+  CHAR16         FileExtension1[MAX_FILE_NAME_SIZE];\r
+  CHAR16         FileName2[MAX_FILE_NAME_SIZE];\r
+  CHAR16         FileExtension2[MAX_FILE_NAME_SIZE];\r
+  CHAR16         TempSubStr1[MAX_FILE_NAME_SIZE];\r
+  CHAR16         TempSubStr2[MAX_FILE_NAME_SIZE];\r
+  UINTN          SubStrLen1;\r
+  UINTN          SubStrLen2;\r
+  INTN           SubStrCmpResult;\r
+\r
+  FileInfo1 = (EFI_FILE_INFO *)(*(UINTN *)Left);\r
+  FileInfo2 = (EFI_FILE_INFO *)(*(UINTN *)Right);\r
+\r
+  SplitFileNameExtension (FileInfo1->FileName, FileName1, FileExtension1);\r
+  SplitFileNameExtension (FileInfo2->FileName, FileName2, FileExtension2);\r
+\r
+  UpperCaseString (FileName1);\r
+  UpperCaseString (FileName2);\r
+\r
+  GetSubStringBeforePeriod (FileName1, TempSubStr1, &SubStrLen1);\r
+  GetSubStringBeforePeriod (FileName2, TempSubStr2, &SubStrLen2);\r
+\r
+  if (SubStrLen1 > SubStrLen2) {\r
+    //\r
+    // Substr in NewFileName is longer.  Pad tail with SPACE\r
+    //\r
+    PadStrInTail (TempSubStr2, SubStrLen1 - SubStrLen2, L' ');\r
+  } else if (SubStrLen1 < SubStrLen2) {\r
+    //\r
+    // Substr in ListedFileName is longer. Pad tail with SPACE\r
+    //\r
+    PadStrInTail (TempSubStr1, SubStrLen2 - SubStrLen1, L' ');\r
+  }\r
+\r
+  SubStrCmpResult = StrnCmp (TempSubStr1, TempSubStr2, MAX_FILE_NAME_LEN);\r
+  if (SubStrCmpResult != 0) {\r
+    return SubStrCmpResult;\r
+  }\r
+\r
+  UpperCaseString (FileExtension1);\r
+  UpperCaseString (FileExtension2);\r
+\r
+  return StrnCmp (FileExtension1, FileExtension2, MAX_FILE_NAME_LEN);\r
+}\r
+\r
+/**\r
+  Dump capsule information from disk.\r
+\r
+  @param[in] Fs                  The device path of disk.\r
+  @param[in] DumpCapsuleInfo     The flag to indicate whether to dump the capsule inforomation.\r
+\r
+  @retval EFI_SUCCESS            The capsule information is dumped.\r
+\r
+**/\r
+EFI_STATUS\r
+DumpCapsuleFromDisk (\r
+  IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs,\r
+  IN BOOLEAN                          DumpCapsuleInfo\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_FILE       *Root;\r
+  EFI_FILE       *DirHandle;\r
+  EFI_FILE       *FileHandle;\r
+  UINTN          Index;\r
+  UINTN          FileSize;\r
+  VOID           *FileBuffer;\r
+  EFI_FILE_INFO  **FileInfoBuffer;\r
+  EFI_FILE_INFO  *FileInfo;\r
+  UINTN          FileCount;\r
+  BOOLEAN        NoFile;\r
+\r
+  DirHandle      = NULL;\r
+  FileHandle     = NULL;\r
+  Index          = 0;\r
+  FileInfoBuffer = NULL;\r
+  FileInfo       = NULL;\r
+  FileCount      = 0;\r
+  NoFile         = FALSE;\r
+\r
+  Status = Fs->OpenVolume (Fs, &Root);\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"Cannot open volume. Status = %r\n", Status);\r
+    goto Done;\r
+  }\r
+\r
+  Status = Root->Open (Root, &DirHandle, EFI_CAPSULE_FILE_DIRECTORY, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"Cannot open %s. Status = %r\n", EFI_CAPSULE_FILE_DIRECTORY, Status);\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Get file count first\r
+  //\r
+  Status = FileHandleFindFirstFile (DirHandle, &FileInfo);\r
+  do {\r
+    if (EFI_ERROR (Status) || (FileInfo == NULL)) {\r
+      Print (L"Get File Info Fail. Status = %r\n", Status);\r
+      goto Done;\r
+    }\r
+\r
+    if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) != 0) {\r
+      FileCount++;\r
+    }\r
+\r
+    Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile);\r
+    if (EFI_ERROR (Status)) {\r
+      Print (L"Get Next File Fail. Status = %r\n", Status);\r
+      goto Done;\r
+    }\r
+  } while (!NoFile);\r
+\r
+  if (FileCount == 0) {\r
+    Print (L"Error: No capsule file found!\n");\r
+    Status = EFI_NOT_FOUND;\r
+    goto Done;\r
+  }\r
+\r
+  FileInfoBuffer = AllocateZeroPool (sizeof (FileInfo) * FileCount);\r
+  if (FileInfoBuffer == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  NoFile = FALSE;\r
+\r
+  //\r
+  // Get all file info\r
+  //\r
+  Status = FileHandleFindFirstFile (DirHandle, &FileInfo);\r
+  do {\r
+    if (EFI_ERROR (Status) || (FileInfo == NULL)) {\r
+      Print (L"Get File Info Fail. Status = %r\n", Status);\r
+      goto Done;\r
+    }\r
+\r
+    if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) != 0) {\r
+      FileInfoBuffer[Index++] = AllocateCopyPool ((UINTN)FileInfo->Size, FileInfo);\r
+    }\r
+\r
+    Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile);\r
+    if (EFI_ERROR (Status)) {\r
+      Print (L"Get Next File Fail. Status = %r\n", Status);\r
+      goto Done;\r
+    }\r
+  } while (!NoFile);\r
+\r
+  //\r
+  // Sort FileInfoBuffer by alphabet order\r
+  //\r
+  PerformQuickSort (\r
+    FileInfoBuffer,\r
+    FileCount,\r
+    sizeof (FileInfo),\r
+    (SORT_COMPARE)CompareFileNameInAlphabet\r
+    );\r
+\r
+  Print (L"The capsules will be performed by following order:\n");\r
+\r
+  for (Index = 0; Index < FileCount; Index++) {\r
+    Print (L"  %d.%s\n", Index + 1, FileInfoBuffer[Index]->FileName);\r
+  }\r
+\r
+  if (!DumpCapsuleInfo) {\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+  Print (L"The infomation of the capsules:\n");\r
+\r
+  for (Index = 0; Index < FileCount; Index++) {\r
+    FileHandle = NULL;\r
+    Status     = DirHandle->Open (DirHandle, &FileHandle, FileInfoBuffer[Index]->FileName, EFI_FILE_MODE_READ, 0);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    Status = FileHandleGetSize (FileHandle, (UINT64 *)&FileSize);\r
+    if (EFI_ERROR (Status)) {\r
+      Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status);\r
+      FileHandleClose (FileHandle);\r
+      goto Done;\r
+    }\r
+\r
+    FileBuffer = AllocatePool (FileSize);\r
+    if (FileBuffer == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+\r
+    Status = FileHandleRead (FileHandle, &FileSize, FileBuffer);\r
+    if (EFI_ERROR (Status)) {\r
+      Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status);\r
+      FileHandleClose (FileHandle);\r
+      FreePool (FileBuffer);\r
+      goto Done;\r
+    }\r
+\r
+    Print (L"**************************\n");\r
+    Print (L"  %d.%s:\n", Index + 1, FileInfoBuffer[Index]->FileName);\r
+    Print (L"**************************\n");\r
+    DumpCapsuleFromBuffer ((EFI_CAPSULE_HEADER *)FileBuffer);\r
+    FileHandleClose (FileHandle);\r
+    FreePool (FileBuffer);\r
+  }\r
+\r
+Done:\r
+  if (FileInfoBuffer != NULL) {\r
+    for (Index = 0; Index < FileCount; Index++) {\r
+      if (FileInfoBuffer[Index] != NULL) {\r
+        FreePool (FileInfoBuffer[Index]);\r
+      }\r
+    }\r
+\r
+    FreePool (FileInfoBuffer);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Dump capsule inforomation form Gather list.\r
+\r
+  @param[in]  BlockDescriptors The block descriptors for the capsule images\r
+  @param[in]  DumpCapsuleInfo  The flag to indicate whether to dump the capsule inforomation.\r
+\r
+**/\r
+VOID\r
+DumpBlockDescriptors (\r
+  IN EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors,\r
+  IN BOOLEAN                       DumpCapsuleInfo\r
+  )\r
+{\r
+  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;\r
+\r
+  TempBlockPtr = BlockDescriptors;\r
+\r
+  while (TRUE) {\r
+    if (TempBlockPtr->Length != 0) {\r
+      if (DumpCapsuleInfo) {\r
+        Print (L"******************************************************\n");\r
+      }\r
+\r
+      Print (L"Capsule data starts at 0x%08x with size 0x%08x\n", TempBlockPtr->Union.DataBlock, TempBlockPtr->Length);\r
+      if (DumpCapsuleInfo) {\r
+        Print (L"******************************************************\n");\r
+        DumpCapsuleFromBuffer ((EFI_CAPSULE_HEADER *)(UINTN)TempBlockPtr->Union.DataBlock);\r
+      }\r
+\r
+      TempBlockPtr += 1;\r
+    } else {\r
+      if (TempBlockPtr->Union.ContinuationPointer == (UINTN)NULL) {\r
+        break;\r
+      } else {\r
+        TempBlockPtr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)TempBlockPtr->Union.ContinuationPointer;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Dump Provisioned Capsule.\r
+\r
+  @param[in]  DumpCapsuleInfo  The flag to indicate whether to dump the capsule inforomation.\r
+\r
+**/\r
+VOID\r
+DumpProvisionedCapsule (\r
+  IN BOOLEAN  DumpCapsuleInfo\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  CHAR16                           CapsuleVarName[30];\r
+  CHAR16                           *TempVarName;\r
+  UINTN                            Index;\r
+  EFI_PHYSICAL_ADDRESS             *CapsuleDataPtr64;\r
+  UINT16                           *BootNext;\r
+  CHAR16                           BootOptionName[20];\r
+  EFI_BOOT_MANAGER_LOAD_OPTION     BootNextOptionEntry;\r
+  EFI_DEVICE_PATH_PROTOCOL         *DevicePath;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;\r
+  EFI_SHELL_PROTOCOL               *ShellProtocol;\r
+\r
+  Index            = 0;\r
+  CapsuleDataPtr64 = NULL;\r
+  BootNext         = NULL;\r
+\r
+  ShellProtocol = GetShellProtocol ();\r
+  if (ShellProtocol == NULL) {\r
+    Print (L"Get Shell Protocol Fail\n");\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Dump capsule provisioned on Memory\r
+  //\r
+  Print (L"#########################\n");\r
+  Print (L"### Capsule on Memory ###\n");\r
+  Print (L"#########################\n");\r
+  StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CHAR16), EFI_CAPSULE_VARIABLE_NAME);\r
+  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
+  while (TRUE) {\r
+    if (Index > 0) {\r
+      UnicodeValueToStringS (\r
+        TempVarName,\r
+        sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),\r
+        0,\r
+        Index,\r
+        0\r
+        );\r
+    }\r
+\r
+    Status = GetVariable2 (\r
+               CapsuleVarName,\r
+               &gEfiCapsuleVendorGuid,\r
+               (VOID **)&CapsuleDataPtr64,\r
+               NULL\r
+               );\r
+    if (EFI_ERROR (Status) || (CapsuleDataPtr64 == NULL)) {\r
+      if (Index == 0) {\r
+        Print (L"No data.\n");\r
+      }\r
+\r
+      break;\r
+    }\r
+\r
+    Index++;\r
+    Print (L"Capsule Description at 0x%08x\n", *CapsuleDataPtr64);\r
+    DumpBlockDescriptors ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)*CapsuleDataPtr64, DumpCapsuleInfo);\r
+  }\r
+\r
+  //\r
+  // Dump capsule provisioned on Disk\r
+  //\r
+  Print (L"#########################\n");\r
+  Print (L"### Capsule on Disk #####\n");\r
+  Print (L"#########################\n");\r
+  Status = GetVariable2 (\r
+             L"BootNext",\r
+             &gEfiGlobalVariableGuid,\r
+             (VOID **)&BootNext,\r
+             NULL\r
+             );\r
+  if (EFI_ERROR (Status) || (BootNext == NULL)) {\r
+    Print (L"Get BootNext Variable Fail. Status = %r\n", Status);\r
+  } else {\r
+    UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", *BootNext);\r
+    Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BootNextOptionEntry);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Display description and device path\r
+      //\r
+      GetEfiSysPartitionFromBootOptionFilePath (BootNextOptionEntry.FilePath, &DevicePath, &Fs);\r
+      if (!EFI_ERROR (Status)) {\r
+        Print (L"Capsules are provisioned on BootOption: %s\n", BootNextOptionEntry.Description);\r
+        Print (L"    %s %s\n", ShellProtocol->GetMapFromDevicePath (&DevicePath), ConvertDevicePathToText (DevicePath, TRUE, TRUE));\r
+        DumpCapsuleFromDisk (Fs, DumpCapsuleInfo);\r
+      }\r
+    }\r
+  }\r
 }\r
 \r
 /**\r
@@ -507,55 +1015,70 @@ DumpEsrtData (
 **/\r
 VOID\r
 DumpFmpImageInfo (\r
-  IN UINTN                           ImageInfoSize,\r
-  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,\r
-  IN UINT32                          DescriptorVersion,\r
-  IN UINT8                           DescriptorCount,\r
-  IN UINTN                           DescriptorSize,\r
-  IN UINT32                          PackageVersion,\r
-  IN CHAR16                          *PackageVersionName\r
+  IN UINTN                          ImageInfoSize,\r
+  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR  *ImageInfo,\r
+  IN UINT32                         DescriptorVersion,\r
+  IN UINT8                          DescriptorCount,\r
+  IN UINTN                          DescriptorSize,\r
+  IN UINT32                         PackageVersion,\r
+  IN CHAR16                         *PackageVersionName\r
   )\r
 {\r
-  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;\r
-  UINTN                                         Index;\r
-\r
-  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);\r
-  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);\r
-  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);\r
-  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);\r
-  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);\r
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR  *CurrentImageInfo;\r
+  UINTN                          Index;\r
+  UINTN                          Index2;\r
+\r
+  Print (L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);\r
+  Print (L"  DescriptorCount    - 0x%x\n", DescriptorCount);\r
+  Print (L"  DescriptorSize     - 0x%x\n", DescriptorSize);\r
+  Print (L"  PackageVersion     - 0x%x\n", PackageVersion);\r
+  Print (L"  PackageVersionName - \"%s\"\n", PackageVersionName);\r
   CurrentImageInfo = ImageInfo;\r
   for (Index = 0; Index < DescriptorCount; Index++) {\r
-    Print(L"  ImageDescriptor (%d)\n", Index);\r
-    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);\r
-    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);\r
-    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);\r
-    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo->ImageIdName);\r
-    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);\r
-    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo->VersionName);\r
-    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);\r
-    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo->AttributesSupported);\r
-    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);\r
-    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);\r
-    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
-    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);\r
-    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);\r
-    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo->AttributesSetting);\r
-    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);\r
-    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);\r
-    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
-    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);\r
-    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);\r
-    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo->Compatibilities);\r
-    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo->Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);\r
+    Print (L"  ImageDescriptor (%d)\n", Index);\r
+    Print (L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);\r
+    Print (L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);\r
+    Print (L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);\r
+    Print (L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo->ImageIdName);\r
+    Print (L"    Version                     - 0x%x\n", CurrentImageInfo->Version);\r
+    Print (L"    VersionName                 - \"%s\"\n", CurrentImageInfo->VersionName);\r
+    Print (L"    Size                        - 0x%x\n", CurrentImageInfo->Size);\r
+    Print (L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo->AttributesSupported);\r
+    Print (L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);\r
+    Print (L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);\r
+    Print (L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
+    Print (L"      IN_USE                    - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);\r
+    Print (L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);\r
+    Print (L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo->AttributesSetting);\r
+    Print (L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);\r
+    Print (L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);\r
+    Print (L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
+    Print (L"      IN_USE                    - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);\r
+    Print (L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);\r
+    Print (L"    Compatibilities             - 0x%lx\n", CurrentImageInfo->Compatibilities);\r
+    Print (L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo->Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);\r
     if (DescriptorVersion > 1) {\r
-      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion);\r
+      Print (L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion);\r
       if (DescriptorVersion > 2) {\r
-        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo->LastAttemptVersion);\r
-        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo->LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));\r
-        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo->HardwareInstance);\r
+        Print (L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo->LastAttemptVersion);\r
+        Print (L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo->LastAttemptStatus, LastAttemptStatusToString (CurrentImageInfo->LastAttemptStatus));\r
+        Print (L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo->HardwareInstance);\r
+        if (DescriptorVersion > 3) {\r
+          Print (L"    Dependencies                - ");\r
+          if (CurrentImageInfo->Dependencies == NULL) {\r
+            Print (L"NULL\n");\r
+          } else {\r
+            Index2 = 0;\r
+            do {\r
+              Print (L"%02x ", CurrentImageInfo->Dependencies->Dependencies[Index2]);\r
+            } while (CurrentImageInfo->Dependencies->Dependencies[Index2++] != EFI_FMP_DEP_END);\r
+\r
+            Print (L"\n");\r
+          }\r
+        }\r
       }\r
     }\r
+\r
     //\r
     // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version\r
     //\r
@@ -574,24 +1097,24 @@ DumpFmpImageInfo (
 **/\r
 VOID\r
 DumpFmpPackageInfo (\r
-  IN UINT32                           PackageVersion,\r
-  IN CHAR16                           *PackageVersionName,\r
-  IN UINT32                           PackageVersionNameMaxLen,\r
-  IN UINT64                           AttributesSupported,\r
-  IN UINT64                           AttributesSetting\r
+  IN UINT32  PackageVersion,\r
+  IN CHAR16  *PackageVersionName,\r
+  IN UINT32  PackageVersionNameMaxLen,\r
+  IN UINT64  AttributesSupported,\r
+  IN UINT64  AttributesSetting\r
   )\r
 {\r
-  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);\r
-  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);\r
-  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);\r
-  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);\r
-  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);\r
-  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);\r
-  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
-  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);\r
-  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);\r
-  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);\r
-  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
+  Print (L"  PackageVersion              - 0x%x\n", PackageVersion);\r
+  Print (L"  PackageVersionName          - \"%s\"\n", PackageVersionName);\r
+  Print (L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);\r
+  Print (L"  AttributesSupported         - 0x%lx\n", AttributesSupported);\r
+  Print (L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);\r
+  Print (L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);\r
+  Print (L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
+  Print (L"  AttributesSetting           - 0x%lx\n", AttributesSetting);\r
+  Print (L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);\r
+  Print (L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);\r
+  Print (L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);\r
 }\r
 \r
 /**\r
@@ -602,25 +1125,25 @@ DumpFmpData (
   VOID\r
   )\r
 {\r
-  EFI_STATUS                                    Status;\r
-  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;\r
-  EFI_HANDLE                                    *HandleBuffer;\r
-  UINTN                                         NumberOfHandles;\r
-  UINTN                                         Index;\r
-  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;\r
-  UINTN                                         ImageInfoSize;\r
-  UINT32                                        FmpImageInfoDescriptorVer;\r
-  UINT8                                         FmpImageInfoCount;\r
-  UINTN                                         DescriptorSize;\r
-  UINT32                                        PackageVersion;\r
-  CHAR16                                        *PackageVersionName;\r
-  UINT32                                        PackageVersionNameMaxLen;\r
-  UINT64                                        AttributesSupported;\r
-  UINT64                                        AttributesSetting;\r
-\r
-  Print(L"############\n");\r
-  Print(L"# FMP DATA #\n");\r
-  Print(L"############\n");\r
+  EFI_STATUS                        Status;\r
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;\r
+  EFI_HANDLE                        *HandleBuffer;\r
+  UINTN                             NumberOfHandles;\r
+  UINTN                             Index;\r
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR     *FmpImageInfoBuf;\r
+  UINTN                             ImageInfoSize;\r
+  UINT32                            FmpImageInfoDescriptorVer;\r
+  UINT8                             FmpImageInfoCount;\r
+  UINTN                             DescriptorSize;\r
+  UINT32                            PackageVersion;\r
+  CHAR16                            *PackageVersionName;\r
+  UINT32                            PackageVersionNameMaxLen;\r
+  UINT64                            AttributesSupported;\r
+  UINT64                            AttributesSetting;\r
+\r
+  Print (L"############\n");\r
+  Print (L"# FMP DATA #\n");\r
+  Print (L"############\n");\r
   Status = gBS->LocateHandleBuffer (\r
                   ByProtocol,\r
                   &gEfiFirmwareManagementProtocolGuid,\r
@@ -628,32 +1151,32 @@ DumpFmpData (
                   &NumberOfHandles,\r
                   &HandleBuffer\r
                   );\r
-  if (EFI_ERROR(Status)) {\r
-    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"FMP protocol - %r\n", EFI_NOT_FOUND);\r
     return;\r
   }\r
 \r
   for (Index = 0; Index < NumberOfHandles; Index++) {\r
-    Status = gBS->HandleProtocol(\r
+    Status = gBS->HandleProtocol (\r
                     HandleBuffer[Index],\r
                     &gEfiFirmwareManagementProtocolGuid,\r
                     (VOID **)&Fmp\r
                     );\r
-    if (EFI_ERROR(Status)) {\r
+    if (EFI_ERROR (Status)) {\r
       continue;\r
     }\r
 \r
     ImageInfoSize = 0;\r
-    Status = Fmp->GetImageInfo (\r
-                    Fmp,\r
-                    &ImageInfoSize,\r
-                    NULL,\r
-                    NULL,\r
-                    NULL,\r
-                    NULL,\r
-                    NULL,\r
-                    NULL\r
-                    );\r
+    Status        = Fmp->GetImageInfo (\r
+                           Fmp,\r
+                           &ImageInfoSize,\r
+                           NULL,\r
+                           NULL,\r
+                           NULL,\r
+                           NULL,\r
+                           NULL,\r
+                           NULL\r
+                           );\r
     if (Status != EFI_BUFFER_TOO_SMALL) {\r
       continue;\r
     }\r
@@ -666,28 +1189,28 @@ DumpFmpData (
     }\r
 \r
     PackageVersionName = NULL;\r
-    Status = Fmp->GetImageInfo (\r
-                    Fmp,\r
-                    &ImageInfoSize,               // ImageInfoSize\r
-                    FmpImageInfoBuf,              // ImageInfo\r
-                    &FmpImageInfoDescriptorVer,   // DescriptorVersion\r
-                    &FmpImageInfoCount,           // DescriptorCount\r
-                    &DescriptorSize,              // DescriptorSize\r
-                    &PackageVersion,              // PackageVersion\r
-                    &PackageVersionName           // PackageVersionName\r
-                    );\r
+    Status             = Fmp->GetImageInfo (\r
+                                Fmp,\r
+                                &ImageInfoSize,             // ImageInfoSize\r
+                                FmpImageInfoBuf,            // ImageInfo\r
+                                &FmpImageInfoDescriptorVer, // DescriptorVersion\r
+                                &FmpImageInfoCount,         // DescriptorCount\r
+                                &DescriptorSize,            // DescriptorSize\r
+                                &PackageVersion,            // PackageVersion\r
+                                &PackageVersionName         // PackageVersionName\r
+                                );\r
 \r
     //\r
     // If FMP GetInformation interface failed, skip this resource\r
     //\r
-    if (EFI_ERROR(Status)) {\r
-      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);\r
-      FreePool(FmpImageInfoBuf);\r
+    if (EFI_ERROR (Status)) {\r
+      Print (L"FMP (%d) ImageInfo - %r\n", Index, Status);\r
+      FreePool (FmpImageInfoBuf);\r
       continue;\r
     }\r
 \r
-    Print(L"FMP (%d) ImageInfo:\n", Index);\r
-    DumpFmpImageInfo(\r
+    Print (L"FMP (%d) ImageInfo:\n", Index);\r
+    DumpFmpImageInfo (\r
       ImageInfoSize,               // ImageInfoSize\r
       FmpImageInfoBuf,             // ImageInfo\r
       FmpImageInfoDescriptorVer,   // DescriptorVersion\r
@@ -698,27 +1221,28 @@ DumpFmpData (
       );\r
 \r
     if (PackageVersionName != NULL) {\r
-      FreePool(PackageVersionName);\r
+      FreePool (PackageVersionName);\r
     }\r
-    FreePool(FmpImageInfoBuf);\r
+\r
+    FreePool (FmpImageInfoBuf);\r
 \r
     //\r
     // Get package info\r
     //\r
     PackageVersionName = NULL;\r
-    Status = Fmp->GetPackageInfo (\r
-                    Fmp,\r
-                    &PackageVersion,              // PackageVersion\r
-                    &PackageVersionName,          // PackageVersionName\r
-                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen\r
-                    &AttributesSupported,         // AttributesSupported\r
-                    &AttributesSetting            // AttributesSetting\r
-                    );\r
-    if (EFI_ERROR(Status)) {\r
-      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);\r
+    Status             = Fmp->GetPackageInfo (\r
+                                Fmp,\r
+                                &PackageVersion,           // PackageVersion\r
+                                &PackageVersionName,       // PackageVersionName\r
+                                &PackageVersionNameMaxLen, // PackageVersionNameMaxLen\r
+                                &AttributesSupported,      // AttributesSupported\r
+                                &AttributesSetting         // AttributesSetting\r
+                                );\r
+    if (EFI_ERROR (Status)) {\r
+      Print (L"FMP (%d) PackageInfo - %r\n", Index, Status);\r
     } else {\r
-      Print(L"FMP (%d) ImageInfo:\n", Index);\r
-      DumpFmpPackageInfo(\r
+      Print (L"FMP (%d) ImageInfo:\n", Index);\r
+      DumpFmpPackageInfo (\r
         PackageVersion,              // PackageVersion\r
         PackageVersionName,          // PackageVersionName\r
         PackageVersionNameMaxLen,    // PackageVersionNameMaxLen\r
@@ -727,12 +1251,217 @@ DumpFmpData (
         );\r
 \r
       if (PackageVersionName != NULL) {\r
-        FreePool(PackageVersionName);\r
+        FreePool (PackageVersionName);\r
       }\r
     }\r
   }\r
-  Print(L"\n");\r
+\r
+  Print (L"\n");\r
 \r
 EXIT:\r
-  FreePool(HandleBuffer);\r
+  FreePool (HandleBuffer);\r
+}\r
+\r
+/**\r
+  Check if the ImageInfo includes the ImageTypeId.\r
+\r
+  @param[in] ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+  @param[in] DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+  @param[in] DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.\r
+  @param[in] ImageTypeId         A unique GUID identifying the firmware image type.\r
+\r
+  @return TRUE  This ImageInfo includes the ImageTypeId\r
+  @return FALSE This ImageInfo does not include the ImageTypeId\r
+**/\r
+BOOLEAN\r
+IsThisFmpImageInfo (\r
+  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR  *ImageInfo,\r
+  IN UINT8                          DescriptorCount,\r
+  IN UINTN                          DescriptorSize,\r
+  IN EFI_GUID                       *ImageTypeId\r
+  )\r
+{\r
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR  *CurrentImageInfo;\r
+  UINTN                          Index;\r
+\r
+  CurrentImageInfo = ImageInfo;\r
+  for (Index = 0; Index < DescriptorCount; Index++) {\r
+    if (CompareGuid (&CurrentImageInfo->ImageTypeId, ImageTypeId)) {\r
+      return TRUE;\r
+    }\r
+\r
+    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  return the FMP whoes ImageInfo includes the ImageTypeId.\r
+\r
+  @param[in] ImageTypeId         A unique GUID identifying the firmware image type.\r
+\r
+  @return The FMP whoes ImageInfo includes the ImageTypeId\r
+**/\r
+EFI_FIRMWARE_MANAGEMENT_PROTOCOL *\r
+FindFmpFromImageTypeId (\r
+  IN EFI_GUID  *ImageTypeId\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;\r
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *TargetFmp;\r
+  EFI_HANDLE                        *HandleBuffer;\r
+  UINTN                             NumberOfHandles;\r
+  UINTN                             Index;\r
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR     *FmpImageInfoBuf;\r
+  UINTN                             ImageInfoSize;\r
+  UINT32                            FmpImageInfoDescriptorVer;\r
+  UINT8                             FmpImageInfoCount;\r
+  UINTN                             DescriptorSize;\r
+  UINT32                            PackageVersion;\r
+  CHAR16                            *PackageVersionName;\r
+\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiFirmwareManagementProtocolGuid,\r
+                  NULL,\r
+                  &NumberOfHandles,\r
+                  &HandleBuffer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"FMP protocol - %r\n", EFI_NOT_FOUND);\r
+    return NULL;\r
+  }\r
+\r
+  TargetFmp = NULL;\r
+  for (Index = 0; Index < NumberOfHandles; Index++) {\r
+    Status = gBS->HandleProtocol (\r
+                    HandleBuffer[Index],\r
+                    &gEfiFirmwareManagementProtocolGuid,\r
+                    (VOID **)&Fmp\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    ImageInfoSize = 0;\r
+    Status        = Fmp->GetImageInfo (\r
+                           Fmp,\r
+                           &ImageInfoSize,\r
+                           NULL,\r
+                           NULL,\r
+                           NULL,\r
+                           NULL,\r
+                           NULL,\r
+                           NULL\r
+                           );\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      continue;\r
+    }\r
+\r
+    FmpImageInfoBuf = NULL;\r
+    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
+    if (FmpImageInfoBuf == NULL) {\r
+      FreePool (HandleBuffer);\r
+      Print (L"Out of resource\n");\r
+      return NULL;\r
+    }\r
+\r
+    PackageVersionName = NULL;\r
+    Status             = Fmp->GetImageInfo (\r
+                                Fmp,\r
+                                &ImageInfoSize,             // ImageInfoSize\r
+                                FmpImageInfoBuf,            // ImageInfo\r
+                                &FmpImageInfoDescriptorVer, // DescriptorVersion\r
+                                &FmpImageInfoCount,         // DescriptorCount\r
+                                &DescriptorSize,            // DescriptorSize\r
+                                &PackageVersion,            // PackageVersion\r
+                                &PackageVersionName         // PackageVersionName\r
+                                );\r
+\r
+    //\r
+    // If FMP GetInformation interface failed, skip this resource\r
+    //\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (FmpImageInfoBuf);\r
+      continue;\r
+    }\r
+\r
+    if (PackageVersionName != NULL) {\r
+      FreePool (PackageVersionName);\r
+    }\r
+\r
+    if (IsThisFmpImageInfo (FmpImageInfoBuf, FmpImageInfoCount, DescriptorSize, ImageTypeId)) {\r
+      TargetFmp = Fmp;\r
+    }\r
+\r
+    FreePool (FmpImageInfoBuf);\r
+    if (TargetFmp != NULL) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  FreePool (HandleBuffer);\r
+  return TargetFmp;\r
+}\r
+\r
+/**\r
+  Dump FMP image data.\r
+\r
+  @param[in]  ImageTypeId   The ImageTypeId of the FMP image.\r
+                            It is used to identify the FMP protocol.\r
+  @param[in]  ImageIndex    The ImageIndex of the FMP image.\r
+                            It is the input parameter for FMP->GetImage().\r
+  @param[in]  ImageName     The file name to hold the output FMP image.\r
+**/\r
+VOID\r
+DumpFmpImage (\r
+  IN EFI_GUID  *ImageTypeId,\r
+  IN UINTN     ImageIndex,\r
+  IN CHAR16    *ImageName\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;\r
+  VOID                              *Image;\r
+  UINTN                             ImageSize;\r
+\r
+  Fmp = FindFmpFromImageTypeId (ImageTypeId);\r
+  if (Fmp == NULL) {\r
+    Print (L"No FMP include ImageTypeId %g\n", ImageTypeId);\r
+    return;\r
+  }\r
+\r
+  if (ImageIndex > 0xFF) {\r
+    Print (L"ImageIndex 0x%x too big\n", ImageIndex);\r
+    return;\r
+  }\r
+\r
+  Image     = Fmp;\r
+  ImageSize = 0;\r
+  Status    = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    Print (L"Fmp->GetImage - %r\n", Status);\r
+    return;\r
+  }\r
+\r
+  Image = AllocatePool (ImageSize);\r
+  if (Image == NULL) {\r
+    Print (L"Allocate FmpImage 0x%x - %r\n", ImageSize, EFI_OUT_OF_RESOURCES);\r
+    return;\r
+  }\r
+\r
+  Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"Fmp->GetImage - %r\n", Status);\r
+    return;\r
+  }\r
+\r
+  Status = WriteFileFromBuffer (ImageName, ImageSize, Image);\r
+  Print (L"CapsuleApp: Dump %g ImageIndex (0x%x) to %s %r\n", ImageTypeId, ImageIndex, ImageName, Status);\r
+\r
+  FreePool (Image);\r
+\r
+  return;\r
 }\r