diff options
Diffstat (limited to 'MdeModulePkg/Application/CapsuleApp/CapsuleDump.c')
| -rw-r--r-- | MdeModulePkg/Application/CapsuleApp/CapsuleDump.c | 2936 |
1 files changed, 1468 insertions, 1468 deletions
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c index 7605153e97..11bc505353 100644 --- a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c @@ -1,1468 +1,1468 @@ -/** @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
-EFIAPI
-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;
-}
+/** @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 +EFIAPI +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; +} |
