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....@intel.com>
Cc: Feng Tian <feng.t...@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.z...@intel.com>
---
 MdeModulePkg/Application/CapsuleApp/AppSupport.c   | 380 +++++----------------
 MdeModulePkg/Application/CapsuleApp/CapsuleApp.c   |   9 +-
 MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf |   7 +-
 3 files changed, 94 insertions(+), 302 deletions(-)

diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c 
b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
index e39ab2037865..fc27343736a4 100644
--- a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
+++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
@@ -18,22 +18,14 @@
 #include <Library/BaseMemoryLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/UefiLib.h>
-#include <Library/PrintLib.h>
-#include <Protocol/LoadedImage.h>
 #include <Protocol/SimpleFileSystem.h>
 #include <Protocol/ShellParameters.h>
+#include <Protocol/Shell.h>
 #include <Guid/FileInfo.h>
-#include <Guid/Gpt.h>
-
-#define IS_HYPHEN(a)               ((a) == L'-')
-#define IS_NULL(a)                 ((a) == L'\0')
-
-#define MAX_ARG_NUM     11
 
 UINTN  Argc;
 CHAR16 **Argv;
+EFI_SHELL_PROTOCOL      *mShellProtocol = NULL;
 
 /**
 
@@ -64,141 +56,103 @@ GetArg (
 }
 
 /**
-  Return File System Volume containing this shell application.
+  Get shell protocol.
 
-  @return File System Volume containing this shell application.
+  @return Pointer to shell protocol.
 **/
-EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
-GetMyVol (
+EFI_SHELL_PROTOCOL *
+GetShellProtocol (
   VOID
   )
 {
-  EFI_STATUS                        Status;
-  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
-
-  Status = gBS->HandleProtocol (
-                  gImageHandle,
-                  &gEfiLoadedImageProtocolGuid,
-                  (VOID **)&LoadedImage
-                  );
-  ASSERT_EFI_ERROR (Status);
+  EFI_STATUS            Status;
 
-  Status = gBS->HandleProtocol (
-                  LoadedImage->DeviceHandle,
-                  &gEfiSimpleFileSystemProtocolGuid,
-                  (VOID **)&Vol
-                  );
-  if (!EFI_ERROR (Status)) {
-    return Vol;
+  if (mShellProtocol == NULL) {
+    Status = gBS->LocateProtocol (
+                    &gEfiShellProtocolGuid,
+                    NULL,
+                    (VOID **) &mShellProtocol
+                    );
+    if (EFI_ERROR (Status)) {
+      mShellProtocol = NULL;
+    }
   }
 
-  return NULL;
+  return mShellProtocol;
 }
 
 /**
-  Read a file from this volume.
+  Read a file.
 
-  @param[in]  Vol             File System Volume
   @param[in]  FileName        The file to be read.
   @param[out] BufferSize      The file buffer size
   @param[out] Buffer          The file buffer
 
   @retval EFI_SUCCESS    Read file successfully
-  @retval EFI_NOT_FOUND  File not found
+  @retval EFI_NOT_FOUND  Shell protocol or file not found
+  @retval others         Read file failed
 **/
 EFI_STATUS
-ReadFileFromVol (
-  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
-  IN  CHAR16                            *FileName,
-  OUT UINTN                             *BufferSize,
-  OUT VOID                              **Buffer
+ReadFileToBuffer (
+  IN  CHAR16                               *FileName,
+  OUT UINTN                                *BufferSize,
+  OUT VOID                                 **Buffer
   )
 {
   EFI_STATUS                        Status;
-  EFI_FILE_HANDLE                   RootDir;
-  EFI_FILE_HANDLE                   Handle;
-  UINTN                             FileInfoSize;
-  EFI_FILE_INFO                     *FileInfo;
+  EFI_SHELL_PROTOCOL                *ShellProtocol;
+  SHELL_FILE_HANDLE                 Handle;
+  UINT64                            FileSize;
   UINTN                             TempBufferSize;
   VOID                              *TempBuffer;
 
-  //
-  // Open the root directory
-  //
-  Status = Vol->OpenVolume (Vol, &RootDir);
-  if (EFI_ERROR (Status)) {
-    return Status;
+  ShellProtocol = GetShellProtocol();
+  if (ShellProtocol == NULL) {
+    return EFI_NOT_FOUND;
   }
 
   //
-  // Open the file
+  // Open file by FileName.
   //
-  Status = RootDir->Open (
-                      RootDir,
-                      &Handle,
-                      FileName,
-                      EFI_FILE_MODE_READ,
-                      0
-                      );
+  Status = ShellProtocol->OpenFileByName (
+                            FileName,
+                            &Handle,
+                            EFI_FILE_MODE_READ
+                            );
   if (EFI_ERROR (Status)) {
-    RootDir->Close (RootDir);
     return Status;
   }
 
-  RootDir->Close (RootDir);
-
   //
-  // Get the file information
+  // Get the file size.
   //
-  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
-
-  FileInfo = AllocateZeroPool (FileInfoSize);
-  if (FileInfo == NULL) {
-    Handle->Close (Handle);
+  Status = ShellProtocol->GetFileSize (Handle, &FileSize);
+  if (EFI_ERROR (Status)) {
+    ShellProtocol->CloseFile (Handle);
     return Status;
   }
 
-  Status = Handle->GetInfo (
-                     Handle,
-                     &gEfiFileInfoGuid,
-                     &FileInfoSize,
-                     FileInfo
-                     );
-  if (EFI_ERROR (Status)) {
-    Handle->Close (Handle);
-    gBS->FreePool (FileInfo);
-    return Status;
-  }
-
-  //
-  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
-  //
-  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
+  TempBufferSize = (UINTN) FileSize;
   TempBuffer = AllocateZeroPool (TempBufferSize);
   if (TempBuffer == NULL) {
-    Handle->Close (Handle);
-    gBS->FreePool (FileInfo);
-    return Status;
+    ShellProtocol->CloseFile (Handle);
+    return EFI_OUT_OF_RESOURCES;
   }
 
-  gBS->FreePool (FileInfo);
-
   //
   // Read the file data to the buffer
   //
-  Status = Handle->Read (
-                     Handle,
-                     &TempBufferSize,
-                     TempBuffer
-                     );
+  Status = ShellProtocol->ReadFile (
+                            Handle,
+                            &TempBufferSize,
+                            TempBuffer
+                            );
   if (EFI_ERROR (Status)) {
-    Handle->Close (Handle);
-    gBS->FreePool (TempBuffer);
+    ShellProtocol->CloseFile (Handle);
     return Status;
   }
 
-  Handle->Close (Handle);
+  ShellProtocol->CloseFile (Handle);
 
   *BufferSize = TempBufferSize;
   *Buffer     = TempBuffer;
@@ -206,156 +160,6 @@ ReadFileFromVol (
 }
 
 /**
-  Read a file.
-  If ScanFs is FLASE, it will use this Vol as default Fs.
-  If ScanFs is TRUE, it will scan all FS and check the file.
-    If there is only one file match the name, it will be read.
-    If there is more than one file match the name, it will return Error.
-
-  @param[in,out]  ThisVol         File System Volume
-  @param[in]      FileName        The file to be read.
-  @param[out]     BufferSize      The file buffer size
-  @param[out]     Buffer          The file buffer
-  @param[in]      ScanFs          Need Scan all FS
-
-  @retval EFI_SUCCESS    Read file successfully
-  @retval EFI_NOT_FOUND  File not found
-  @retval EFI_NO_MAPPING There is duplicated files found
-**/
-EFI_STATUS
-ReadFileToBufferEx (
-  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
-  IN  CHAR16                               *FileName,
-  OUT UINTN                                *BufferSize,
-  OUT VOID                                 **Buffer,
-  IN  BOOLEAN                              ScanFs
-  )
-{
-  EFI_STATUS                        Status;
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
-  UINTN                             TempBufferSize;
-  VOID                              *TempBuffer;
-  UINTN                             NoHandles;
-  EFI_HANDLE                        *HandleBuffer;
-  UINTN                             Index;
-
-  //
-  // Check parameters
-  //
-  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // not scan fs
-  //
-  if (!ScanFs) {
-    if (*ThisVol == NULL) {
-      *ThisVol = GetMyVol ();
-      if (*ThisVol == NULL) {
-        return EFI_INVALID_PARAMETER;
-      }
-    }
-    //
-    // Read file directly from Vol
-    //
-    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
-  }
-
-  //
-  // need scan fs
-  //
-
-  //
-  // Get all Vol handle
-  //
-  Status = gBS->LocateHandleBuffer (
-                   ByProtocol,
-                   &gEfiSimpleFileSystemProtocolGuid,
-                   NULL,
-                   &NoHandles,
-                   &HandleBuffer
-                   );
-  if (EFI_ERROR (Status) && (NoHandles == 0)) {
-    return EFI_NOT_FOUND;
-  }
-
-  //
-  // Walk through each Vol
-  //
-  *ThisVol = NULL;
-  *BufferSize = 0;
-  *Buffer     = NULL;
-  for (Index = 0; Index < NoHandles; Index++) {
-    Status = gBS->HandleProtocol (
-                    HandleBuffer[Index],
-                    &gEfiSimpleFileSystemProtocolGuid,
-                    (VOID **)&Vol
-                    );
-    if (EFI_ERROR(Status)) {
-      continue;
-    }
-
-    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
-    if (!EFI_ERROR (Status)) {
-      //
-      // Read file OK, check duplication
-      //
-      if (*ThisVol != NULL) {
-        //
-        // Find the duplicated file
-        //
-        gBS->FreePool (TempBuffer);
-        gBS->FreePool (*Buffer);
-        Print (L"Duplicated FileName found!\n");
-        return EFI_NO_MAPPING;
-      } else {
-        //
-        // Record value
-        //
-        *ThisVol = Vol;
-        *BufferSize = TempBufferSize;
-        *Buffer     = TempBuffer;
-      }
-    }
-  }
-
-  //
-  // Scan Fs done
-  //
-  if (*ThisVol == NULL) {
-    return EFI_NOT_FOUND;
-  }
-
-  //
-  // Done
-  //
-  return EFI_SUCCESS;
-}
-
-/**
-  Read a file.
-
-  @param[in]  FileName        The file to be read.
-  @param[out] BufferSize      The file buffer size
-  @param[out] Buffer          The file buffer
-
-  @retval EFI_SUCCESS    Read file successfully
-  @retval EFI_NOT_FOUND  File not found
-**/
-EFI_STATUS
-ReadFileToBuffer (
-  IN  CHAR16                               *FileName,
-  OUT UINTN                                *BufferSize,
-  OUT VOID                                 **Buffer
-  )
-{
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
-  Vol = NULL;
-  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
-}
-
-/**
   Write a file.
 
   @param[in] FileName        The file to be written.
@@ -363,6 +167,8 @@ ReadFileToBuffer (
   @param[in] Buffer          The file buffer
 
   @retval EFI_SUCCESS    Write file successfully
+  @retval EFI_NOT_FOUND  Shell protocol not found
+  @retval others         Write file failed
 **/
 EFI_STATUS
 WriteFileFromBuffer (
@@ -372,79 +178,69 @@ WriteFileFromBuffer (
   )
 {
   EFI_STATUS                        Status;
-  EFI_FILE_HANDLE                   RootDir;
-  EFI_FILE_HANDLE                   Handle;
+  EFI_SHELL_PROTOCOL                *ShellProtocol;
+  SHELL_FILE_HANDLE                 Handle;
+  EFI_FILE_INFO                     *FileInfo;
   UINTN                             TempBufferSize;
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
 
-  Vol = GetMyVol();
-  if (Vol == NULL) {
+  ShellProtocol = GetShellProtocol();
+  if (ShellProtocol == NULL) {
     return EFI_NOT_FOUND;
   }
 
   //
-  // Open the root directory
+  // Open file by FileName.
   //
-  Status = Vol->OpenVolume (Vol, &RootDir);
+  Status = ShellProtocol->OpenFileByName (
+                            FileName,
+                            &Handle,
+                            EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | 
EFI_FILE_MODE_CREATE
+                            );
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
   //
-  // Open the file
+  // Empty the file contents.
   //
-  Status = RootDir->Open (
-                      RootDir,
-                      &Handle,
-                      FileName,
-                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| 
EFI_FILE_MODE_CREATE,
-                      0
-                      );
-  if (EFI_ERROR (Status)) {
-    RootDir->Close (RootDir);
-    return Status;
-  }
-
-  //
-  // Delete file
-  //
-  Status = Handle->Delete(Handle);
-  if (EFI_ERROR(Status)) {
-    return Status;
+  FileInfo = ShellProtocol->GetFileInfo (Handle);
+  if (FileInfo == NULL) {
+    ShellProtocol->CloseFile (Handle);
+    return EFI_DEVICE_ERROR;
   }
 
   //
-  // Open the file again
+  // If the file size is already 0, then it has been empty.
   //
-  Status = RootDir->Open (
-                      RootDir,
-                      &Handle,
-                      FileName,
-                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| 
EFI_FILE_MODE_CREATE,
-                      0
-                      );
-  if (EFI_ERROR (Status)) {
-    RootDir->Close (RootDir);
-    return Status;
+  if (FileInfo->FileSize != 0) {
+    //
+    // Set the file size to 0.
+    //
+    FileInfo->FileSize = 0;
+    Status = ShellProtocol->SetFileInfo (Handle, FileInfo);
+    if (EFI_ERROR (Status)) {
+      FreePool (FileInfo);
+      ShellProtocol->CloseFile (Handle);
+      return Status;
+    }
   }
-
-  RootDir->Close (RootDir);
+  FreePool (FileInfo);
 
   //
   // Write the file data from the buffer
   //
   TempBufferSize = BufferSize;
-  Status = Handle->Write (
-                     Handle,
-                     &TempBufferSize,
-                     Buffer
-                     );
+  Status = ShellProtocol->WriteFile (
+                            Handle,
+                            &TempBufferSize,
+                            Buffer
+                            );
   if (EFI_ERROR (Status)) {
-    Handle->Close (Handle);
+    ShellProtocol->CloseFile (Handle);
     return Status;
   }
 
-  Handle->Close (Handle);
+  ShellProtocol->CloseFile (Handle);
 
   return EFI_SUCCESS;
 }
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c 
b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
index 6febe846b140..63c83b1474a5 100644
--- a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
@@ -21,11 +21,7 @@
 #include <Library/UefiRuntimeServicesTableLib.h>
 #include <Library/UefiLib.h>
 #include <Library/PrintLib.h>
-#include <Protocol/LoadedImage.h>
-#include <Protocol/SimpleFileSystem.h>
 #include <Protocol/GraphicsOutput.h>
-#include <Guid/FileInfo.h>
-#include <Guid/Gpt.h>
 #include <Guid/GlobalVariable.h>
 #include <Guid/CapsuleReport.h>
 #include <Guid/SystemResourceTable.h>
@@ -117,7 +113,8 @@ DumpEsrtData (
   @param[out] Buffer          The file buffer
 
   @retval EFI_SUCCESS    Read file successfully
-  @retval EFI_NOT_FOUND  File not found
+  @retval EFI_NOT_FOUND  Shell protocol or file not found
+  @retval others         Read file failed
 **/
 EFI_STATUS
 ReadFileToBuffer (
@@ -134,6 +131,8 @@ ReadFileToBuffer (
   @param[in] Buffer          The file buffer
 
   @retval EFI_SUCCESS    Write file successfully
+  @retval EFI_NOT_FOUND  Shell protocol not found
+  @retval others         Write file failed
 **/
 EFI_STATUS
 WriteFileFromBuffer (
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf 
b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
index c255096aaeb7..b06c4ea1bc88 100644
--- a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
@@ -4,7 +4,7 @@
 # This application can trigger capsule update process. It can also
 # generate capsule image, or dump capsule variable information.
 #
-#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD 
License
 #  which accompanies this distribution.  The full text of the license may be 
found at
@@ -40,8 +40,6 @@ [Packages]
   MdeModulePkg/MdeModulePkg.dec
 
 [Guids]
-  gEfiFileInfoGuid                       ## CONSUMES   ## GUID
-  gEfiPartTypeSystemPartGuid             ## CONSUMES   ## GUID
   gEfiGlobalVariableGuid                 ## CONSUMES   ## GUID
   gEfiCapsuleReportGuid                  ## CONSUMES   ## GUID
   gEfiFmpCapsuleGuid                     ## CONSUMES   ## GUID
@@ -51,11 +49,10 @@ [Guids]
   gEfiSystemResourceTableGuid            ## CONSUMES   ## GUID
 
 [Protocols]
-  gEfiLoadedImageProtocolGuid            ## CONSUMES
-  gEfiSimpleFileSystemProtocolGuid       ## CONSUMES
   gEfiGraphicsOutputProtocolGuid         ## CONSUMES
   gEfiFirmwareManagementProtocolGuid     ## CONSUMES
   gEfiShellParametersProtocolGuid        ## CONSUMES
+  gEfiShellProtocolGuid                  ## CONSUMES
 
 [LibraryClasses]
   BaseLib
-- 
2.7.0.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to