| /** @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 | |
| ); | |
| /** | |
| 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 FMP image authentication information. | |
| @param[in] Image The FMP capsule image | |
| @param[in] ImageSize The size of the FMP capsule image in bytes. | |
| @return the size of FMP authentication. | |
| **/ | |
| UINTN | |
| DumpImageAuthentication ( | |
| IN VOID *Image, | |
| IN UINTN ImageSize | |
| ) | |
| { | |
| EFI_FIRMWARE_IMAGE_AUTHENTICATION *ImageAuthentication; | |
| ImageAuthentication = Image; | |
| if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) || | |
| CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertTypeRsa2048Sha256Guid)) { | |
| Print(L"[ImageAuthentication]\n"); | |
| Print(L" MonotonicCount - 0x%lx\n", ImageAuthentication->MonotonicCount); | |
| Print(L"WIN_CERTIFICATE:\n"); | |
| Print(L" dwLength - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength); | |
| Print(L" wRevision - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wRevision); | |
| Print(L" wCertificateType - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wCertificateType); | |
| Print(L" CertType - %g\n", &ImageAuthentication->AuthInfo.CertType); | |
| return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication->AuthInfo.Hdr.dwLength; | |
| } else { | |
| return 0; | |
| } | |
| } | |
| /** | |
| 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->HeaderSize - (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; | |
| } | |
| 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 | |
| DmpCapsuleStatusVariable ( | |
| 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" PERSIST_ACROSS_RESET - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET); | |
| Print(L" POPULATE_SYSTEM_TABLE - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE); | |
| Print(L" INITIATE_RESET - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_INITIATE_RESET); | |
| 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); | |
| return ; | |
| } |