summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c1444
1 files changed, 1444 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
new file mode 100644
index 00000000..0f8ddbb7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
@@ -0,0 +1,1444 @@
+/** @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 ;
+}