]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
MdeModulePkg/CapsuleApp: Add Fmp->GetImage() support.
[mirror_edk2.git] / MdeModulePkg / Application / CapsuleApp / CapsuleDump.c
index d09b938fed3b7a70e11da1d1f30b3366f3f5269c..3d83ec4498a3b5eddca4982cb046de83430eaa86 100644 (file)
@@ -45,6 +45,22 @@ ReadFileToBuffer (
   OUT VOID                                 **Buffer\r
   );\r
 \r
+/**\r
+  Write a file.\r
+\r
+  @param[in] FileName        The file to be written.\r
+  @param[in] BufferSize      The file buffer size\r
+  @param[in] Buffer          The file buffer\r
+\r
+  @retval EFI_SUCCESS    Write file successfully\r
+**/\r
+EFI_STATUS\r
+WriteFileFromBuffer (\r
+  IN  CHAR16                               *FileName,\r
+  IN  UINTN                                BufferSize,\r
+  IN  VOID                                 *Buffer\r
+  );\r
+\r
 /**\r
   Dump UX capsule information.\r
 \r
@@ -738,3 +754,201 @@ DumpFmpData (
 EXIT:\r
   FreePool(HandleBuffer);\r
 }\r
+\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