]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
MdeModulePkg CapsuleApp: Refine -N option help information
[mirror_edk2.git] / MdeModulePkg / Application / CapsuleApp / CapsuleApp.c
index 6febe846b1406f1f9098114061b3ccd95877dd09..3a87439f104eb8958772778b3f1d566bb6b628db 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   A shell application that triggers capsule update process.\r
 \r
-  Copyright (c) 2016 - 2017, 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
 #include <Library/UefiRuntimeServicesTableLib.h>\r
 #include <Library/UefiLib.h>\r
 #include <Library/PrintLib.h>\r
-#include <Protocol/LoadedImage.h>\r
-#include <Protocol/SimpleFileSystem.h>\r
+#include <Library/BmpSupportLib.h>\r
 #include <Protocol/GraphicsOutput.h>\r
-#include <Guid/FileInfo.h>\r
-#include <Guid/Gpt.h>\r
 #include <Guid/GlobalVariable.h>\r
 #include <Guid/CapsuleReport.h>\r
 #include <Guid/SystemResourceTable.h>\r
@@ -117,7 +114,8 @@ DumpEsrtData (
   @param[out] Buffer          The file buffer\r
 \r
   @retval EFI_SUCCESS    Read file successfully\r
-  @retval EFI_NOT_FOUND  File not found\r
+  @retval EFI_NOT_FOUND  Shell protocol or file not found\r
+  @retval others         Read file failed\r
 **/\r
 EFI_STATUS\r
 ReadFileToBuffer (\r
@@ -134,6 +132,8 @@ ReadFileToBuffer (
   @param[in] Buffer          The file buffer\r
 \r
   @retval EFI_SUCCESS    Write file successfully\r
+  @retval EFI_NOT_FOUND  Shell protocol not found\r
+  @retval others         Write file failed\r
 **/\r
 EFI_STATUS\r
 WriteFileFromBuffer (\r
@@ -174,20 +174,26 @@ CreateBmpFmp (
   EFI_DISPLAY_CAPSULE                           *DisplayCapsule;\r
   EFI_STATUS                                    Status;\r
   EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION          *Info;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL                 *GopBlt;\r
+  UINTN                                         GopBltSize;\r
+  UINTN                                         Height;\r
+  UINTN                                         Width;\r
 \r
   Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);\r
   if (EFI_ERROR(Status)) {\r
     Print(L"CapsuleApp: NO GOP is found.\n");\r
     return EFI_UNSUPPORTED;\r
   }\r
+  Info = Gop->Mode->Info;\r
   Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);\r
-  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);\r
-  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);\r
+  Print(L"HorizontalResolution - %d, ", Info->HorizontalResolution);\r
+  Print(L"VerticalResolution - %d\n", Info->VerticalResolution);\r
   // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth\r
   // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight\r
 \r
   if (Argc != 5) {\r
-    Print(L"CapsuleApp: Invalid Parameter.\n");\r
+    Print(L"CapsuleApp: Incorrect parameter count.\n");\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
@@ -208,6 +214,35 @@ CreateBmpFmp (
     goto Done;\r
   }\r
 \r
+  GopBlt = NULL;\r
+  Status = TranslateBmpToGopBlt (\r
+             BmpBuffer,\r
+             FileSize,\r
+             &GopBlt,\r
+             &GopBltSize,\r
+             &Height,\r
+             &Width\r
+             );\r
+  if (EFI_ERROR(Status)) {\r
+    Print(L"CapsuleApp: BMP image (%s) is not valid.\n", BmpName);\r
+    goto Done;\r
+  }\r
+  if (GopBlt != NULL) {\r
+    FreePool (GopBlt);\r
+  }\r
+  Print(L"BMP image (%s), Width - %d, Height - %d\n", BmpName, Width, Height);\r
+\r
+  if (Height > Info->VerticalResolution) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    Print(L"CapsuleApp: BMP image (%s) height is larger than current resolution.\n", BmpName);\r
+    goto Done;\r
+  }\r
+  if (Width > Info->HorizontalResolution) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    Print(L"CapsuleApp: BMP image (%s) width is larger than current resolution.\n", BmpName);\r
+    goto Done;\r
+  }\r
+\r
   FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;\r
   FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);\r
   if (FullCapsuleBuffer == NULL) {\r
@@ -227,8 +262,27 @@ CreateBmpFmp (
   DisplayCapsule->ImagePayload.ImageType = 0; // BMP\r
   DisplayCapsule->ImagePayload.Reserved = 0;\r
   DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;\r
-  DisplayCapsule->ImagePayload.OffsetX = 0;\r
-  DisplayCapsule->ImagePayload.OffsetY = 0;\r
+\r
+  //\r
+  // Center the bitmap horizontally\r
+  //\r
+  DisplayCapsule->ImagePayload.OffsetX = (UINT32)((Info->HorizontalResolution - Width) / 2);\r
+\r
+  //\r
+  // Put bitmap 3/4 down the display.  If bitmap is too tall, then align bottom\r
+  // of bitmap at bottom of display.\r
+  //\r
+  DisplayCapsule->ImagePayload.OffsetY =\r
+    MIN (\r
+      (UINT32)(Info->VerticalResolution - Height),\r
+      (UINT32)(((3 * Info->VerticalResolution) - (2 * Height)) / 4)\r
+      );\r
+\r
+  Print(L"BMP image (%s), OffsetX - %d, OffsetY - %d\n",\r
+    BmpName,\r
+    DisplayCapsule->ImagePayload.OffsetX,\r
+    DisplayCapsule->ImagePayload.OffsetY\r
+    );\r
 \r
   CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);\r
 \r
@@ -333,7 +387,7 @@ CreateNestedFmp (
   EFI_STATUS                                    Status;\r
 \r
   if (Argc != 5) {\r
-    Print(L"CapsuleApp: Invalid Parameter.\n");\r
+    Print(L"CapsuleApp: Incorrect parameter count.\n");\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
@@ -377,7 +431,7 @@ CreateNestedFmp (
   ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);\r
   CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);\r
   NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;\r
-  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ? SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;\r
+  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_SYSTEMFIRMWARE) ? SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;\r
   NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;\r
 \r
   CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize, CapsuleBuffer, FileSize);\r
@@ -498,7 +552,7 @@ BuildGatherList (
       goto ERREXIT;\r
     } else {\r
       Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN) BlockDescriptors1);\r
-      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n", (UINTN) CapsuleBuffer, FileSize);\r
+      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n", (UINTN) CapsuleBuffer[Index], FileSize[Index]);\r
     }\r
 \r
     //\r
@@ -654,13 +708,47 @@ CleanGatherList (
         break;\r
       }\r
 \r
-      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);\r
+      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr[Index].Union.ContinuationPointer);\r
       FreePool(TempBlockPtr1);\r
       TempBlockPtr1 = TempBlockPtr2;\r
     }\r
   }\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
+  if (CapsuleSize < sizeof (EFI_CAPSULE_HEADER)) {\r
+    return FALSE;\r
+  }\r
+  if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {\r
+    return FALSE;\r
+  }\r
+  if (CapsuleHeader->HeaderSize > CapsuleHeader->CapsuleImageSize) {\r
+    return FALSE;\r
+  }\r
+  if (CapsuleHeader->HeaderSize < sizeof (EFI_CAPSULE_HEADER)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
 /**\r
   Print APP usage.\r
 **/\r
@@ -684,17 +772,19 @@ PrintUsage (
   Print(L"       with CAPSULE_FLAGS_PERSIST_ACROSS_RESET and without CAPSULE_FLAGS_INITIATE_RESET.\n");\r
   Print(L"  -S:  Dump capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");\r
   Print(L"       which is defined in UEFI specification.\n");\r
-  Print(L"  -C:  Clear capsule report variable (EFI_CAPSULE_RPORT_GUID),\n");\r
+  Print(L"  -C:  Clear capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");\r
   Print(L"       which is defined in UEFI specification.\n");\r
-  Print(L"  -P:  Dump UEFI FMP protocol info.\n");\r
+  Print(L"  -P:  Dump UEFI FMP protocol info, or get image with specified\n");\r
+  Print(L"       ImageTypeId and index to a file if 'GET' option is used.\n");\r
   Print(L"  -E:  Dump UEFI ESRT table info.\n");\r
-  Print(L"  -G:  Convert a BMP file to be a UX capsule,\n");\r
+  Print(L"  -G:  Convert a BMP file to be an UX capsule,\n");\r
   Print(L"       according to Windows Firmware Update document\n");\r
-  Print(L"  -N:  Append a Capsule Header to an existing capsule image,\n");\r
+  Print(L"  -N:  Append a Capsule Header to an existing FMP capsule image\n");\r
+  Print(L"       with its ImageTypeId supported by the system,\n");\r
   Print(L"       according to Windows Firmware Update document\n");\r
   Print(L"  -O:  Output new Capsule file name\n");\r
-  Print(L"  -D:  Dump Capsule image header information and FMP header information,\n");\r
-  Print(L"       if it is an FMP capsule.\n");\r
+  Print(L"  -D:  Dump Capsule image header information, image payload information if it is an UX capsule\n");\r
+  Print(L"       and FMP header information if it is a FMP capsule.\n");\r
 }\r
 \r
 /**\r
@@ -704,7 +794,8 @@ PrintUsage (
   @param[in]  SystemTable     The system table.\r
 \r
   @retval EFI_SUCCESS            Command completed successfully.\r
-  @retval EFI_INVALID_PARAMETER  Command usage error.\r
+  @retval EFI_UNSUPPORTED        Command usage unsupported.\r
+  @retval EFI_INVALID_PARAMETER  Command usage invalid.\r
   @retval EFI_NOT_FOUND          The input file can't be found.\r
 **/\r
 EFI_STATUS\r
@@ -719,14 +810,16 @@ UefiMain (
   UINTN                         FileSize[MAX_CAPSULE_NUM];\r
   VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];\r
   EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;\r
-  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];\r
-  UINT64                         MaxCapsuleSize;\r
-  EFI_RESET_TYPE                 ResetType;\r
-  BOOLEAN                        NeedReset;\r
-  BOOLEAN                        NoReset;\r
-  CHAR16                         *CapsuleName;\r
-  UINTN                          CapsuleNum;\r
-  UINTN                          Index;\r
+  EFI_CAPSULE_HEADER            *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];\r
+  UINT64                        MaxCapsuleSize;\r
+  EFI_RESET_TYPE                ResetType;\r
+  BOOLEAN                       NeedReset;\r
+  BOOLEAN                       NoReset;\r
+  CHAR16                        *CapsuleName;\r
+  UINTN                         CapsuleNum;\r
+  UINTN                         Index;\r
+  EFI_GUID                      ImageTypeId;\r
+  UINTN                         ImageIndex;\r
 \r
   Status = GetArg();\r
   if (EFI_ERROR(Status)) {\r
@@ -735,9 +828,13 @@ UefiMain (
   }\r
   if (Argc < 2) {\r
     PrintUsage();\r
-    return EFI_INVALID_PARAMETER;\r
+    return EFI_UNSUPPORTED;\r
   }\r
   if (StrCmp(Argv[1], L"-D") == 0) {\r
+    if (Argc != 3) {\r
+      Print(L"CapsuleApp: Incorrect parameter count.\n");\r
+      return EFI_UNSUPPORTED;\r
+    }\r
     Status = DumpCapsule(Argv[2]);\r
     return Status;\r
   }\r
@@ -762,9 +859,15 @@ UefiMain (
       DumpFmpData();\r
     }\r
     if (Argc >= 3) {\r
-      if (StrCmp(Argv[2], L"GET") == 0) {\r
-        EFI_GUID  ImageTypeId;\r
-        UINTN     ImageIndex;\r
+      if (StrCmp(Argv[2], L"GET") != 0) {\r
+        Print(L"CapsuleApp: Unrecognized option(%s).\n", Argv[2]);\r
+        return EFI_UNSUPPORTED;\r
+      } else {\r
+        if (Argc != 7) {\r
+          Print(L"CapsuleApp: Incorrect parameter count.\n");\r
+          return EFI_UNSUPPORTED;\r
+        }\r
+\r
         //\r
         // FMP->GetImage()\r
         //\r
@@ -774,17 +877,26 @@ UefiMain (
           return EFI_INVALID_PARAMETER;\r
         }\r
         ImageIndex = StrDecimalToUintn(Argv[4]);\r
-        if (StrCmp(Argv[5], L"-O") == 0) {\r
-          DumpFmpImage(&ImageTypeId, ImageIndex, Argv[6]);\r
+        if (StrCmp(Argv[5], L"-O") != 0) {\r
+          Print(L"CapsuleApp: NO output file name.\n");\r
+          return EFI_UNSUPPORTED;\r
         }\r
+        DumpFmpImage(&ImageTypeId, ImageIndex, Argv[6]);\r
       }\r
     }\r
     return EFI_SUCCESS;\r
   }\r
+\r
   if (StrCmp(Argv[1], L"-E") == 0) {\r
     DumpEsrtData();\r
     return EFI_SUCCESS;\r
   }\r
+\r
+  if (Argv[1][0] == L'-') {\r
+    Print(L"CapsuleApp: Unrecognized option(%s).\n", Argv[1]);\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   CapsuleFirstIndex = 1;\r
   NoReset = FALSE;\r
   if ((Argc > 1) && (StrCmp(Argv[Argc - 1], L"-NR") == 0)) {\r
@@ -815,6 +927,10 @@ UefiMain (
       Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);\r
       goto Done;\r
     }\r
+    if (!IsValidCapsuleHeader (CapsuleBuffer[Index], FileSize[Index])) {\r
+      Print(L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
   }\r
 \r
   //\r