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>
		
			
				
	
	
		
			248 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			248 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  A shell application that triggers capsule update process.
 | 
						|
 | 
						|
  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
 | 
						|
  http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <Uefi.h>
 | 
						|
#include <Library/BaseLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Library/UefiBootServicesTableLib.h>
 | 
						|
#include <Protocol/SimpleFileSystem.h>
 | 
						|
#include <Protocol/ShellParameters.h>
 | 
						|
#include <Protocol/Shell.h>
 | 
						|
#include <Guid/FileInfo.h>
 | 
						|
 | 
						|
UINTN  Argc;
 | 
						|
CHAR16 **Argv;
 | 
						|
EFI_SHELL_PROTOCOL      *mShellProtocol = NULL;
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  This function parse application ARG.
 | 
						|
 | 
						|
  @return Status
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetArg (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters;
 | 
						|
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  gImageHandle,
 | 
						|
                  &gEfiShellParametersProtocolGuid,
 | 
						|
                  (VOID**)&ShellParameters
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Argc = ShellParameters->Argc;
 | 
						|
  Argv = ShellParameters->Argv;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get shell protocol.
 | 
						|
 | 
						|
  @return Pointer to shell protocol.
 | 
						|
**/
 | 
						|
EFI_SHELL_PROTOCOL *
 | 
						|
GetShellProtocol (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
 | 
						|
  if (mShellProtocol == NULL) {
 | 
						|
    Status = gBS->LocateProtocol (
 | 
						|
                    &gEfiShellProtocolGuid,
 | 
						|
                    NULL,
 | 
						|
                    (VOID **) &mShellProtocol
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      mShellProtocol = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return mShellProtocol;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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  Shell protocol or file not found
 | 
						|
  @retval others         Read file failed
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ReadFileToBuffer (
 | 
						|
  IN  CHAR16                               *FileName,
 | 
						|
  OUT UINTN                                *BufferSize,
 | 
						|
  OUT VOID                                 **Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_SHELL_PROTOCOL                *ShellProtocol;
 | 
						|
  SHELL_FILE_HANDLE                 Handle;
 | 
						|
  UINT64                            FileSize;
 | 
						|
  UINTN                             TempBufferSize;
 | 
						|
  VOID                              *TempBuffer;
 | 
						|
 | 
						|
  ShellProtocol = GetShellProtocol();
 | 
						|
  if (ShellProtocol == NULL) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Open file by FileName.
 | 
						|
  //
 | 
						|
  Status = ShellProtocol->OpenFileByName (
 | 
						|
                            FileName,
 | 
						|
                            &Handle,
 | 
						|
                            EFI_FILE_MODE_READ
 | 
						|
                            );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the file size.
 | 
						|
  //
 | 
						|
  Status = ShellProtocol->GetFileSize (Handle, &FileSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ShellProtocol->CloseFile (Handle);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  TempBufferSize = (UINTN) FileSize;
 | 
						|
  TempBuffer = AllocateZeroPool (TempBufferSize);
 | 
						|
  if (TempBuffer == NULL) {
 | 
						|
    ShellProtocol->CloseFile (Handle);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Read the file data to the buffer
 | 
						|
  //
 | 
						|
  Status = ShellProtocol->ReadFile (
 | 
						|
                            Handle,
 | 
						|
                            &TempBufferSize,
 | 
						|
                            TempBuffer
 | 
						|
                            );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ShellProtocol->CloseFile (Handle);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  ShellProtocol->CloseFile (Handle);
 | 
						|
 | 
						|
  *BufferSize = TempBufferSize;
 | 
						|
  *Buffer     = TempBuffer;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Write a file.
 | 
						|
 | 
						|
  @param[in] FileName        The file to be written.
 | 
						|
  @param[in] BufferSize      The file buffer size
 | 
						|
  @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 (
 | 
						|
  IN  CHAR16                               *FileName,
 | 
						|
  IN  UINTN                                BufferSize,
 | 
						|
  IN  VOID                                 *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_SHELL_PROTOCOL                *ShellProtocol;
 | 
						|
  SHELL_FILE_HANDLE                 Handle;
 | 
						|
  EFI_FILE_INFO                     *FileInfo;
 | 
						|
  UINTN                             TempBufferSize;
 | 
						|
 | 
						|
  ShellProtocol = GetShellProtocol();
 | 
						|
  if (ShellProtocol == NULL) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Open file by FileName.
 | 
						|
  //
 | 
						|
  Status = ShellProtocol->OpenFileByName (
 | 
						|
                            FileName,
 | 
						|
                            &Handle,
 | 
						|
                            EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE
 | 
						|
                            );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Empty the file contents.
 | 
						|
  //
 | 
						|
  FileInfo = ShellProtocol->GetFileInfo (Handle);
 | 
						|
  if (FileInfo == NULL) {
 | 
						|
    ShellProtocol->CloseFile (Handle);
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If the file size is already 0, then it has been empty.
 | 
						|
  //
 | 
						|
  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;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  FreePool (FileInfo);
 | 
						|
 | 
						|
  //
 | 
						|
  // Write the file data from the buffer
 | 
						|
  //
 | 
						|
  TempBufferSize = BufferSize;
 | 
						|
  Status = ShellProtocol->WriteFile (
 | 
						|
                            Handle,
 | 
						|
                            &TempBufferSize,
 | 
						|
                            Buffer
 | 
						|
                            );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ShellProtocol->CloseFile (Handle);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  ShellProtocol->CloseFile (Handle);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 |