REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			1468 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1468 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Dump Capsule image information.
 | |
| 
 | |
|   Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "CapsuleApp.h"
 | |
| 
 | |
| /**
 | |
|   Validate if it is valid capsule header
 | |
| 
 | |
|   This function assumes the caller provided correct CapsuleHeader pointer
 | |
|   and CapsuleSize.
 | |
| 
 | |
|   This function validates the fields in EFI_CAPSULE_HEADER.
 | |
| 
 | |
|   @param[in] CapsuleHeader  Points to a capsule header.
 | |
|   @param[in] CapsuleSize    Size of the whole capsule image.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsValidCapsuleHeader (
 | |
|   IN EFI_CAPSULE_HEADER  *CapsuleHeader,
 | |
|   IN UINT64              CapsuleSize
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Dump UX capsule information.
 | |
| 
 | |
|   @param[in] CapsuleHeader      The UX capsule header
 | |
| **/
 | |
| VOID
 | |
| DumpUxCapsule (
 | |
|   IN EFI_CAPSULE_HEADER  *CapsuleHeader
 | |
|   )
 | |
| {
 | |
|   EFI_DISPLAY_CAPSULE  *DisplayCapsule;
 | |
| 
 | |
|   DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
 | |
|   Print (L"[UxCapsule]\n");
 | |
|   Print (L"CapsuleHeader:\n");
 | |
|   Print (L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
 | |
|   Print (L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
 | |
|   Print (L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
 | |
|   Print (L"  CapsuleImageSize - 0x%x\n", DisplayCapsule->CapsuleHeader.CapsuleImageSize);
 | |
|   Print (L"ImagePayload:\n");
 | |
|   Print (L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
 | |
|   Print (L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
 | |
|   Print (L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
 | |
|   Print (L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
 | |
|   Print (L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
 | |
|   Print (L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump a non-nested FMP capsule.
 | |
| 
 | |
|   @param[in]  CapsuleHeader  A pointer to CapsuleHeader
 | |
| **/
 | |
| VOID
 | |
| DumpFmpCapsule (
 | |
|   IN EFI_CAPSULE_HEADER  *CapsuleHeader
 | |
|   )
 | |
| {
 | |
|   EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
 | |
|   UINT64                                        *ItemOffsetList;
 | |
|   UINTN                                         Index;
 | |
|   UINTN                                         Count;
 | |
|   EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
 | |
| 
 | |
|   Print (L"[FmpCapsule]\n");
 | |
|   Print (L"CapsuleHeader:\n");
 | |
|   Print (L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
 | |
|   Print (L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
 | |
|   Print (L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
 | |
|   Print (L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
 | |
| 
 | |
|   FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
 | |
|   ItemOffsetList   = (UINT64 *)(FmpCapsuleHeader + 1);
 | |
|   Print (L"FmpHeader:\n");
 | |
|   Print (L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
 | |
|   Print (L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
 | |
|   Print (L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
 | |
|   Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
 | |
|   for (Index = 0; Index < Count; Index++) {
 | |
|     Print (L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
 | |
|   }
 | |
| 
 | |
|   for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
 | |
|     Print (L"FmpPayload[%d] ImageHeader:\n", Index);
 | |
|     FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
 | |
|     Print (L"  Version                - 0x%x\n", FmpImageHeader->Version);
 | |
|     Print (L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
 | |
|     Print (L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
 | |
|     Print (L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
 | |
|     Print (L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
 | |
|     if (FmpImageHeader->Version >= 2) {
 | |
|       Print (L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader->UpdateHardwareInstance);
 | |
|       if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
 | |
|         Print (L"  ImageCapsuleSupport    - 0x%lx\n", FmpImageHeader->ImageCapsuleSupport);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Return if there is a FMP header below capsule header.
 | |
| 
 | |
|   @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
 | |
| 
 | |
|   @retval TRUE  There is a FMP header below capsule header.
 | |
|   @retval FALSE There is not a FMP header below capsule header
 | |
| **/
 | |
| BOOLEAN
 | |
| IsNestedFmpCapsule (
 | |
|   IN EFI_CAPSULE_HEADER  *CapsuleHeader
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                 Status;
 | |
|   EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
 | |
|   EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
 | |
|   UINTN                      Index;
 | |
|   BOOLEAN                    EsrtGuidFound;
 | |
|   EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
 | |
|   UINTN                      NestedCapsuleSize;
 | |
| 
 | |
|   //
 | |
|   // Check ESRT
 | |
|   //
 | |
|   EsrtGuidFound = FALSE;
 | |
|   Status        = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     ASSERT (Esrt != NULL);
 | |
|     EsrtEntry = (VOID *)(Esrt + 1);
 | |
|     for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
 | |
|       if (CompareGuid (&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
 | |
|         EsrtGuidFound = TRUE;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!EsrtGuidFound) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check nested capsule header
 | |
|   // FMP GUID after ESRT one
 | |
|   //
 | |
|   NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
 | |
|   NestedCapsuleSize   = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize- (UINTN)NestedCapsuleHeader;
 | |
|   if (NestedCapsuleSize < sizeof (EFI_CAPSULE_HEADER)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if (!CompareGuid (&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump capsule information
 | |
| 
 | |
|   @param[in] CapsuleName  The name of the capsule image.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The capsule information is dumped.
 | |
|   @retval EFI_UNSUPPORTED        Input parameter is not valid.
 | |
| **/
 | |
| EFI_STATUS
 | |
| DumpCapsule (
 | |
|   IN CHAR16  *CapsuleName
 | |
|   )
 | |
| {
 | |
|   VOID                *Buffer;
 | |
|   UINTN               FileSize;
 | |
|   EFI_CAPSULE_HEADER  *CapsuleHeader;
 | |
|   EFI_STATUS          Status;
 | |
| 
 | |
|   Buffer = NULL;
 | |
|   Status = ReadFileToBuffer (CapsuleName, &FileSize, &Buffer);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Print (L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (!IsValidCapsuleHeader (Buffer, FileSize)) {
 | |
|     Print (L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   CapsuleHeader = Buffer;
 | |
|   if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
 | |
|     DumpUxCapsule (CapsuleHeader);
 | |
|     Status = EFI_SUCCESS;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
 | |
|     DumpFmpCapsule (CapsuleHeader);
 | |
|   }
 | |
| 
 | |
|   if (IsNestedFmpCapsule (CapsuleHeader)) {
 | |
|     Print (L"[NestedCapsule]\n");
 | |
|     Print (L"CapsuleHeader:\n");
 | |
|     Print (L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
 | |
|     Print (L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
 | |
|     Print (L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
 | |
|     Print (L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
 | |
|     DumpFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   if (Buffer != NULL) {
 | |
|     FreePool (Buffer);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump capsule status variable.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The capsule status variable is dumped.
 | |
|   @retval EFI_UNSUPPORTED        Input parameter is not valid.
 | |
| **/
 | |
| EFI_STATUS
 | |
| DumpCapsuleStatusVariable (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                          Status;
 | |
|   UINT32                              Index;
 | |
|   CHAR16                              CapsuleVarName[20];
 | |
|   CHAR16                              *TempVarName;
 | |
|   EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
 | |
|   EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
 | |
|   UINTN                               CapsuleFileNameSize;
 | |
|   CHAR16                              CapsuleIndexData[12];
 | |
|   CHAR16                              *CapsuleIndex;
 | |
|   CHAR16                              *CapsuleFileName;
 | |
|   CHAR16                              *CapsuleTarget;
 | |
| 
 | |
|   Status = GetVariable2 (
 | |
|              L"CapsuleMax",
 | |
|              &gEfiCapsuleReportGuid,
 | |
|              (VOID **)&CapsuleIndex,
 | |
|              NULL
 | |
|              );
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     ASSERT (CapsuleIndex != NULL);
 | |
|     CopyMem (CapsuleIndexData, CapsuleIndex, 11 * sizeof (CHAR16));
 | |
|     CapsuleIndexData[11] = 0;
 | |
|     Print (L"CapsuleMax - %s\n", CapsuleIndexData);
 | |
|     FreePool (CapsuleIndex);
 | |
|   }
 | |
| 
 | |
|   Status = GetVariable2 (
 | |
|              L"CapsuleLast",
 | |
|              &gEfiCapsuleReportGuid,
 | |
|              (VOID **)&CapsuleIndex,
 | |
|              NULL
 | |
|              );
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     ASSERT (CapsuleIndex != NULL);
 | |
|     CopyMem (CapsuleIndexData, CapsuleIndex, 11 * sizeof (CHAR16));
 | |
|     CapsuleIndexData[11] = 0;
 | |
|     Print (L"CapsuleLast - %s\n", CapsuleIndexData);
 | |
|     FreePool (CapsuleIndex);
 | |
|   }
 | |
| 
 | |
|   StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CapsuleVarName[0]), L"Capsule");
 | |
|   TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
 | |
|   Index       = 0;
 | |
| 
 | |
|   while (TRUE) {
 | |
|     UnicodeSPrint (TempVarName, 5 * sizeof (CHAR16), L"%04x", Index);
 | |
| 
 | |
|     Status = GetVariable2 (
 | |
|                CapsuleVarName,
 | |
|                &gEfiCapsuleReportGuid,
 | |
|                (VOID **)&CapsuleResult,
 | |
|                NULL
 | |
|                );
 | |
|     if (Status == EFI_NOT_FOUND) {
 | |
|       break;
 | |
|     } else if (EFI_ERROR (Status)) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     ASSERT (CapsuleResult != NULL);
 | |
| 
 | |
|     //
 | |
|     // display capsule process status
 | |
|     //
 | |
|     if (CapsuleResult->VariableTotalSize >= sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
 | |
|       Print (L"CapsuleName: %s\n", CapsuleVarName);
 | |
|       Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
 | |
|       Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
 | |
|       Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
 | |
|     }
 | |
| 
 | |
|     if (CompareGuid (&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
 | |
|       if (CapsuleResult->VariableTotalSize >= sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof (CHAR16) * 2) {
 | |
|         CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
 | |
|         Print (L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
 | |
|         Print (L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
 | |
|         Print (L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp->UpdateImageIndex);
 | |
|         Print (L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp->UpdateImageTypeId);
 | |
|         CapsuleFileName = (CHAR16 *)(CapsuleResultFmp + 1);
 | |
|         Print (L"  Capsule FMP CapsuleFileName: \"%s\"\n", CapsuleFileName);
 | |
|         CapsuleFileNameSize = StrSize (CapsuleFileName);
 | |
|         CapsuleTarget       = (CHAR16 *)((UINTN)CapsuleFileName + CapsuleFileNameSize);
 | |
|         Print (L"  Capsule FMP CapsuleTarget: \"%s\"\n", CapsuleTarget);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     FreePool (CapsuleResult);
 | |
| 
 | |
|     Index++;
 | |
|     if (Index > 0xFFFF) {
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| CHAR8  *mFwTypeString[] = {
 | |
|   "Unknown",
 | |
|   "SystemFirmware",
 | |
|   "DeviceFirmware",
 | |
|   "UefiDriver",
 | |
| };
 | |
| 
 | |
| CHAR8  *mLastAttemptStatusString[] = {
 | |
|   "Success",
 | |
|   "Error: Unsuccessful",
 | |
|   "Error: Insufficient Resources",
 | |
|   "Error: Incorrect Version",
 | |
|   "Error: Invalid Format",
 | |
|   "Error: Auth Error",
 | |
|   "Error: Power Event AC",
 | |
|   "Error: Power Event Battery",
 | |
|   "Error: Unsatisfied Dependencies",
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Convert FwType to a string.
 | |
| 
 | |
|   @param[in] FwType  FwType in ESRT
 | |
| 
 | |
|   @return a string for FwType.
 | |
| **/
 | |
| CHAR8 *
 | |
| FwTypeToString (
 | |
|   IN UINT32  FwType
 | |
|   )
 | |
| {
 | |
|   if (FwType < sizeof (mFwTypeString) / sizeof (mFwTypeString[0])) {
 | |
|     return mFwTypeString[FwType];
 | |
|   } else {
 | |
|     return "Invalid";
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert LastAttemptStatus to a string.
 | |
| 
 | |
|   @param[in] LastAttemptStatus  LastAttemptStatus in FMP or ESRT
 | |
| 
 | |
|   @return a string for LastAttemptStatus.
 | |
| **/
 | |
| CHAR8 *
 | |
| LastAttemptStatusToString (
 | |
|   IN UINT32  LastAttemptStatus
 | |
|   )
 | |
| {
 | |
|   if (LastAttemptStatus < sizeof (mLastAttemptStatusString) / sizeof (mLastAttemptStatusString[0])) {
 | |
|     return mLastAttemptStatusString[LastAttemptStatus];
 | |
|   } else {
 | |
|     return "Error: Unknown";
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump ESRT entry.
 | |
| 
 | |
|   @param[in] EsrtEntry  ESRT entry
 | |
| **/
 | |
| VOID
 | |
| DumpEsrtEntry (
 | |
|   IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
 | |
|   )
 | |
| {
 | |
|   Print (L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
 | |
|   Print (L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType, FwTypeToString (EsrtEntry->FwType));
 | |
|   Print (L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
 | |
|   Print (L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
 | |
|   Print (L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
 | |
|   Print (L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
 | |
|   Print (L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus, LastAttemptStatusToString (EsrtEntry->LastAttemptStatus));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump ESRT table.
 | |
| 
 | |
|   @param[in] Esrt  ESRT table
 | |
| **/
 | |
| VOID
 | |
| DumpEsrt (
 | |
|   IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
 | |
|   )
 | |
| {
 | |
|   UINTN                      Index;
 | |
|   EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
 | |
| 
 | |
|   if (Esrt == NULL) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Print (L"EFI_SYSTEM_RESOURCE_TABLE:\n");
 | |
|   Print (L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
 | |
|   Print (L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
 | |
|   Print (L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
 | |
| 
 | |
|   EsrtEntry = (VOID *)(Esrt + 1);
 | |
|   for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
 | |
|     Print (L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
 | |
|     DumpEsrtEntry (EsrtEntry);
 | |
|     EsrtEntry++;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump ESRT info.
 | |
| **/
 | |
| VOID
 | |
| DumpEsrtData (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                 Status;
 | |
|   EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
 | |
| 
 | |
|   Print (L"##############\n");
 | |
|   Print (L"# ESRT TABLE #\n");
 | |
|   Print (L"##############\n");
 | |
| 
 | |
|   Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Print (L"ESRT - %r\n", Status);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   DumpEsrt (Esrt);
 | |
|   Print (L"\n");
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump capsule information from CapsuleHeader
 | |
| 
 | |
|   @param[in] CapsuleHeader       The CapsuleHeader of the capsule image.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The capsule information is dumped.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| DumpCapsuleFromBuffer (
 | |
|   IN EFI_CAPSULE_HEADER  *CapsuleHeader
 | |
|   )
 | |
| {
 | |
|   if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
 | |
|     DumpUxCapsule (CapsuleHeader);
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
 | |
|     DumpFmpCapsule (CapsuleHeader);
 | |
|   }
 | |
| 
 | |
|   if (IsNestedFmpCapsule (CapsuleHeader)) {
 | |
|     Print (L"[NestedCapusule]\n");
 | |
|     Print (L"CapsuleHeader:\n");
 | |
|     Print (L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
 | |
|     Print (L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
 | |
|     Print (L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
 | |
|     Print (L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
 | |
|     DumpFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This routine is called to upper case given unicode string.
 | |
| 
 | |
|   @param[in]   Str              String to upper case
 | |
| 
 | |
|   @retval upper cased string after process
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| CHAR16 *
 | |
| UpperCaseString (
 | |
|   IN CHAR16  *Str
 | |
|   )
 | |
| {
 | |
|   CHAR16  *Cptr;
 | |
| 
 | |
|   for (Cptr = Str; *Cptr != L'\0'; Cptr++) {
 | |
|     if ((L'a' <= *Cptr) && (*Cptr <= L'z')) {
 | |
|       *Cptr = *Cptr - L'a' + L'A';
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Str;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This routine is used to return substring before period '.' or '\0'
 | |
|   Caller should respsonsible of substr space allocation & free
 | |
| 
 | |
|   @param[in]   Str              String to check
 | |
|   @param[out]  SubStr           First part of string before period or '\0'
 | |
|   @param[out]  SubStrLen        Length of first part of string
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| GetSubStringBeforePeriod (
 | |
|   IN  CHAR16  *Str,
 | |
|   OUT CHAR16  *SubStr,
 | |
|   OUT UINTN   *SubStrLen
 | |
|   )
 | |
| {
 | |
|   UINTN  Index;
 | |
| 
 | |
|   for (Index = 0; Str[Index] != L'.' && Str[Index] != L'\0'; Index++) {
 | |
|     SubStr[Index] = Str[Index];
 | |
|   }
 | |
| 
 | |
|   SubStr[Index] = L'\0';
 | |
|   *SubStrLen    = Index;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This routine pad the string in tail with input character.
 | |
| 
 | |
|   @param[in]   StrBuf            Str buffer to be padded, should be enough room for
 | |
|   @param[in]   PadLen            Expected padding length
 | |
|   @param[in]   Character         Character used to pad
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| PadStrInTail (
 | |
|   IN CHAR16  *StrBuf,
 | |
|   IN UINTN   PadLen,
 | |
|   IN CHAR16  Character
 | |
|   )
 | |
| {
 | |
|   UINTN  Index;
 | |
| 
 | |
|   for (Index = 0; StrBuf[Index] != L'\0'; Index++) {
 | |
|   }
 | |
| 
 | |
|   while (PadLen != 0) {
 | |
|     StrBuf[Index] = Character;
 | |
|     Index++;
 | |
|     PadLen--;
 | |
|   }
 | |
| 
 | |
|   StrBuf[Index] = L'\0';
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This routine find the offset of the last period '.' of string. if No period exists
 | |
|   function FileNameExtension is set to L'\0'
 | |
| 
 | |
|   @param[in]   FileName           File name to split between last period
 | |
|   @param[out]  FileNameFirst      First FileName before last period
 | |
|   @param[out]  FileNameExtension  FileName after last period
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| SplitFileNameExtension (
 | |
|   IN  CHAR16  *FileName,
 | |
|   OUT CHAR16  *FileNameFirst,
 | |
|   OUT CHAR16  *FileNameExtension
 | |
|   )
 | |
| {
 | |
|   UINTN  Index;
 | |
|   UINTN  StringLen;
 | |
| 
 | |
|   StringLen = StrLen (FileName);
 | |
|   for (Index = StringLen; Index > 0 && FileName[Index] != L'.'; Index--) {
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // No period exists. No FileName Extension
 | |
|   //
 | |
|   if ((Index == 0) && (FileName[Index] != L'.')) {
 | |
|     FileNameExtension[0] = L'\0';
 | |
|     Index                = StringLen;
 | |
|   } else {
 | |
|     StrCpyS (FileNameExtension, MAX_FILE_NAME_LEN, &FileName[Index+1]);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Copy First file name
 | |
|   //
 | |
|   StrnCpyS (FileNameFirst, MAX_FILE_NAME_LEN, FileName, Index);
 | |
|   FileNameFirst[Index] = L'\0';
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The function is called by PerformQuickSort to sort file name in alphabet.
 | |
| 
 | |
|   @param[in] Left            The pointer to first buffer.
 | |
|   @param[in] Right           The pointer to second buffer.
 | |
| 
 | |
|   @retval 0                  Buffer1 equal to Buffer2.
 | |
|   @return <0                 Buffer1 is less than Buffer2.
 | |
|   @return >0                 Buffer1 is greater than Buffer2.
 | |
| 
 | |
| **/
 | |
| INTN
 | |
| CompareFileNameInAlphabet (
 | |
|   IN VOID  *Left,
 | |
|   IN VOID  *Right
 | |
|   )
 | |
| {
 | |
|   EFI_FILE_INFO  *FileInfo1;
 | |
|   EFI_FILE_INFO  *FileInfo2;
 | |
|   CHAR16         FileName1[MAX_FILE_NAME_SIZE];
 | |
|   CHAR16         FileExtension1[MAX_FILE_NAME_SIZE];
 | |
|   CHAR16         FileName2[MAX_FILE_NAME_SIZE];
 | |
|   CHAR16         FileExtension2[MAX_FILE_NAME_SIZE];
 | |
|   CHAR16         TempSubStr1[MAX_FILE_NAME_SIZE];
 | |
|   CHAR16         TempSubStr2[MAX_FILE_NAME_SIZE];
 | |
|   UINTN          SubStrLen1;
 | |
|   UINTN          SubStrLen2;
 | |
|   INTN           SubStrCmpResult;
 | |
| 
 | |
|   FileInfo1 = (EFI_FILE_INFO *)(*(UINTN *)Left);
 | |
|   FileInfo2 = (EFI_FILE_INFO *)(*(UINTN *)Right);
 | |
| 
 | |
|   SplitFileNameExtension (FileInfo1->FileName, FileName1, FileExtension1);
 | |
|   SplitFileNameExtension (FileInfo2->FileName, FileName2, FileExtension2);
 | |
| 
 | |
|   UpperCaseString (FileName1);
 | |
|   UpperCaseString (FileName2);
 | |
| 
 | |
|   GetSubStringBeforePeriod (FileName1, TempSubStr1, &SubStrLen1);
 | |
|   GetSubStringBeforePeriod (FileName2, TempSubStr2, &SubStrLen2);
 | |
| 
 | |
|   if (SubStrLen1 > SubStrLen2) {
 | |
|     //
 | |
|     // Substr in NewFileName is longer.  Pad tail with SPACE
 | |
|     //
 | |
|     PadStrInTail (TempSubStr2, SubStrLen1 - SubStrLen2, L' ');
 | |
|   } else if (SubStrLen1 < SubStrLen2) {
 | |
|     //
 | |
|     // Substr in ListedFileName is longer. Pad tail with SPACE
 | |
|     //
 | |
|     PadStrInTail (TempSubStr1, SubStrLen2 - SubStrLen1, L' ');
 | |
|   }
 | |
| 
 | |
|   SubStrCmpResult = StrnCmp (TempSubStr1, TempSubStr2, MAX_FILE_NAME_LEN);
 | |
|   if (SubStrCmpResult != 0) {
 | |
|     return SubStrCmpResult;
 | |
|   }
 | |
| 
 | |
|   UpperCaseString (FileExtension1);
 | |
|   UpperCaseString (FileExtension2);
 | |
| 
 | |
|   return StrnCmp (FileExtension1, FileExtension2, MAX_FILE_NAME_LEN);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump capsule information from disk.
 | |
| 
 | |
|   @param[in] Fs                  The device path of disk.
 | |
|   @param[in] DumpCapsuleInfo     The flag to indicate whether to dump the capsule inforomation.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The capsule information is dumped.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| DumpCapsuleFromDisk (
 | |
|   IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs,
 | |
|   IN BOOLEAN                          DumpCapsuleInfo
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS     Status;
 | |
|   EFI_FILE       *Root;
 | |
|   EFI_FILE       *DirHandle;
 | |
|   EFI_FILE       *FileHandle;
 | |
|   UINTN          Index;
 | |
|   UINTN          FileSize;
 | |
|   VOID           *FileBuffer;
 | |
|   EFI_FILE_INFO  **FileInfoBuffer;
 | |
|   EFI_FILE_INFO  *FileInfo;
 | |
|   UINTN          FileCount;
 | |
|   BOOLEAN        NoFile;
 | |
| 
 | |
|   DirHandle      = NULL;
 | |
|   FileHandle     = NULL;
 | |
|   Index          = 0;
 | |
|   FileInfoBuffer = NULL;
 | |
|   FileInfo       = NULL;
 | |
|   FileCount      = 0;
 | |
|   NoFile         = FALSE;
 | |
| 
 | |
|   Status = Fs->OpenVolume (Fs, &Root);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Print (L"Cannot open volume. Status = %r\n", Status);
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = Root->Open (Root, &DirHandle, EFI_CAPSULE_FILE_DIRECTORY, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Print (L"Cannot open %s. Status = %r\n", EFI_CAPSULE_FILE_DIRECTORY, Status);
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get file count first
 | |
|   //
 | |
|   Status = FileHandleFindFirstFile (DirHandle, &FileInfo);
 | |
|   do {
 | |
|     if (EFI_ERROR (Status) || (FileInfo == NULL)) {
 | |
|       Print (L"Get File Info Fail. Status = %r\n", Status);
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) != 0) {
 | |
|       FileCount++;
 | |
|     }
 | |
| 
 | |
|     Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Print (L"Get Next File Fail. Status = %r\n", Status);
 | |
|       goto Done;
 | |
|     }
 | |
|   } while (!NoFile);
 | |
| 
 | |
|   if (FileCount == 0) {
 | |
|     Print (L"Error: No capsule file found!\n");
 | |
|     Status = EFI_NOT_FOUND;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   FileInfoBuffer = AllocateZeroPool (sizeof (FileInfo) * FileCount);
 | |
|   if (FileInfoBuffer == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   NoFile = FALSE;
 | |
| 
 | |
|   //
 | |
|   // Get all file info
 | |
|   //
 | |
|   Status = FileHandleFindFirstFile (DirHandle, &FileInfo);
 | |
|   do {
 | |
|     if (EFI_ERROR (Status) || (FileInfo == NULL)) {
 | |
|       Print (L"Get File Info Fail. Status = %r\n", Status);
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) != 0) {
 | |
|       FileInfoBuffer[Index++] = AllocateCopyPool ((UINTN)FileInfo->Size, FileInfo);
 | |
|     }
 | |
| 
 | |
|     Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Print (L"Get Next File Fail. Status = %r\n", Status);
 | |
|       goto Done;
 | |
|     }
 | |
|   } while (!NoFile);
 | |
| 
 | |
|   //
 | |
|   // Sort FileInfoBuffer by alphabet order
 | |
|   //
 | |
|   PerformQuickSort (
 | |
|     FileInfoBuffer,
 | |
|     FileCount,
 | |
|     sizeof (FileInfo),
 | |
|     (SORT_COMPARE)CompareFileNameInAlphabet
 | |
|     );
 | |
| 
 | |
|   Print (L"The capsules will be performed by following order:\n");
 | |
| 
 | |
|   for (Index = 0; Index < FileCount; Index++) {
 | |
|     Print (L"  %d.%s\n", Index + 1, FileInfoBuffer[Index]->FileName);
 | |
|   }
 | |
| 
 | |
|   if (!DumpCapsuleInfo) {
 | |
|     Status = EFI_SUCCESS;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Print (L"The infomation of the capsules:\n");
 | |
| 
 | |
|   for (Index = 0; Index < FileCount; Index++) {
 | |
|     FileHandle = NULL;
 | |
|     Status     = DirHandle->Open (DirHandle, &FileHandle, FileInfoBuffer[Index]->FileName, EFI_FILE_MODE_READ, 0);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     Status = FileHandleGetSize (FileHandle, (UINT64 *)&FileSize);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status);
 | |
|       FileHandleClose (FileHandle);
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     FileBuffer = AllocatePool (FileSize);
 | |
|     if (FileBuffer == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     Status = FileHandleRead (FileHandle, &FileSize, FileBuffer);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status);
 | |
|       FileHandleClose (FileHandle);
 | |
|       FreePool (FileBuffer);
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     Print (L"**************************\n");
 | |
|     Print (L"  %d.%s:\n", Index + 1, FileInfoBuffer[Index]->FileName);
 | |
|     Print (L"**************************\n");
 | |
|     DumpCapsuleFromBuffer ((EFI_CAPSULE_HEADER *)FileBuffer);
 | |
|     FileHandleClose (FileHandle);
 | |
|     FreePool (FileBuffer);
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   if (FileInfoBuffer != NULL) {
 | |
|     for (Index = 0; Index < FileCount; Index++) {
 | |
|       if (FileInfoBuffer[Index] != NULL) {
 | |
|         FreePool (FileInfoBuffer[Index]);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     FreePool (FileInfoBuffer);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump capsule inforomation form Gather list.
 | |
| 
 | |
|   @param[in]  BlockDescriptors The block descriptors for the capsule images
 | |
|   @param[in]  DumpCapsuleInfo  The flag to indicate whether to dump the capsule inforomation.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DumpBlockDescriptors (
 | |
|   IN EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors,
 | |
|   IN BOOLEAN                       DumpCapsuleInfo
 | |
|   )
 | |
| {
 | |
|   EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
 | |
| 
 | |
|   TempBlockPtr = BlockDescriptors;
 | |
| 
 | |
|   while (TRUE) {
 | |
|     if (TempBlockPtr->Length != 0) {
 | |
|       if (DumpCapsuleInfo) {
 | |
|         Print (L"******************************************************\n");
 | |
|       }
 | |
| 
 | |
|       Print (L"Capsule data starts at 0x%08x with size 0x%08x\n", TempBlockPtr->Union.DataBlock, TempBlockPtr->Length);
 | |
|       if (DumpCapsuleInfo) {
 | |
|         Print (L"******************************************************\n");
 | |
|         DumpCapsuleFromBuffer ((EFI_CAPSULE_HEADER *)(UINTN)TempBlockPtr->Union.DataBlock);
 | |
|       }
 | |
| 
 | |
|       TempBlockPtr += 1;
 | |
|     } else {
 | |
|       if (TempBlockPtr->Union.ContinuationPointer == (UINTN)NULL) {
 | |
|         break;
 | |
|       } else {
 | |
|         TempBlockPtr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)TempBlockPtr->Union.ContinuationPointer;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump Provisioned Capsule.
 | |
| 
 | |
|   @param[in]  DumpCapsuleInfo  The flag to indicate whether to dump the capsule inforomation.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DumpProvisionedCapsule (
 | |
|   IN BOOLEAN  DumpCapsuleInfo
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                       Status;
 | |
|   CHAR16                           CapsuleVarName[30];
 | |
|   CHAR16                           *TempVarName;
 | |
|   UINTN                            Index;
 | |
|   EFI_PHYSICAL_ADDRESS             *CapsuleDataPtr64;
 | |
|   UINT16                           *BootNext;
 | |
|   CHAR16                           BootOptionName[20];
 | |
|   EFI_BOOT_MANAGER_LOAD_OPTION     BootNextOptionEntry;
 | |
|   EFI_DEVICE_PATH_PROTOCOL         *DevicePath;
 | |
|   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
 | |
|   EFI_SHELL_PROTOCOL               *ShellProtocol;
 | |
| 
 | |
|   Index            = 0;
 | |
|   CapsuleDataPtr64 = NULL;
 | |
|   BootNext         = NULL;
 | |
| 
 | |
|   ShellProtocol = GetShellProtocol ();
 | |
|   if (ShellProtocol == NULL) {
 | |
|     Print (L"Get Shell Protocol Fail\n");
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Dump capsule provisioned on Memory
 | |
|   //
 | |
|   Print (L"#########################\n");
 | |
|   Print (L"### Capsule on Memory ###\n");
 | |
|   Print (L"#########################\n");
 | |
|   StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CHAR16), EFI_CAPSULE_VARIABLE_NAME);
 | |
|   TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
 | |
|   while (TRUE) {
 | |
|     if (Index > 0) {
 | |
|       UnicodeValueToStringS (
 | |
|         TempVarName,
 | |
|         sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),
 | |
|         0,
 | |
|         Index,
 | |
|         0
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     Status = GetVariable2 (
 | |
|                CapsuleVarName,
 | |
|                &gEfiCapsuleVendorGuid,
 | |
|                (VOID **)&CapsuleDataPtr64,
 | |
|                NULL
 | |
|                );
 | |
|     if (EFI_ERROR (Status) || (CapsuleDataPtr64 == NULL)) {
 | |
|       if (Index == 0) {
 | |
|         Print (L"No data.\n");
 | |
|       }
 | |
| 
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Index++;
 | |
|     Print (L"Capsule Description at 0x%08x\n", *CapsuleDataPtr64);
 | |
|     DumpBlockDescriptors ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)*CapsuleDataPtr64, DumpCapsuleInfo);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Dump capsule provisioned on Disk
 | |
|   //
 | |
|   Print (L"#########################\n");
 | |
|   Print (L"### Capsule on Disk #####\n");
 | |
|   Print (L"#########################\n");
 | |
|   Status = GetVariable2 (
 | |
|              L"BootNext",
 | |
|              &gEfiGlobalVariableGuid,
 | |
|              (VOID **)&BootNext,
 | |
|              NULL
 | |
|              );
 | |
|   if (EFI_ERROR (Status) || (BootNext == NULL)) {
 | |
|     Print (L"Get BootNext Variable Fail. Status = %r\n", Status);
 | |
|   } else {
 | |
|     UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", *BootNext);
 | |
|     Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BootNextOptionEntry);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // Display description and device path
 | |
|       //
 | |
|       GetEfiSysPartitionFromBootOptionFilePath (BootNextOptionEntry.FilePath, &DevicePath, &Fs);
 | |
|       if (!EFI_ERROR (Status)) {
 | |
|         Print (L"Capsules are provisioned on BootOption: %s\n", BootNextOptionEntry.Description);
 | |
|         Print (L"    %s %s\n", ShellProtocol->GetMapFromDevicePath (&DevicePath), ConvertDevicePathToText (DevicePath, TRUE, TRUE));
 | |
|         DumpCapsuleFromDisk (Fs, DumpCapsuleInfo);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump FMP information.
 | |
| 
 | |
|   @param[in] ImageInfoSize       The size of ImageInfo, in bytes.
 | |
|   @param[in] ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | |
|   @param[in] DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | |
|   @param[in] DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | |
|   @param[in] DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
 | |
|   @param[in] PackageVersion      The version of package.
 | |
|   @param[in] PackageVersionName  The version name of package.
 | |
| **/
 | |
| VOID
 | |
| DumpFmpImageInfo (
 | |
|   IN UINTN                          ImageInfoSize,
 | |
|   IN EFI_FIRMWARE_IMAGE_DESCRIPTOR  *ImageInfo,
 | |
|   IN UINT32                         DescriptorVersion,
 | |
|   IN UINT8                          DescriptorCount,
 | |
|   IN UINTN                          DescriptorSize,
 | |
|   IN UINT32                         PackageVersion,
 | |
|   IN CHAR16                         *PackageVersionName
 | |
|   )
 | |
| {
 | |
|   EFI_FIRMWARE_IMAGE_DESCRIPTOR  *CurrentImageInfo;
 | |
|   UINTN                          Index;
 | |
|   UINTN                          Index2;
 | |
| 
 | |
|   Print (L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
 | |
|   Print (L"  DescriptorCount    - 0x%x\n", DescriptorCount);
 | |
|   Print (L"  DescriptorSize     - 0x%x\n", DescriptorSize);
 | |
|   Print (L"  PackageVersion     - 0x%x\n", PackageVersion);
 | |
|   Print (L"  PackageVersionName - \"%s\"\n", PackageVersionName);
 | |
|   CurrentImageInfo = ImageInfo;
 | |
|   for (Index = 0; Index < DescriptorCount; Index++) {
 | |
|     Print (L"  ImageDescriptor (%d)\n", Index);
 | |
|     Print (L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
 | |
|     Print (L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
 | |
|     Print (L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
 | |
|     Print (L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo->ImageIdName);
 | |
|     Print (L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
 | |
|     Print (L"    VersionName                 - \"%s\"\n", CurrentImageInfo->VersionName);
 | |
|     Print (L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
 | |
|     Print (L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo->AttributesSupported);
 | |
|     Print (L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
 | |
|     Print (L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
 | |
|     Print (L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
 | |
|     Print (L"      IN_USE                    - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
 | |
|     Print (L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
 | |
|     Print (L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo->AttributesSetting);
 | |
|     Print (L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
 | |
|     Print (L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
 | |
|     Print (L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
 | |
|     Print (L"      IN_USE                    - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
 | |
|     Print (L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
 | |
|     Print (L"    Compatibilities             - 0x%lx\n", CurrentImageInfo->Compatibilities);
 | |
|     Print (L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo->Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
 | |
|     if (DescriptorVersion > 1) {
 | |
|       Print (L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion);
 | |
|       if (DescriptorVersion > 2) {
 | |
|         Print (L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo->LastAttemptVersion);
 | |
|         Print (L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo->LastAttemptStatus, LastAttemptStatusToString (CurrentImageInfo->LastAttemptStatus));
 | |
|         Print (L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo->HardwareInstance);
 | |
|         if (DescriptorVersion > 3) {
 | |
|           Print (L"    Dependencies                - ");
 | |
|           if (CurrentImageInfo->Dependencies == NULL) {
 | |
|             Print (L"NULL\n");
 | |
|           } else {
 | |
|             Index2 = 0;
 | |
|             do {
 | |
|               Print (L"%02x ", CurrentImageInfo->Dependencies->Dependencies[Index2]);
 | |
|             } while (CurrentImageInfo->Dependencies->Dependencies[Index2++] != EFI_FMP_DEP_END);
 | |
| 
 | |
|             Print (L"\n");
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
 | |
|     //
 | |
|     CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump FMP package information.
 | |
| 
 | |
|   @param[in] PackageVersion             The version of package.
 | |
|   @param[in] PackageVersionName         The version name of package.
 | |
|   @param[in] PackageVersionNameMaxLen   The maximum length of PackageVersionName.
 | |
|   @param[in] AttributesSupported        Package attributes that are supported by this device.
 | |
|   @param[in] AttributesSetting          Package attributes.
 | |
| **/
 | |
| VOID
 | |
| DumpFmpPackageInfo (
 | |
|   IN UINT32  PackageVersion,
 | |
|   IN CHAR16  *PackageVersionName,
 | |
|   IN UINT32  PackageVersionNameMaxLen,
 | |
|   IN UINT64  AttributesSupported,
 | |
|   IN UINT64  AttributesSetting
 | |
|   )
 | |
| {
 | |
|   Print (L"  PackageVersion              - 0x%x\n", PackageVersion);
 | |
|   Print (L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
 | |
|   Print (L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
 | |
|   Print (L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
 | |
|   Print (L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
 | |
|   Print (L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
 | |
|   Print (L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
 | |
|   Print (L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
 | |
|   Print (L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
 | |
|   Print (L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
 | |
|   Print (L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump FMP protocol info.
 | |
| **/
 | |
| VOID
 | |
| DumpFmpData (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;
 | |
|   EFI_HANDLE                        *HandleBuffer;
 | |
|   UINTN                             NumberOfHandles;
 | |
|   UINTN                             Index;
 | |
|   EFI_FIRMWARE_IMAGE_DESCRIPTOR     *FmpImageInfoBuf;
 | |
|   UINTN                             ImageInfoSize;
 | |
|   UINT32                            FmpImageInfoDescriptorVer;
 | |
|   UINT8                             FmpImageInfoCount;
 | |
|   UINTN                             DescriptorSize;
 | |
|   UINT32                            PackageVersion;
 | |
|   CHAR16                            *PackageVersionName;
 | |
|   UINT32                            PackageVersionNameMaxLen;
 | |
|   UINT64                            AttributesSupported;
 | |
|   UINT64                            AttributesSetting;
 | |
| 
 | |
|   Print (L"############\n");
 | |
|   Print (L"# FMP DATA #\n");
 | |
|   Print (L"############\n");
 | |
|   Status = gBS->LocateHandleBuffer (
 | |
|                   ByProtocol,
 | |
|                   &gEfiFirmwareManagementProtocolGuid,
 | |
|                   NULL,
 | |
|                   &NumberOfHandles,
 | |
|                   &HandleBuffer
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Print (L"FMP protocol - %r\n", EFI_NOT_FOUND);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < NumberOfHandles; Index++) {
 | |
|     Status = gBS->HandleProtocol (
 | |
|                     HandleBuffer[Index],
 | |
|                     &gEfiFirmwareManagementProtocolGuid,
 | |
|                     (VOID **)&Fmp
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     ImageInfoSize = 0;
 | |
|     Status        = Fmp->GetImageInfo (
 | |
|                            Fmp,
 | |
|                            &ImageInfoSize,
 | |
|                            NULL,
 | |
|                            NULL,
 | |
|                            NULL,
 | |
|                            NULL,
 | |
|                            NULL,
 | |
|                            NULL
 | |
|                            );
 | |
|     if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     FmpImageInfoBuf = NULL;
 | |
|     FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
 | |
|     if (FmpImageInfoBuf == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto EXIT;
 | |
|     }
 | |
| 
 | |
|     PackageVersionName = NULL;
 | |
|     Status             = Fmp->GetImageInfo (
 | |
|                                 Fmp,
 | |
|                                 &ImageInfoSize,             // ImageInfoSize
 | |
|                                 FmpImageInfoBuf,            // ImageInfo
 | |
|                                 &FmpImageInfoDescriptorVer, // DescriptorVersion
 | |
|                                 &FmpImageInfoCount,         // DescriptorCount
 | |
|                                 &DescriptorSize,            // DescriptorSize
 | |
|                                 &PackageVersion,            // PackageVersion
 | |
|                                 &PackageVersionName         // PackageVersionName
 | |
|                                 );
 | |
| 
 | |
|     //
 | |
|     // If FMP GetInformation interface failed, skip this resource
 | |
|     //
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Print (L"FMP (%d) ImageInfo - %r\n", Index, Status);
 | |
|       FreePool (FmpImageInfoBuf);
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     Print (L"FMP (%d) ImageInfo:\n", Index);
 | |
|     DumpFmpImageInfo (
 | |
|       ImageInfoSize,               // ImageInfoSize
 | |
|       FmpImageInfoBuf,             // ImageInfo
 | |
|       FmpImageInfoDescriptorVer,   // DescriptorVersion
 | |
|       FmpImageInfoCount,           // DescriptorCount
 | |
|       DescriptorSize,              // DescriptorSize
 | |
|       PackageVersion,              // PackageVersion
 | |
|       PackageVersionName           // PackageVersionName
 | |
|       );
 | |
| 
 | |
|     if (PackageVersionName != NULL) {
 | |
|       FreePool (PackageVersionName);
 | |
|     }
 | |
| 
 | |
|     FreePool (FmpImageInfoBuf);
 | |
| 
 | |
|     //
 | |
|     // Get package info
 | |
|     //
 | |
|     PackageVersionName = NULL;
 | |
|     Status             = Fmp->GetPackageInfo (
 | |
|                                 Fmp,
 | |
|                                 &PackageVersion,           // PackageVersion
 | |
|                                 &PackageVersionName,       // PackageVersionName
 | |
|                                 &PackageVersionNameMaxLen, // PackageVersionNameMaxLen
 | |
|                                 &AttributesSupported,      // AttributesSupported
 | |
|                                 &AttributesSetting         // AttributesSetting
 | |
|                                 );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Print (L"FMP (%d) PackageInfo - %r\n", Index, Status);
 | |
|     } else {
 | |
|       Print (L"FMP (%d) ImageInfo:\n", Index);
 | |
|       DumpFmpPackageInfo (
 | |
|         PackageVersion,              // PackageVersion
 | |
|         PackageVersionName,          // PackageVersionName
 | |
|         PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
 | |
|         AttributesSupported,         // AttributesSupported
 | |
|         AttributesSetting            // AttributesSetting
 | |
|         );
 | |
| 
 | |
|       if (PackageVersionName != NULL) {
 | |
|         FreePool (PackageVersionName);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Print (L"\n");
 | |
| 
 | |
| EXIT:
 | |
|   FreePool (HandleBuffer);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check if the ImageInfo includes the ImageTypeId.
 | |
| 
 | |
|   @param[in] ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | |
|   @param[in] DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
 | |
|   @param[in] DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
 | |
|   @param[in] ImageTypeId         A unique GUID identifying the firmware image type.
 | |
| 
 | |
|   @return TRUE  This ImageInfo includes the ImageTypeId
 | |
|   @return FALSE This ImageInfo does not include the ImageTypeId
 | |
| **/
 | |
| BOOLEAN
 | |
| IsThisFmpImageInfo (
 | |
|   IN EFI_FIRMWARE_IMAGE_DESCRIPTOR  *ImageInfo,
 | |
|   IN UINT8                          DescriptorCount,
 | |
|   IN UINTN                          DescriptorSize,
 | |
|   IN EFI_GUID                       *ImageTypeId
 | |
|   )
 | |
| {
 | |
|   EFI_FIRMWARE_IMAGE_DESCRIPTOR  *CurrentImageInfo;
 | |
|   UINTN                          Index;
 | |
| 
 | |
|   CurrentImageInfo = ImageInfo;
 | |
|   for (Index = 0; Index < DescriptorCount; Index++) {
 | |
|     if (CompareGuid (&CurrentImageInfo->ImageTypeId, ImageTypeId)) {
 | |
|       return TRUE;
 | |
|     }
 | |
| 
 | |
|     CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   return the FMP whoes ImageInfo includes the ImageTypeId.
 | |
| 
 | |
|   @param[in] ImageTypeId         A unique GUID identifying the firmware image type.
 | |
| 
 | |
|   @return The FMP whoes ImageInfo includes the ImageTypeId
 | |
| **/
 | |
| EFI_FIRMWARE_MANAGEMENT_PROTOCOL *
 | |
| FindFmpFromImageTypeId (
 | |
|   IN EFI_GUID  *ImageTypeId
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;
 | |
|   EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *TargetFmp;
 | |
|   EFI_HANDLE                        *HandleBuffer;
 | |
|   UINTN                             NumberOfHandles;
 | |
|   UINTN                             Index;
 | |
|   EFI_FIRMWARE_IMAGE_DESCRIPTOR     *FmpImageInfoBuf;
 | |
|   UINTN                             ImageInfoSize;
 | |
|   UINT32                            FmpImageInfoDescriptorVer;
 | |
|   UINT8                             FmpImageInfoCount;
 | |
|   UINTN                             DescriptorSize;
 | |
|   UINT32                            PackageVersion;
 | |
|   CHAR16                            *PackageVersionName;
 | |
| 
 | |
|   Status = gBS->LocateHandleBuffer (
 | |
|                   ByProtocol,
 | |
|                   &gEfiFirmwareManagementProtocolGuid,
 | |
|                   NULL,
 | |
|                   &NumberOfHandles,
 | |
|                   &HandleBuffer
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Print (L"FMP protocol - %r\n", EFI_NOT_FOUND);
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   TargetFmp = NULL;
 | |
|   for (Index = 0; Index < NumberOfHandles; Index++) {
 | |
|     Status = gBS->HandleProtocol (
 | |
|                     HandleBuffer[Index],
 | |
|                     &gEfiFirmwareManagementProtocolGuid,
 | |
|                     (VOID **)&Fmp
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     ImageInfoSize = 0;
 | |
|     Status        = Fmp->GetImageInfo (
 | |
|                            Fmp,
 | |
|                            &ImageInfoSize,
 | |
|                            NULL,
 | |
|                            NULL,
 | |
|                            NULL,
 | |
|                            NULL,
 | |
|                            NULL,
 | |
|                            NULL
 | |
|                            );
 | |
|     if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     FmpImageInfoBuf = NULL;
 | |
|     FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
 | |
|     if (FmpImageInfoBuf == NULL) {
 | |
|       FreePool (HandleBuffer);
 | |
|       Print (L"Out of resource\n");
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|     PackageVersionName = NULL;
 | |
|     Status             = Fmp->GetImageInfo (
 | |
|                                 Fmp,
 | |
|                                 &ImageInfoSize,             // ImageInfoSize
 | |
|                                 FmpImageInfoBuf,            // ImageInfo
 | |
|                                 &FmpImageInfoDescriptorVer, // DescriptorVersion
 | |
|                                 &FmpImageInfoCount,         // DescriptorCount
 | |
|                                 &DescriptorSize,            // DescriptorSize
 | |
|                                 &PackageVersion,            // PackageVersion
 | |
|                                 &PackageVersionName         // PackageVersionName
 | |
|                                 );
 | |
| 
 | |
|     //
 | |
|     // If FMP GetInformation interface failed, skip this resource
 | |
|     //
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       FreePool (FmpImageInfoBuf);
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if (PackageVersionName != NULL) {
 | |
|       FreePool (PackageVersionName);
 | |
|     }
 | |
| 
 | |
|     if (IsThisFmpImageInfo (FmpImageInfoBuf, FmpImageInfoCount, DescriptorSize, ImageTypeId)) {
 | |
|       TargetFmp = Fmp;
 | |
|     }
 | |
| 
 | |
|     FreePool (FmpImageInfoBuf);
 | |
|     if (TargetFmp != NULL) {
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   FreePool (HandleBuffer);
 | |
|   return TargetFmp;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump FMP image data.
 | |
| 
 | |
|   @param[in]  ImageTypeId   The ImageTypeId of the FMP image.
 | |
|                             It is used to identify the FMP protocol.
 | |
|   @param[in]  ImageIndex    The ImageIndex of the FMP image.
 | |
|                             It is the input parameter for FMP->GetImage().
 | |
|   @param[in]  ImageName     The file name to hold the output FMP image.
 | |
| **/
 | |
| VOID
 | |
| DumpFmpImage (
 | |
|   IN EFI_GUID  *ImageTypeId,
 | |
|   IN UINTN     ImageIndex,
 | |
|   IN CHAR16    *ImageName
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;
 | |
|   VOID                              *Image;
 | |
|   UINTN                             ImageSize;
 | |
| 
 | |
|   Fmp = FindFmpFromImageTypeId (ImageTypeId);
 | |
|   if (Fmp == NULL) {
 | |
|     Print (L"No FMP include ImageTypeId %g\n", ImageTypeId);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (ImageIndex > 0xFF) {
 | |
|     Print (L"ImageIndex 0x%x too big\n", ImageIndex);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Image     = Fmp;
 | |
|   ImageSize = 0;
 | |
|   Status    = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);
 | |
|   if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|     Print (L"Fmp->GetImage - %r\n", Status);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Image = AllocatePool (ImageSize);
 | |
|   if (Image == NULL) {
 | |
|     Print (L"Allocate FmpImage 0x%x - %r\n", ImageSize, EFI_OUT_OF_RESOURCES);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Print (L"Fmp->GetImage - %r\n", Status);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Status = WriteFileFromBuffer (ImageName, ImageSize, Image);
 | |
|   Print (L"CapsuleApp: Dump %g ImageIndex (0x%x) to %s %r\n", ImageTypeId, ImageIndex, ImageName, Status);
 | |
| 
 | |
|   FreePool (Image);
 | |
| 
 | |
|   return;
 | |
| }
 |