]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
MdeModulePkg CapsuleApp: Check Buffer against NULL before freeing it
[mirror_edk2.git] / MdeModulePkg / Application / CapsuleApp / CapsuleDump.c
index 9291ba3af358d594a8a2ee4b245e0f4480442ffc..6c1320942bf423929e5cc6c67c9f66d12e5e8639 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Dump Capsule image information.\r
 \r
-  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -31,9 +31,9 @@
 /**\r
   Read a file.\r
 \r
-  @param[in] FileName        The file to be read.\r
-  @param[in] BufferSize      The file buffer size\r
-  @param[in] Buffer          The file buffer\r
+  @param[in]  FileName        The file to be read.\r
+  @param[out] BufferSize      The file buffer size\r
+  @param[out] Buffer          The file buffer\r
 \r
   @retval EFI_SUCCESS    Read file successfully\r
   @retval EFI_NOT_FOUND  File not found\r
@@ -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
@@ -226,6 +242,7 @@ DumpCapsule (
   EFI_CAPSULE_HEADER                            *CapsuleHeader;\r
   EFI_STATUS                                    Status;\r
 \r
+  Buffer = NULL;\r
   Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);\r
   if (EFI_ERROR(Status)) {\r
     Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);\r
@@ -253,7 +270,9 @@ DumpCapsule (
   }\r
 \r
 Done:\r
-  FreePool(Buffer);\r
+  if (Buffer != NULL) {\r
+    FreePool(Buffer);\r
+  }\r
   return Status;\r
 }\r
 \r
@@ -277,6 +296,8 @@ DmpCapsuleStatusVariable (
   UINTN                               CapsuleFileNameSize;\r
   CHAR16                              CapsuleIndexData[12];\r
   CHAR16                              *CapsuleIndex;\r
+  CHAR16                              *CapsuleFileName;\r
+  CHAR16                              *CapsuleTarget;\r
 \r
   Status = GetVariable2(\r
              L"CapsuleMax",\r
@@ -285,6 +306,7 @@ DmpCapsuleStatusVariable (
              NULL\r
              );\r
   if (!EFI_ERROR(Status)) {\r
+    ASSERT (CapsuleIndex != NULL);\r
     CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));\r
     CapsuleIndexData[11] = 0;\r
     Print(L"CapsuleMax - %s\n", CapsuleIndexData);\r
@@ -297,6 +319,7 @@ DmpCapsuleStatusVariable (
              NULL\r
              );\r
   if (!EFI_ERROR(Status)) {\r
+    ASSERT (CapsuleIndex != NULL);\r
     CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));\r
     CapsuleIndexData[11] = 0;\r
     Print(L"CapsuleLast - %s\n", CapsuleIndexData);\r
@@ -335,19 +358,17 @@ DmpCapsuleStatusVariable (
     }\r
 \r
     if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {\r
-      if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {\r
+      if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) * 2) {\r
         CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);\r
         Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);\r
         Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);\r
         Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp->UpdateImageIndex);\r
         Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp->UpdateImageTypeId);\r
-        if (CapsuleResult->VariableTotalSize > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {\r
-          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));\r
-          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));\r
-          if (CapsuleResult->VariableTotalSize > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapsuleFileNameSize) {\r
-            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp + 1) + CapsuleFileNameSize);\r
-          }\r
-        }\r
+        CapsuleFileName = (CHAR16 *)(CapsuleResultFmp + 1);\r
+        Print(L"  Capsule FMP CapsuleFileName: \"%s\"\n", CapsuleFileName);\r
+        CapsuleFileNameSize = StrSize(CapsuleFileName);\r
+        CapsuleTarget = (CHAR16 *)((UINTN)CapsuleFileName + CapsuleFileNameSize);\r
+        Print(L"  Capsule FMP CapsuleTarget: \"%s\"\n", CapsuleTarget);\r
       }\r
     }\r
 \r
@@ -736,3 +757,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