MdeModulePkg CapsuleApp: Add directory support
authorStar Zeng <star.zeng@intel.com>
Tue, 11 Apr 2017 01:55:51 +0000 (09:55 +0800)
committerStar Zeng <star.zeng@intel.com>
Fri, 14 Apr 2017 05:47:39 +0000 (13:47 +0800)
Current CapsuleApp only supports input/output file from rootdirectory.
If the CapsuleApp and related file are put into subdirectory,
below message will be shown when running the CapsuleApp in shell.

"CapsuleApp: capsule image (Capsule image file name) is not found."

This patch is to add directory support for CapsuleApp
by using shell protocol.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
MdeModulePkg/Application/CapsuleApp/AppSupport.c
MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf

index e39ab2037865215d8b226ce78357142fcd4e9cdc..fc27343736a4d2b261c0d8a8e52485af58dfe89c 100644 (file)
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\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 <Protocol/ShellParameters.h>\r
+#include <Protocol/Shell.h>\r
 #include <Guid/FileInfo.h>\r
-#include <Guid/Gpt.h>\r
-\r
-#define IS_HYPHEN(a)               ((a) == L'-')\r
-#define IS_NULL(a)                 ((a) == L'\0')\r
-\r
-#define MAX_ARG_NUM     11\r
 \r
 UINTN  Argc;\r
 CHAR16 **Argv;\r
+EFI_SHELL_PROTOCOL      *mShellProtocol = NULL;\r
 \r
 /**\r
 \r
@@ -64,297 +56,109 @@ GetArg (
 }\r
 \r
 /**\r
-  Return File System Volume containing this shell application.\r
+  Get shell protocol.\r
 \r
-  @return File System Volume containing this shell application.\r
+  @return Pointer to shell protocol.\r
 **/\r
-EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *\r
-GetMyVol (\r
+EFI_SHELL_PROTOCOL *\r
+GetShellProtocol (\r
   VOID\r
   )\r
 {\r
-  EFI_STATUS                        Status;\r
-  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;\r
-\r
-  Status = gBS->HandleProtocol (\r
-                  gImageHandle,\r
-                  &gEfiLoadedImageProtocolGuid,\r
-                  (VOID **)&LoadedImage\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
+  EFI_STATUS            Status;\r
 \r
-  Status = gBS->HandleProtocol (\r
-                  LoadedImage->DeviceHandle,\r
-                  &gEfiSimpleFileSystemProtocolGuid,\r
-                  (VOID **)&Vol\r
-                  );\r
-  if (!EFI_ERROR (Status)) {\r
-    return Vol;\r
+  if (mShellProtocol == NULL) {\r
+    Status = gBS->LocateProtocol (\r
+                    &gEfiShellProtocolGuid,\r
+                    NULL,\r
+                    (VOID **) &mShellProtocol\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      mShellProtocol = NULL;\r
+    }\r
   }\r
 \r
-  return NULL;\r
+  return mShellProtocol;\r
 }\r
 \r
 /**\r
-  Read a file from this volume.\r
+  Read a file.\r
 \r
-  @param[in]  Vol             File System Volume\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
+  @retval EFI_NOT_FOUND  Shell protocol or file not found\r
+  @retval others         Read file failed\r
 **/\r
 EFI_STATUS\r
-ReadFileFromVol (\r
-  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,\r
-  IN  CHAR16                            *FileName,\r
-  OUT UINTN                             *BufferSize,\r
-  OUT VOID                              **Buffer\r
+ReadFileToBuffer (\r
+  IN  CHAR16                               *FileName,\r
+  OUT UINTN                                *BufferSize,\r
+  OUT VOID                                 **Buffer\r
   )\r
 {\r
   EFI_STATUS                        Status;\r
-  EFI_FILE_HANDLE                   RootDir;\r
-  EFI_FILE_HANDLE                   Handle;\r
-  UINTN                             FileInfoSize;\r
-  EFI_FILE_INFO                     *FileInfo;\r
+  EFI_SHELL_PROTOCOL                *ShellProtocol;\r
+  SHELL_FILE_HANDLE                 Handle;\r
+  UINT64                            FileSize;\r
   UINTN                             TempBufferSize;\r
   VOID                              *TempBuffer;\r
 \r
-  //\r
-  // Open the root directory\r
-  //\r
-  Status = Vol->OpenVolume (Vol, &RootDir);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
+  ShellProtocol = GetShellProtocol();\r
+  if (ShellProtocol == NULL) {\r
+    return EFI_NOT_FOUND;\r
   }\r
 \r
   //\r
-  // Open the file\r
+  // Open file by FileName.\r
   //\r
-  Status = RootDir->Open (\r
-                      RootDir,\r
-                      &Handle,\r
-                      FileName,\r
-                      EFI_FILE_MODE_READ,\r
-                      0\r
-                      );\r
+  Status = ShellProtocol->OpenFileByName (\r
+                            FileName,\r
+                            &Handle,\r
+                            EFI_FILE_MODE_READ\r
+                            );\r
   if (EFI_ERROR (Status)) {\r
-    RootDir->Close (RootDir);\r
     return Status;\r
   }\r
 \r
-  RootDir->Close (RootDir);\r
-\r
   //\r
-  // Get the file information\r
+  // Get the file size.\r
   //\r
-  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;\r
-\r
-  FileInfo = AllocateZeroPool (FileInfoSize);\r
-  if (FileInfo == NULL) {\r
-    Handle->Close (Handle);\r
+  Status = ShellProtocol->GetFileSize (Handle, &FileSize);\r
+  if (EFI_ERROR (Status)) {
+    ShellProtocol->CloseFile (Handle);\r
     return Status;\r
   }\r
 \r
-  Status = Handle->GetInfo (\r
-                     Handle,\r
-                     &gEfiFileInfoGuid,\r
-                     &FileInfoSize,\r
-                     FileInfo\r
-                     );\r
-  if (EFI_ERROR (Status)) {\r
-    Handle->Close (Handle);\r
-    gBS->FreePool (FileInfo);\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Allocate buffer for the file data. The last CHAR16 is for L'\0'\r
-  //\r
-  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);\r
+  TempBufferSize = (UINTN) FileSize;\r
   TempBuffer = AllocateZeroPool (TempBufferSize);\r
   if (TempBuffer == NULL) {\r
-    Handle->Close (Handle);\r
-    gBS->FreePool (FileInfo);\r
-    return Status;\r
+    ShellProtocol->CloseFile (Handle);\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  gBS->FreePool (FileInfo);\r
-\r
   //\r
   // Read the file data to the buffer\r
   //\r
-  Status = Handle->Read (\r
-                     Handle,\r
-                     &TempBufferSize,\r
-                     TempBuffer\r
-                     );\r
+  Status = ShellProtocol->ReadFile (\r
+                            Handle,\r
+                            &TempBufferSize,\r
+                            TempBuffer\r
+                            );\r
   if (EFI_ERROR (Status)) {\r
-    Handle->Close (Handle);\r
-    gBS->FreePool (TempBuffer);\r
+    ShellProtocol->CloseFile (Handle);\r
     return Status;\r
   }\r
 \r
-  Handle->Close (Handle);\r
+  ShellProtocol->CloseFile (Handle);\r
 \r
   *BufferSize = TempBufferSize;\r
   *Buffer     = TempBuffer;\r
   return EFI_SUCCESS;\r
 }\r
 \r
-/**\r
-  Read a file.\r
-  If ScanFs is FLASE, it will use this Vol as default Fs.\r
-  If ScanFs is TRUE, it will scan all FS and check the file.\r
-    If there is only one file match the name, it will be read.\r
-    If there is more than one file match the name, it will return Error.\r
-\r
-  @param[in,out]  ThisVol         File System Volume\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
-  @param[in]      ScanFs          Need Scan all FS\r
-\r
-  @retval EFI_SUCCESS    Read file successfully\r
-  @retval EFI_NOT_FOUND  File not found\r
-  @retval EFI_NO_MAPPING There is duplicated files found\r
-**/\r
-EFI_STATUS\r
-ReadFileToBufferEx (\r
-  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,\r
-  IN  CHAR16                               *FileName,\r
-  OUT UINTN                                *BufferSize,\r
-  OUT VOID                                 **Buffer,\r
-  IN  BOOLEAN                              ScanFs\r
-  )\r
-{\r
-  EFI_STATUS                        Status;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;\r
-  UINTN                             TempBufferSize;\r
-  VOID                              *TempBuffer;\r
-  UINTN                             NoHandles;\r
-  EFI_HANDLE                        *HandleBuffer;\r
-  UINTN                             Index;\r
-\r
-  //\r
-  // Check parameters\r
-  //\r
-  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  //\r
-  // not scan fs\r
-  //\r
-  if (!ScanFs) {\r
-    if (*ThisVol == NULL) {\r
-      *ThisVol = GetMyVol ();\r
-      if (*ThisVol == NULL) {\r
-        return EFI_INVALID_PARAMETER;\r
-      }\r
-    }\r
-    //\r
-    // Read file directly from Vol\r
-    //\r
-    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);\r
-  }\r
-\r
-  //\r
-  // need scan fs\r
-  //\r
-\r
-  //\r
-  // Get all Vol handle\r
-  //\r
-  Status = gBS->LocateHandleBuffer (\r
-                   ByProtocol,\r
-                   &gEfiSimpleFileSystemProtocolGuid,\r
-                   NULL,\r
-                   &NoHandles,\r
-                   &HandleBuffer\r
-                   );\r
-  if (EFI_ERROR (Status) && (NoHandles == 0)) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  //\r
-  // Walk through each Vol\r
-  //\r
-  *ThisVol = NULL;\r
-  *BufferSize = 0;\r
-  *Buffer     = NULL;\r
-  for (Index = 0; Index < NoHandles; Index++) {\r
-    Status = gBS->HandleProtocol (\r
-                    HandleBuffer[Index],\r
-                    &gEfiSimpleFileSystemProtocolGuid,\r
-                    (VOID **)&Vol\r
-                    );\r
-    if (EFI_ERROR(Status)) {\r
-      continue;\r
-    }\r
-\r
-    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);\r
-    if (!EFI_ERROR (Status)) {\r
-      //\r
-      // Read file OK, check duplication\r
-      //\r
-      if (*ThisVol != NULL) {\r
-        //\r
-        // Find the duplicated file\r
-        //\r
-        gBS->FreePool (TempBuffer);\r
-        gBS->FreePool (*Buffer);\r
-        Print (L"Duplicated FileName found!\n");\r
-        return EFI_NO_MAPPING;\r
-      } else {\r
-        //\r
-        // Record value\r
-        //\r
-        *ThisVol = Vol;\r
-        *BufferSize = TempBufferSize;\r
-        *Buffer     = TempBuffer;\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  // Scan Fs done\r
-  //\r
-  if (*ThisVol == NULL) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  //\r
-  // Done\r
-  //\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Read a file.\r
-\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
-**/\r
-EFI_STATUS\r
-ReadFileToBuffer (\r
-  IN  CHAR16                               *FileName,\r
-  OUT UINTN                                *BufferSize,\r
-  OUT VOID                                 **Buffer\r
-  )\r
-{\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;\r
-  Vol = NULL;\r
-  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);\r
-}\r
-\r
 /**\r
   Write a file.\r
 \r
@@ -363,6 +167,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
@@ -372,79 +178,69 @@ WriteFileFromBuffer (
   )\r
 {\r
   EFI_STATUS                        Status;\r
-  EFI_FILE_HANDLE                   RootDir;\r
-  EFI_FILE_HANDLE                   Handle;\r
+  EFI_SHELL_PROTOCOL                *ShellProtocol;\r
+  SHELL_FILE_HANDLE                 Handle;\r
+  EFI_FILE_INFO                     *FileInfo;\r
   UINTN                             TempBufferSize;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;\r
 \r
-  Vol = GetMyVol();\r
-  if (Vol == NULL) {\r
+  ShellProtocol = GetShellProtocol();\r
+  if (ShellProtocol == NULL) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
   //\r
-  // Open the root directory\r
+  // Open file by FileName.\r
   //\r
-  Status = Vol->OpenVolume (Vol, &RootDir);\r
+  Status = ShellProtocol->OpenFileByName (\r
+                            FileName,\r
+                            &Handle,\r
+                            EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE\r
+                            );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
   //\r
-  // Open the file\r
+  // Empty the file contents.\r
   //\r
-  Status = RootDir->Open (\r
-                      RootDir,\r
-                      &Handle,\r
-                      FileName,\r
-                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,\r
-                      0\r
-                      );\r
-  if (EFI_ERROR (Status)) {\r
-    RootDir->Close (RootDir);\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Delete file\r
-  //\r
-  Status = Handle->Delete(Handle);\r
-  if (EFI_ERROR(Status)) {\r
-    return Status;\r
+  FileInfo = ShellProtocol->GetFileInfo (Handle);\r
+  if (FileInfo == NULL) {\r
+    ShellProtocol->CloseFile (Handle);\r
+    return EFI_DEVICE_ERROR;\r
   }\r
 \r
   //\r
-  // Open the file again\r
+  // If the file size is already 0, then it has been empty.\r
   //\r
-  Status = RootDir->Open (\r
-                      RootDir,\r
-                      &Handle,\r
-                      FileName,\r
-                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,\r
-                      0\r
-                      );\r
-  if (EFI_ERROR (Status)) {\r
-    RootDir->Close (RootDir);\r
-    return Status;\r
+  if (FileInfo->FileSize != 0) {\r
+    //\r
+    // Set the file size to 0.\r
+    //\r
+    FileInfo->FileSize = 0;\r
+    Status = ShellProtocol->SetFileInfo (Handle, FileInfo);\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (FileInfo);\r
+      ShellProtocol->CloseFile (Handle);\r
+      return Status;\r
+    }\r
   }\r
-\r
-  RootDir->Close (RootDir);\r
+  FreePool (FileInfo);\r
 \r
   //\r
   // Write the file data from the buffer\r
   //\r
   TempBufferSize = BufferSize;\r
-  Status = Handle->Write (\r
-                     Handle,\r
-                     &TempBufferSize,\r
-                     Buffer\r
-                     );\r
+  Status = ShellProtocol->WriteFile (\r
+                            Handle,\r
+                            &TempBufferSize,\r
+                            Buffer\r
+                            );\r
   if (EFI_ERROR (Status)) {\r
-    Handle->Close (Handle);\r
+    ShellProtocol->CloseFile (Handle);\r
     return Status;\r
   }\r
 \r
-  Handle->Close (Handle);\r
+  ShellProtocol->CloseFile (Handle);\r
 \r
   return EFI_SUCCESS;\r
 }\r
index 6febe846b1406f1f9098114061b3ccd95877dd09..63c83b1474a585ce5963f94af508ba00bf2ea2ff 100644 (file)
 #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 <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 +113,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 +131,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
index c255096aaeb7c2920c7ebc52c387c83b26e8f588..b06c4ea1bc8813af9c5122f4ce506bcd330b2db0 100644 (file)
@@ -4,7 +4,7 @@
 # This application can trigger capsule update process. It can also\r
 # generate capsule image, or dump capsule variable information.\r
 #\r
-#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2016 - 2017, 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
@@ -40,8 +40,6 @@
   MdeModulePkg/MdeModulePkg.dec\r
 \r
 [Guids]\r
-  gEfiFileInfoGuid                       ## CONSUMES   ## GUID\r
-  gEfiPartTypeSystemPartGuid             ## CONSUMES   ## GUID\r
   gEfiGlobalVariableGuid                 ## CONSUMES   ## GUID\r
   gEfiCapsuleReportGuid                  ## CONSUMES   ## GUID\r
   gEfiFmpCapsuleGuid                     ## CONSUMES   ## GUID\r
   gEfiSystemResourceTableGuid            ## CONSUMES   ## GUID\r
 \r
 [Protocols]\r
-  gEfiLoadedImageProtocolGuid            ## CONSUMES\r
-  gEfiSimpleFileSystemProtocolGuid       ## CONSUMES\r
   gEfiGraphicsOutputProtocolGuid         ## CONSUMES\r
   gEfiFirmwareManagementProtocolGuid     ## CONSUMES\r
   gEfiShellParametersProtocolGuid        ## CONSUMES\r
+  gEfiShellProtocolGuid                  ## CONSUMES\r
 \r
 [LibraryClasses]\r
   BaseLib\r