mirror of https://github.com/acidanthera/audk.git
949 lines
34 KiB
C
949 lines
34 KiB
C
/** @file
|
|
Dump Capsule image information.
|
|
|
|
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#include <PiDxe.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/PrintLib.h>
|
|
#include <Protocol/FirmwareManagement.h>
|
|
#include <Guid/ImageAuthentication.h>
|
|
#include <Guid/CapsuleReport.h>
|
|
#include <Guid/SystemResourceTable.h>
|
|
#include <Guid/FmpCapsule.h>
|
|
#include <IndustryStandard/WindowsUxCapsule.h>
|
|
|
|
/**
|
|
Read a file.
|
|
|
|
@param[in] FileName The file to be read.
|
|
@param[out] BufferSize The file buffer size
|
|
@param[out] Buffer The file buffer
|
|
|
|
@retval EFI_SUCCESS Read file successfully
|
|
@retval EFI_NOT_FOUND File not found
|
|
**/
|
|
EFI_STATUS
|
|
ReadFileToBuffer (
|
|
IN CHAR16 *FileName,
|
|
OUT UINTN *BufferSize,
|
|
OUT VOID **Buffer
|
|
);
|
|
|
|
/**
|
|
Write a file.
|
|
|
|
@param[in] FileName The file to be written.
|
|
@param[in] BufferSize The file buffer size
|
|
@param[in] Buffer The file buffer
|
|
|
|
@retval EFI_SUCCESS Write file successfully
|
|
**/
|
|
EFI_STATUS
|
|
WriteFileFromBuffer (
|
|
IN CHAR16 *FileName,
|
|
IN UINTN BufferSize,
|
|
IN VOID *Buffer
|
|
);
|
|
|
|
/**
|
|
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"[UxCapusule]\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"[FmpCapusule]\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 >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
|
|
Print(L" UpdateHardwareInstance - 0x%lx\n", FmpImageHeader->UpdateHardwareInstance);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
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"[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));
|
|
}
|
|
|
|
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",
|
|
};
|
|
|
|
/**
|
|
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 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;
|
|
|
|
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);
|
|
}
|
|
}
|
|
//
|
|
// 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 ;
|
|
}
|