]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
MdeModulePkg CapsuleApp: Remove a redundant function
[mirror_edk2.git] / MdeModulePkg / Application / CapsuleApp / CapsuleDump.c
index d09b938fed3b7a70e11da1d1f30b3366f3f5269c..7a3eb9436249deb31e6a356609d2897cea80bd28 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,40 @@ 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
+  Validate if it is valid capsule header\r
+\r
+  This function assumes the caller provided correct CapsuleHeader pointer\r
+  and CapsuleSize.\r
+\r
+  This function validates the fields in EFI_CAPSULE_HEADER.\r
+\r
+  @param[in] CapsuleHeader  Points to a capsule header.\r
+  @param[in] CapsuleSize    Size of the whole capsule image.\r
+\r
+**/\r
+BOOLEAN\r
+IsValidCapsuleHeader (\r
+  IN EFI_CAPSULE_HEADER     *CapsuleHeader,\r
+  IN UINT64                 CapsuleSize\r
+  );\r
+\r
 /**\r
   Dump UX capsule information.\r
 \r
@@ -72,37 +106,6 @@ DumpUxCapsule (
   Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);\r
 }\r
 \r
-/**\r
-  Dump FMP image authentication information.\r
-\r
-  @param[in] Image      The FMP capsule image\r
-  @param[in] ImageSize  The size of the FMP capsule image in bytes.\r
-\r
-  @return the size of FMP authentication.\r
-**/\r
-UINTN\r
-DumpImageAuthentication (\r
-  IN VOID   *Image,\r
-  IN UINTN  ImageSize\r
-  )\r
-{\r
-  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;\r
-\r
-  ImageAuthentication = Image;\r
-  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||\r
-      CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertTypeRsa2048Sha256Guid)) {\r
-    Print(L"[ImageAuthentication]\n");\r
-    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);\r
-    Print(L"WIN_CERTIFICATE:\n");\r
-    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);\r
-    Print(L"  wRevision        - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wRevision);\r
-    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wCertificateType);\r
-    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);\r
-    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication->AuthInfo.Hdr.dwLength;\r
-  } else {\r
-    return 0;\r
-  }\r
-}\r
 \r
 /**\r
   Dump a non-nested FMP capsule.\r
@@ -198,7 +201,7 @@ IsNestedFmpCapsule (
   // FMP GUID after ESRT one\r
   //\r
   NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);\r
-  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize - (UINTN)NestedCapsuleHeader;\r
+  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize- (UINTN)NestedCapsuleHeader;\r
   if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {\r
     return FALSE;\r
   }\r
@@ -226,11 +229,17 @@ 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
     goto Done;\r
   }\r
+  if (!IsValidCapsuleHeader (Buffer, FileSize)) {\r
+    Print(L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  }\r
 \r
   CapsuleHeader = Buffer;\r
   if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {\r
@@ -253,7 +262,9 @@ DumpCapsule (
   }\r
 \r
 Done:\r
-  FreePool(Buffer);\r
+  if (Buffer != NULL) {\r
+    FreePool(Buffer);\r
+  }\r
   return Status;\r
 }\r
 \r
@@ -264,7 +275,7 @@ Done:
   @retval EFI_UNSUPPORTED        Input parameter is not valid.\r
 **/\r
 EFI_STATUS\r
-DmpCapsuleStatusVariable (\r
+DumpCapsuleStatusVariable (\r
   VOID\r
   )\r
 {\r
@@ -277,6 +288,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
@@ -337,19 +350,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
@@ -435,9 +446,6 @@ DumpEsrtEntry (
   Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);\r
   Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);\r
   Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);\r
-  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET);\r
-  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);\r
-  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_INITIATE_RESET);\r
   Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);\r
   Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus, LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));\r
 }\r
@@ -738,3 +746,203 @@ 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
+  FreePool (Image);\r
+\r
+  return ;\r
+}\r