+\r
+/**\r
+ Check if the ImageInfo includes the ImageTypeId.\r
+\r
+ @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+ @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+ @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.\r
+ @param[in] ImageTypeId A unique GUID identifying the firmware image type.\r
+\r
+ @return TRUE This ImageInfo includes the ImageTypeId\r
+ @return FALSE This ImageInfo does not include the ImageTypeId\r
+**/\r
+BOOLEAN\r
+IsThisFmpImageInfo (\r
+ IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,\r
+ IN UINT8 DescriptorCount,\r
+ IN UINTN DescriptorSize,\r
+ IN EFI_GUID *ImageTypeId\r
+ )\r
+{\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageInfo;\r
+ UINTN Index;\r
+\r
+ CurrentImageInfo = ImageInfo;\r
+ for (Index = 0; Index < DescriptorCount; Index++) {\r
+ if (CompareGuid (&CurrentImageInfo->ImageTypeId, ImageTypeId)) {\r
+ return TRUE;\r
+ }\r
+ CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ return the FMP whoes ImageInfo includes the ImageTypeId.\r
+\r
+ @param[in] ImageTypeId A unique GUID identifying the firmware image type.\r
+\r
+ @return The FMP whoes ImageInfo includes the ImageTypeId\r
+**/\r
+EFI_FIRMWARE_MANAGEMENT_PROTOCOL *\r
+FindFmpFromImageTypeId (\r
+ IN EFI_GUID *ImageTypeId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *TargetFmp;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN NumberOfHandles;\r
+ UINTN Index;\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
+ UINTN ImageInfoSize;\r
+ UINT32 FmpImageInfoDescriptorVer;\r
+ UINT8 FmpImageInfoCount;\r
+ UINTN DescriptorSize;\r
+ UINT32 PackageVersion;\r
+ CHAR16 *PackageVersionName;\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ NULL,\r
+ &NumberOfHandles,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);\r
+ return NULL;\r
+ }\r
+\r
+ TargetFmp = NULL;\r
+ for (Index = 0; Index < NumberOfHandles; Index++) {\r
+ Status = gBS->HandleProtocol(\r
+ HandleBuffer[Index],\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ (VOID **)&Fmp\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ continue;\r
+ }\r
+\r
+ ImageInfoSize = 0;\r
+ Status = Fmp->GetImageInfo (\r
+ Fmp,\r
+ &ImageInfoSize,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ continue;\r
+ }\r
+\r
+ FmpImageInfoBuf = NULL;\r
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
+ if (FmpImageInfoBuf == NULL) {\r
+ FreePool(HandleBuffer);\r
+ Print(L"Out of resource\n");\r
+ return NULL;\r
+ }\r
+\r
+ PackageVersionName = NULL;\r
+ Status = Fmp->GetImageInfo (\r
+ Fmp,\r
+ &ImageInfoSize, // ImageInfoSize\r
+ FmpImageInfoBuf, // ImageInfo\r
+ &FmpImageInfoDescriptorVer, // DescriptorVersion\r
+ &FmpImageInfoCount, // DescriptorCount\r
+ &DescriptorSize, // DescriptorSize\r
+ &PackageVersion, // PackageVersion\r
+ &PackageVersionName // PackageVersionName\r
+ );\r
+\r
+ //\r
+ // If FMP GetInformation interface failed, skip this resource\r
+ //\r
+ if (EFI_ERROR(Status)) {\r
+ FreePool(FmpImageInfoBuf);\r
+ continue;\r
+ }\r
+\r
+ if (PackageVersionName != NULL) {\r
+ FreePool(PackageVersionName);\r
+ }\r
+\r
+ if (IsThisFmpImageInfo (FmpImageInfoBuf, FmpImageInfoCount, DescriptorSize, ImageTypeId)) {\r
+ TargetFmp = Fmp;\r
+ }\r
+ FreePool(FmpImageInfoBuf);\r
+ if (TargetFmp != NULL) {\r
+ break;\r
+ }\r
+ }\r
+ FreePool(HandleBuffer);\r
+ return TargetFmp;\r
+}\r
+\r
+/**\r
+ Dump FMP image data.\r
+\r
+ @param[in] ImageTypeId The ImageTypeId of the FMP image.\r
+ It is used to identify the FMP protocol.\r
+ @param[in] ImageIndex The ImageIndex of the FMP image.\r
+ It is the input parameter for FMP->GetImage().\r
+ @param[in] ImageName The file name to hold the output FMP image.\r
+**/\r
+VOID\r
+DumpFmpImage (\r
+ IN EFI_GUID *ImageTypeId,\r
+ IN UINTN ImageIndex,\r
+ IN CHAR16 *ImageName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
+ VOID *Image;\r
+ UINTN ImageSize;\r
+\r
+ Fmp = FindFmpFromImageTypeId (ImageTypeId);\r
+ if (Fmp == NULL) {\r
+ Print(L"No FMP include ImageTypeId %g\n", ImageTypeId);\r
+ return ;\r
+ }\r
+\r
+ if (ImageIndex > 0xFF) {\r
+ Print(L"ImageIndex 0x%x too big\n", ImageIndex);\r
+ return ;\r
+ }\r
+\r
+ Image = Fmp;\r
+ ImageSize = 0;\r
+ Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ Print(L"Fmp->GetImage - %r\n", Status);\r
+ return ;\r
+ }\r
+\r
+ Image = AllocatePool (ImageSize);\r
+ if (Image == NULL) {\r
+ Print(L"Allocate FmpImage 0x%x - %r\n", ImageSize, EFI_OUT_OF_RESOURCES);\r
+ return ;\r
+ }\r
+\r
+ Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);\r
+ if (EFI_ERROR(Status)) {\r
+ Print(L"Fmp->GetImage - %r\n", Status);\r
+ return ;\r
+ }\r
+\r
+ Status = WriteFileFromBuffer(ImageName, ImageSize, Image);\r
+ Print(L"CapsuleApp: Dump %g ImageIndex (0x%x) to %s %r\n", ImageTypeId, ImageIndex, ImageName, Status);\r
+\r
+ return ;\r
+}\r