Use explicit CopyMem to replace compiler builtin to do the structure values assignment. This change is needed to pass CLANG38 build. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Steven Shi <steven.shi@intel.com> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com>
		
			
				
	
	
		
			1052 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1052 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/** @file
 | 
						|
  The implementation for the 'tftp' Shell command.
 | 
						|
 | 
						|
  Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
 | 
						|
  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved. <BR>
 | 
						|
  (C) Copyright 2015 Hewlett Packard Enterprise Development LP<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 "UefiShellTftpCommandLib.h"
 | 
						|
 | 
						|
#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32
 | 
						|
 | 
						|
/*
 | 
						|
   Constant strings and definitions related to the message indicating the amount of
 | 
						|
   progress in the dowloading of a TFTP file.
 | 
						|
*/
 | 
						|
 | 
						|
// Frame for the progression slider
 | 
						|
STATIC CONST CHAR16 mTftpProgressFrame[] = L"[                                        ]";
 | 
						|
 | 
						|
// Number of steps in the progression slider
 | 
						|
#define TFTP_PROGRESS_SLIDER_STEPS  ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 3)
 | 
						|
 | 
						|
// Size in number of characters plus one (final zero) of the message to
 | 
						|
// indicate the progress of a TFTP download. The format is "[(progress slider:
 | 
						|
// 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". There
 | 
						|
// are thus the number of characters in mTftpProgressFrame[] plus 11 characters
 | 
						|
// (2 // spaces, "Kb" and seven characters for the number of KBytes).
 | 
						|
#define TFTP_PROGRESS_MESSAGE_SIZE  ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) + 12)
 | 
						|
 | 
						|
// String to delete the TFTP progress message to be able to update it :
 | 
						|
// (TFTP_PROGRESS_MESSAGE_SIZE-1) '\b'
 | 
						|
STATIC CONST CHAR16 mTftpProgressDelete[] = L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
 | 
						|
 | 
						|
/**
 | 
						|
  Check and convert the UINT16 option values of the 'tftp' command
 | 
						|
 | 
						|
  @param[in]  ValueStr  Value as an Unicode encoded string
 | 
						|
  @param[out] Value     UINT16 value
 | 
						|
 | 
						|
  @return     TRUE      The value was returned.
 | 
						|
  @return     FALSE     A parsing error occured.
 | 
						|
**/
 | 
						|
STATIC 
 | 
						|
BOOLEAN 
 | 
						|
StringToUint16 (
 | 
						|
  IN   CONST CHAR16  *ValueStr,
 | 
						|
  OUT  UINT16        *Value
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Get the name of the NIC.
 | 
						|
 | 
						|
  @param[in]   ControllerHandle  The network physical device handle.
 | 
						|
  @param[in]   NicNumber         The network physical device number.
 | 
						|
  @param[out]  NicName           Address where to store the NIC name.
 | 
						|
                                 The memory area has to be at least
 | 
						|
                                 IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 
 | 
						|
                                 double byte wide.
 | 
						|
 | 
						|
  @return  EFI_SUCCESS  The name of the NIC was returned.
 | 
						|
  @return  Others       The creation of the child for the Managed
 | 
						|
                        Network Service failed or the opening of
 | 
						|
                        the Managed Network Protocol failed or
 | 
						|
                        the operational parameters for the
 | 
						|
                        Managed Network Protocol could not be
 | 
						|
                        read.
 | 
						|
**/
 | 
						|
STATIC 
 | 
						|
EFI_STATUS 
 | 
						|
GetNicName (
 | 
						|
  IN   EFI_HANDLE  ControllerHandle,
 | 
						|
  IN   UINTN       NicNumber,
 | 
						|
  OUT  CHAR16      *NicName
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Create a child for the service identified by its service binding protocol GUID
 | 
						|
  and get from the child the interface of the protocol identified by its GUID.
 | 
						|
 | 
						|
  @param[in]   ControllerHandle            Controller handle.
 | 
						|
  @param[in]   ServiceBindingProtocolGuid  Service binding protocol GUID of the
 | 
						|
                                           service to be created.
 | 
						|
  @param[in]   ProtocolGuid                GUID of the protocol to be open.
 | 
						|
  @param[out]  ChildHandle                 Address where the handler of the
 | 
						|
                                           created child is returned. NULL is
 | 
						|
                                           returned in case of error.
 | 
						|
  @param[out]  Interface                   Address where a pointer to the
 | 
						|
                                           protocol interface is returned in
 | 
						|
                                           case of success.
 | 
						|
 | 
						|
  @return  EFI_SUCCESS  The child was created and the protocol opened.
 | 
						|
  @return  Others       Either the creation of the child or the opening
 | 
						|
                        of the protocol failed.
 | 
						|
**/
 | 
						|
STATIC 
 | 
						|
EFI_STATUS 
 | 
						|
CreateServiceChildAndOpenProtocol (
 | 
						|
  IN   EFI_HANDLE  ControllerHandle,
 | 
						|
  IN   EFI_GUID    *ServiceBindingProtocolGuid,
 | 
						|
  IN   EFI_GUID    *ProtocolGuid,
 | 
						|
  OUT  EFI_HANDLE  *ChildHandle,
 | 
						|
  OUT  VOID        **Interface
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Close the protocol identified by its GUID on the child handle of the service
 | 
						|
  identified by its service binding protocol GUID, then destroy the child
 | 
						|
  handle.
 | 
						|
 | 
						|
  @param[in]  ControllerHandle            Controller handle.
 | 
						|
  @param[in]  ServiceBindingProtocolGuid  Service binding protocol GUID of the
 | 
						|
                                          service to be destroyed.
 | 
						|
  @param[in]  ProtocolGuid                GUID of the protocol to be closed.
 | 
						|
  @param[in]  ChildHandle                 Handle of the child to be destroyed.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC 
 | 
						|
VOID 
 | 
						|
CloseProtocolAndDestroyServiceChild (
 | 
						|
  IN  EFI_HANDLE  ControllerHandle,
 | 
						|
  IN  EFI_GUID    *ServiceBindingProtocolGuid,
 | 
						|
  IN  EFI_GUID    *ProtocolGuid,
 | 
						|
  IN  EFI_HANDLE  ChildHandle
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Worker function that gets the size in numbers of bytes of a file from a TFTP
 | 
						|
  server before to download the file.
 | 
						|
 | 
						|
  @param[in]   Mtftp4    MTFTP4 protocol interface
 | 
						|
  @param[in]   FilePath  Path of the file, ASCII encoded
 | 
						|
  @param[out]  FileSize  Address where to store the file size in number of
 | 
						|
                         bytes.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS      The size of the file was returned.
 | 
						|
  @retval  EFI_UNSUPPORTED  The server does not support the "tsize" option.
 | 
						|
  @retval  Others           Error when retrieving the information from the server
 | 
						|
                            (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes)
 | 
						|
                            or error when parsing the response of the server.
 | 
						|
**/
 | 
						|
STATIC 
 | 
						|
EFI_STATUS 
 | 
						|
GetFileSize (
 | 
						|
  IN   EFI_MTFTP4_PROTOCOL  *Mtftp4,
 | 
						|
  IN   CONST CHAR8          *FilePath,
 | 
						|
  OUT  UINTN                *FileSize
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Worker function that download the data of a file from a TFTP server given
 | 
						|
  the path of the file and its size.
 | 
						|
 | 
						|
  @param[in]   Mtftp4         MTFTP4 protocol interface
 | 
						|
  @param[in]   FilePath       Path of the file, Unicode encoded
 | 
						|
  @param[in]   AsciiFilePath  Path of the file, ASCII encoded
 | 
						|
  @param[in]   FileSize       Size of the file in number of bytes
 | 
						|
  @param[in]   BlockSize      Value of the TFTP blksize option
 | 
						|
  @param[out]  Data           Address where to store the address of the buffer
 | 
						|
                              where the data of the file were downloaded in
 | 
						|
                              case of success.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS           The file was downloaded.
 | 
						|
  @retval  EFI_OUT_OF_RESOURCES  A memory allocation failed.
 | 
						|
  @retval  Others                The downloading of the file from the server failed
 | 
						|
                                 (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes).
 | 
						|
 | 
						|
**/
 | 
						|
STATIC 
 | 
						|
EFI_STATUS 
 | 
						|
DownloadFile (
 | 
						|
  IN   EFI_MTFTP4_PROTOCOL  *Mtftp4,
 | 
						|
  IN   CONST CHAR16         *FilePath,
 | 
						|
  IN   CONST CHAR8          *AsciiFilePath,
 | 
						|
  IN   UINTN                FileSize,
 | 
						|
  IN   UINT16               BlockSize,
 | 
						|
  OUT  VOID                 **Data
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Update the progress of a file download
 | 
						|
  This procedure is called each time a new TFTP packet is received.
 | 
						|
 | 
						|
  @param[in]  This       MTFTP4 protocol interface
 | 
						|
  @param[in]  Token      Parameters for the download of the file
 | 
						|
  @param[in]  PacketLen  Length of the packet
 | 
						|
  @param[in]  Packet     Address of the packet
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS  All packets are accepted.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC 
 | 
						|
EFI_STATUS 
 | 
						|
EFIAPI
 | 
						|
CheckPacket (
 | 
						|
  IN EFI_MTFTP4_PROTOCOL  *This,
 | 
						|
  IN EFI_MTFTP4_TOKEN     *Token,
 | 
						|
  IN UINT16               PacketLen,
 | 
						|
  IN EFI_MTFTP4_PACKET    *Packet
 | 
						|
  );
 | 
						|
 | 
						|
EFI_MTFTP4_CONFIG_DATA DefaultMtftp4ConfigData = {
 | 
						|
  TRUE,                             // Use default setting
 | 
						|
  { { 0, 0, 0, 0 } },               // StationIp         - Not relevant as UseDefaultSetting=TRUE
 | 
						|
  { { 0, 0, 0, 0 } },               // SubnetMask        - Not relevant as UseDefaultSetting=TRUE
 | 
						|
  0,                                // LocalPort         - Automatically assigned port number.
 | 
						|
  { { 0, 0, 0, 0 } },               // GatewayIp         - Not relevant as UseDefaultSetting=TRUE
 | 
						|
  { { 0, 0, 0, 0 } },               // ServerIp          - Not known yet
 | 
						|
  69,                               // InitialServerPort - Standard TFTP server port
 | 
						|
  6,                                // TryCount          - Max number of retransmissions.
 | 
						|
  4                                 // TimeoutValue      - Retransmission timeout in seconds.
 | 
						|
};
 | 
						|
 | 
						|
STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
 | 
						|
  {L"-i", TypeValue},
 | 
						|
  {L"-l", TypeValue},
 | 
						|
  {L"-r", TypeValue},
 | 
						|
  {L"-c", TypeValue},
 | 
						|
  {L"-t", TypeValue},
 | 
						|
  {L"-s", TypeValue},
 | 
						|
  {NULL , TypeMax}
 | 
						|
  };
 | 
						|
 | 
						|
///
 | 
						|
/// The default block size (512) of tftp is defined in the RFC1350.
 | 
						|
///
 | 
						|
#define MTFTP_DEFAULT_BLKSIZE      512
 | 
						|
///
 | 
						|
/// The valid range of block size option is defined in the RFC2348.
 | 
						|
///
 | 
						|
#define MTFTP_MIN_BLKSIZE          8
 | 
						|
#define MTFTP_MAX_BLKSIZE          65464
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Function for 'tftp' command.
 | 
						|
 | 
						|
  @param[in] ImageHandle  Handle to the Image (NULL if Internal).
 | 
						|
  @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
 | 
						|
 | 
						|
  @return  SHELL_SUCCESS            The 'tftp' command completed successfully.
 | 
						|
  @return  SHELL_ABORTED            The Shell Library initialization failed.
 | 
						|
  @return  SHELL_INVALID_PARAMETER  At least one of the command's arguments is
 | 
						|
                                    not valid.
 | 
						|
  @return  SHELL_OUT_OF_RESOURCES   A memory allocation failed.
 | 
						|
  @return  SHELL_NOT_FOUND          Network Interface Card not found or server
 | 
						|
                                    error or file error.
 | 
						|
 | 
						|
**/
 | 
						|
SHELL_STATUS
 | 
						|
EFIAPI
 | 
						|
ShellCommandRunTftp (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  SHELL_STATUS            ShellStatus;
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  LIST_ENTRY              *CheckPackage;
 | 
						|
  CHAR16                  *ProblemParam;
 | 
						|
  UINTN                   ParamCount;
 | 
						|
  CONST CHAR16            *UserNicName;
 | 
						|
  BOOLEAN                 NicFound;
 | 
						|
  CONST CHAR16            *ValueStr;
 | 
						|
  CONST CHAR16            *RemoteFilePath;
 | 
						|
  CHAR8                   *AsciiRemoteFilePath;
 | 
						|
  UINTN                   FilePathSize;
 | 
						|
  CONST CHAR16            *Walker;
 | 
						|
  CONST CHAR16            *LocalFilePath;
 | 
						|
  EFI_MTFTP4_CONFIG_DATA  Mtftp4ConfigData;
 | 
						|
  EFI_HANDLE              *Handles;
 | 
						|
  UINTN                   HandleCount;
 | 
						|
  UINTN                   NicNumber;
 | 
						|
  CHAR16                  NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];
 | 
						|
  EFI_HANDLE              ControllerHandle;
 | 
						|
  EFI_HANDLE              Mtftp4ChildHandle;
 | 
						|
  EFI_MTFTP4_PROTOCOL     *Mtftp4;
 | 
						|
  UINTN                   FileSize;
 | 
						|
  VOID                    *Data;
 | 
						|
  SHELL_FILE_HANDLE       FileHandle;
 | 
						|
  UINT16                  BlockSize;
 | 
						|
 | 
						|
  ShellStatus         = SHELL_INVALID_PARAMETER;
 | 
						|
  ProblemParam        = NULL;
 | 
						|
  NicFound            = FALSE;
 | 
						|
  AsciiRemoteFilePath = NULL;
 | 
						|
  Handles             = NULL;
 | 
						|
  FileSize            = 0;
 | 
						|
  BlockSize           = MTFTP_DEFAULT_BLKSIZE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the Shell library (we must be in non-auto-init...)
 | 
						|
  //
 | 
						|
  Status = ShellInitialize ();
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    return SHELL_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse the command line.
 | 
						|
  //
 | 
						|
  Status = ShellCommandLineParse (ParamList, &CheckPackage, &ProblemParam, TRUE);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    if ((Status == EFI_VOLUME_CORRUPTED) &&
 | 
						|
        (ProblemParam != NULL) ) {
 | 
						|
      ShellPrintHiiEx (
 | 
						|
        -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellTftpHiiHandle,
 | 
						|
        L"tftp", ProblemParam
 | 
						|
        );
 | 
						|
      FreePool (ProblemParam);
 | 
						|
    } else {
 | 
						|
      ASSERT (FALSE);
 | 
						|
    }
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the number of parameters
 | 
						|
  //
 | 
						|
  ParamCount = ShellCommandLineGetCount (CheckPackage);
 | 
						|
  if (ParamCount > 4) {
 | 
						|
    ShellPrintHiiEx (
 | 
						|
      -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),
 | 
						|
      gShellTftpHiiHandle, L"tftp"
 | 
						|
      );
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
  if (ParamCount < 3) {
 | 
						|
    ShellPrintHiiEx (
 | 
						|
      -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW),
 | 
						|
      gShellTftpHiiHandle, L"tftp"
 | 
						|
      );
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (&Mtftp4ConfigData, &DefaultMtftp4ConfigData, sizeof (EFI_MTFTP4_CONFIG_DATA));
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the host IPv4 address
 | 
						|
  //
 | 
						|
  ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1);
 | 
						|
  Status = NetLibStrToIp4 (ValueStr, &Mtftp4ConfigData.ServerIp);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ShellPrintHiiEx (
 | 
						|
      -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
 | 
						|
      gShellTftpHiiHandle, L"tftp", ValueStr
 | 
						|
    );
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
 | 
						|
  RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);
 | 
						|
  ASSERT(RemoteFilePath != NULL);
 | 
						|
  FilePathSize = StrLen (RemoteFilePath) + 1;
 | 
						|
  AsciiRemoteFilePath = AllocatePool (FilePathSize);
 | 
						|
  if (AsciiRemoteFilePath == NULL) {
 | 
						|
    ShellStatus = SHELL_OUT_OF_RESOURCES;
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
  UnicodeStrToAsciiStrS (RemoteFilePath, AsciiRemoteFilePath, FilePathSize);
 | 
						|
 | 
						|
  if (ParamCount == 4) {
 | 
						|
    LocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3);
 | 
						|
  } else {
 | 
						|
    Walker = RemoteFilePath + StrLen (RemoteFilePath);
 | 
						|
    while ((--Walker) >= RemoteFilePath) {
 | 
						|
      if ((*Walker == L'\\') ||
 | 
						|
          (*Walker == L'/' )    ) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    LocalFilePath = Walker + 1;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the name of the Network Interface Card to be used if any.
 | 
						|
  //
 | 
						|
  UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i");
 | 
						|
 | 
						|
  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l");
 | 
						|
  if (ValueStr != NULL) {
 | 
						|
    if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.LocalPort)) {
 | 
						|
      goto Error;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-r");
 | 
						|
  if (ValueStr != NULL) {
 | 
						|
    if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.InitialServerPort)) {
 | 
						|
      goto Error;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-c");
 | 
						|
  if (ValueStr != NULL) {
 | 
						|
    if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TryCount)) {
 | 
						|
      goto Error;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");
 | 
						|
  if (ValueStr != NULL) {
 | 
						|
    if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TimeoutValue)) {
 | 
						|
      goto Error;
 | 
						|
    }
 | 
						|
    if (Mtftp4ConfigData.TimeoutValue == 0) {
 | 
						|
      ShellPrintHiiEx (
 | 
						|
        -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
 | 
						|
        gShellTftpHiiHandle, L"tftp", ValueStr
 | 
						|
      );
 | 
						|
      goto Error;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");
 | 
						|
  if (ValueStr != NULL) {
 | 
						|
    if (!StringToUint16 (ValueStr, &BlockSize)) {
 | 
						|
      goto Error;
 | 
						|
    }
 | 
						|
    if (BlockSize < MTFTP_MIN_BLKSIZE || BlockSize > MTFTP_MAX_BLKSIZE) {
 | 
						|
      ShellPrintHiiEx (
 | 
						|
        -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
 | 
						|
        gShellTftpHiiHandle, L"tftp", ValueStr
 | 
						|
      );
 | 
						|
      goto Error;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Locate all MTFTP4 Service Binding protocols
 | 
						|
  //
 | 
						|
  ShellStatus = SHELL_NOT_FOUND;
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                 ByProtocol,
 | 
						|
                 &gEfiManagedNetworkServiceBindingProtocolGuid,
 | 
						|
                 NULL,
 | 
						|
                 &HandleCount,
 | 
						|
                 &Handles
 | 
						|
                 );
 | 
						|
  if (EFI_ERROR (Status) || (HandleCount == 0)) {
 | 
						|
    ShellPrintHiiEx (
 | 
						|
      -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NO_NIC),
 | 
						|
      gShellTftpHiiHandle
 | 
						|
    );
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
 | 
						|
  for (NicNumber = 0;
 | 
						|
       (NicNumber < HandleCount) && (ShellStatus != SHELL_SUCCESS);
 | 
						|
       NicNumber++) {
 | 
						|
    ControllerHandle = Handles[NicNumber];
 | 
						|
    Data = NULL;
 | 
						|
 | 
						|
    Status = GetNicName (ControllerHandle, NicNumber, NicName);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ShellPrintHiiEx (
 | 
						|
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NAME),
 | 
						|
        gShellTftpHiiHandle, NicNumber, Status
 | 
						|
      );
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (UserNicName != NULL) {
 | 
						|
      if (StrCmp (NicName, UserNicName) != 0) {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      NicFound = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = CreateServiceChildAndOpenProtocol (
 | 
						|
               ControllerHandle,
 | 
						|
               &gEfiMtftp4ServiceBindingProtocolGuid,
 | 
						|
               &gEfiMtftp4ProtocolGuid,
 | 
						|
               &Mtftp4ChildHandle,
 | 
						|
               (VOID**)&Mtftp4
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ShellPrintHiiEx (
 | 
						|
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_OPEN_PROTOCOL),
 | 
						|
        gShellTftpHiiHandle, NicName, Status
 | 
						|
      );
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = Mtftp4->Configure (Mtftp4, &Mtftp4ConfigData);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ShellPrintHiiEx (
 | 
						|
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_CONFIGURE),
 | 
						|
        gShellTftpHiiHandle, NicName, Status
 | 
						|
      );
 | 
						|
      goto NextHandle;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = GetFileSize (Mtftp4, AsciiRemoteFilePath, &FileSize);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ShellPrintHiiEx (
 | 
						|
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_FILE_SIZE),
 | 
						|
        gShellTftpHiiHandle, RemoteFilePath, NicName, Status
 | 
						|
      );
 | 
						|
      goto NextHandle;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, BlockSize, &Data);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ShellPrintHiiEx (
 | 
						|
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD),
 | 
						|
        gShellTftpHiiHandle, RemoteFilePath, NicName, Status
 | 
						|
      );
 | 
						|
      goto NextHandle;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!EFI_ERROR (ShellFileExists (LocalFilePath))) {
 | 
						|
      ShellDeleteFileByName (LocalFilePath);
 | 
						|
    }
 | 
						|
 | 
						|
    Status = ShellOpenFileByName (
 | 
						|
               LocalFilePath,
 | 
						|
               &FileHandle,
 | 
						|
               EFI_FILE_MODE_CREATE |
 | 
						|
               EFI_FILE_MODE_WRITE  |
 | 
						|
               EFI_FILE_MODE_READ,
 | 
						|
               0
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ShellPrintHiiEx (
 | 
						|
        -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),
 | 
						|
        gShellTftpHiiHandle, L"tftp", LocalFilePath
 | 
						|
      );
 | 
						|
      goto NextHandle;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = ShellWriteFile (FileHandle, &FileSize, Data);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      ShellStatus = SHELL_SUCCESS;
 | 
						|
    } else {
 | 
						|
      ShellPrintHiiEx (
 | 
						|
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_WRITE),
 | 
						|
        gShellTftpHiiHandle, LocalFilePath, Status
 | 
						|
      );
 | 
						|
    }
 | 
						|
    ShellCloseFile (&FileHandle);
 | 
						|
 | 
						|
    NextHandle:
 | 
						|
 | 
						|
    if (Data != NULL) {
 | 
						|
      gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Data, EFI_SIZE_TO_PAGES (FileSize));
 | 
						|
    }
 | 
						|
 | 
						|
    CloseProtocolAndDestroyServiceChild (
 | 
						|
      ControllerHandle,
 | 
						|
      &gEfiMtftp4ServiceBindingProtocolGuid,
 | 
						|
      &gEfiMtftp4ProtocolGuid,
 | 
						|
      Mtftp4ChildHandle
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if ((UserNicName != NULL) && (!NicFound)) {
 | 
						|
    ShellPrintHiiEx (
 | 
						|
      -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND),
 | 
						|
      gShellTftpHiiHandle, UserNicName
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  Error:
 | 
						|
 | 
						|
  ShellCommandLineFreeVarList (CheckPackage);
 | 
						|
  if (AsciiRemoteFilePath != NULL) {
 | 
						|
    FreePool (AsciiRemoteFilePath);
 | 
						|
  }
 | 
						|
  if (Handles != NULL) {
 | 
						|
    FreePool (Handles);
 | 
						|
  }
 | 
						|
 | 
						|
  return ShellStatus;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check and convert the UINT16 option values of the 'tftp' command
 | 
						|
 | 
						|
  @param[in]  ValueStr  Value as an Unicode encoded string
 | 
						|
  @param[out] Value     UINT16 value
 | 
						|
 | 
						|
  @return     TRUE      The value was returned.
 | 
						|
  @return     FALSE     A parsing error occured.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
StringToUint16 (
 | 
						|
  IN   CONST CHAR16  *ValueStr,
 | 
						|
  OUT  UINT16        *Value
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  Val;
 | 
						|
 | 
						|
  Val = ShellStrToUintn (ValueStr);
 | 
						|
  if (Val > MAX_UINT16) {
 | 
						|
    ShellPrintHiiEx (
 | 
						|
      -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
 | 
						|
      gShellTftpHiiHandle, L"tftp", ValueStr
 | 
						|
    );
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  *Value = (UINT16)Val;
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the name of the NIC.
 | 
						|
 | 
						|
  @param[in]   ControllerHandle  The network physical device handle.
 | 
						|
  @param[in]   NicNumber         The network physical device number.
 | 
						|
  @param[out]  NicName           Address where to store the NIC name.
 | 
						|
                                 The memory area has to be at least
 | 
						|
                                 IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 
 | 
						|
                                 double byte wide.
 | 
						|
 | 
						|
  @return  EFI_SUCCESS  The name of the NIC was returned.
 | 
						|
  @return  Others       The creation of the child for the Managed
 | 
						|
                        Network Service failed or the opening of
 | 
						|
                        the Managed Network Protocol failed or
 | 
						|
                        the operational parameters for the
 | 
						|
                        Managed Network Protocol could not be
 | 
						|
                        read.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
GetNicName (
 | 
						|
  IN   EFI_HANDLE  ControllerHandle,
 | 
						|
  IN   UINTN       NicNumber,
 | 
						|
  OUT  CHAR16      *NicName
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_HANDLE                    MnpHandle;
 | 
						|
  EFI_MANAGED_NETWORK_PROTOCOL  *Mnp;
 | 
						|
  EFI_SIMPLE_NETWORK_MODE       SnpMode;
 | 
						|
 | 
						|
  Status = CreateServiceChildAndOpenProtocol (
 | 
						|
             ControllerHandle,
 | 
						|
             &gEfiManagedNetworkServiceBindingProtocolGuid,
 | 
						|
             &gEfiManagedNetworkProtocolGuid,
 | 
						|
             &MnpHandle,
 | 
						|
             (VOID**)&Mnp
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);
 | 
						|
  if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
 | 
						|
  UnicodeSPrint (
 | 
						|
    NicName,
 | 
						|
    IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH,
 | 
						|
    SnpMode.IfType == NET_IFTYPE_ETHERNET ?
 | 
						|
    L"eth%d" :
 | 
						|
    L"unk%d" ,
 | 
						|
    NicNumber
 | 
						|
    );
 | 
						|
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
 | 
						|
Error:
 | 
						|
 | 
						|
  if (MnpHandle != NULL) {
 | 
						|
    CloseProtocolAndDestroyServiceChild (
 | 
						|
      ControllerHandle,
 | 
						|
      &gEfiManagedNetworkServiceBindingProtocolGuid,
 | 
						|
      &gEfiManagedNetworkProtocolGuid,
 | 
						|
      MnpHandle
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create a child for the service identified by its service binding protocol GUID
 | 
						|
  and get from the child the interface of the protocol identified by its GUID.
 | 
						|
 | 
						|
  @param[in]   ControllerHandle            Controller handle.
 | 
						|
  @param[in]   ServiceBindingProtocolGuid  Service binding protocol GUID of the
 | 
						|
                                           service to be created.
 | 
						|
  @param[in]   ProtocolGuid                GUID of the protocol to be open.
 | 
						|
  @param[out]  ChildHandle                 Address where the handler of the
 | 
						|
                                           created child is returned. NULL is
 | 
						|
                                           returned in case of error.
 | 
						|
  @param[out]  Interface                   Address where a pointer to the
 | 
						|
                                           protocol interface is returned in
 | 
						|
                                           case of success.
 | 
						|
 | 
						|
  @return  EFI_SUCCESS  The child was created and the protocol opened.
 | 
						|
  @return  Others       Either the creation of the child or the opening
 | 
						|
                        of the protocol failed.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
CreateServiceChildAndOpenProtocol (
 | 
						|
  IN   EFI_HANDLE  ControllerHandle,
 | 
						|
  IN   EFI_GUID    *ServiceBindingProtocolGuid,
 | 
						|
  IN   EFI_GUID    *ProtocolGuid,
 | 
						|
  OUT  EFI_HANDLE  *ChildHandle,
 | 
						|
  OUT  VOID        **Interface
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  *ChildHandle = NULL;
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
             ControllerHandle,
 | 
						|
             gImageHandle,
 | 
						|
             ServiceBindingProtocolGuid,
 | 
						|
             ChildHandle
 | 
						|
             );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    *ChildHandle,
 | 
						|
                    ProtocolGuid,
 | 
						|
                    Interface,
 | 
						|
                    gImageHandle,
 | 
						|
                    ControllerHandle,
 | 
						|
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      NetLibDestroyServiceChild (
 | 
						|
        ControllerHandle,
 | 
						|
        gImageHandle,
 | 
						|
        ServiceBindingProtocolGuid,
 | 
						|
        *ChildHandle
 | 
						|
        );
 | 
						|
      *ChildHandle = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Close the protocol identified by its GUID on the child handle of the service
 | 
						|
  identified by its service binding protocol GUID, then destroy the child
 | 
						|
  handle.
 | 
						|
 | 
						|
  @param[in]  ControllerHandle            Controller handle.
 | 
						|
  @param[in]  ServiceBindingProtocolGuid  Service binding protocol GUID of the
 | 
						|
                                          service to be destroyed.
 | 
						|
  @param[in]  ProtocolGuid                GUID of the protocol to be closed.
 | 
						|
  @param[in]  ChildHandle                 Handle of the child to be destroyed.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
CloseProtocolAndDestroyServiceChild (
 | 
						|
  IN  EFI_HANDLE  ControllerHandle,
 | 
						|
  IN  EFI_GUID    *ServiceBindingProtocolGuid,
 | 
						|
  IN  EFI_GUID    *ProtocolGuid,
 | 
						|
  IN  EFI_HANDLE  ChildHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  gBS->CloseProtocol (
 | 
						|
         ChildHandle,
 | 
						|
         ProtocolGuid,
 | 
						|
         gImageHandle,
 | 
						|
         ControllerHandle
 | 
						|
         );
 | 
						|
 | 
						|
  NetLibDestroyServiceChild (
 | 
						|
    ControllerHandle,
 | 
						|
    gImageHandle,
 | 
						|
    ServiceBindingProtocolGuid,
 | 
						|
    ChildHandle
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Worker function that gets the size in numbers of bytes of a file from a TFTP
 | 
						|
  server before to download the file.
 | 
						|
 | 
						|
  @param[in]   Mtftp4    MTFTP4 protocol interface
 | 
						|
  @param[in]   FilePath  Path of the file, ASCII encoded
 | 
						|
  @param[out]  FileSize  Address where to store the file size in number of
 | 
						|
                         bytes.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS      The size of the file was returned.
 | 
						|
  @retval  EFI_UNSUPPORTED  The server does not support the "tsize" option.
 | 
						|
  @retval  Others           Error when retrieving the information from the server
 | 
						|
                            (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes)
 | 
						|
                            or error when parsing the response of the server.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
GetFileSize (
 | 
						|
  IN   EFI_MTFTP4_PROTOCOL  *Mtftp4,
 | 
						|
  IN   CONST CHAR8          *FilePath,
 | 
						|
  OUT  UINTN                *FileSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS         Status;
 | 
						|
  EFI_MTFTP4_OPTION  ReqOpt[1];
 | 
						|
  EFI_MTFTP4_PACKET  *Packet;
 | 
						|
  UINT32             PktLen;
 | 
						|
  EFI_MTFTP4_OPTION  *TableOfOptions;
 | 
						|
  EFI_MTFTP4_OPTION  *Option;
 | 
						|
  UINT32             OptCnt;
 | 
						|
  UINT8              OptBuf[128];
 | 
						|
 | 
						|
  ReqOpt[0].OptionStr = (UINT8*)"tsize";
 | 
						|
  OptBuf[0] = '0';
 | 
						|
  OptBuf[1] = 0;
 | 
						|
  ReqOpt[0].ValueStr = OptBuf;
 | 
						|
 | 
						|
  Status = Mtftp4->GetInfo (
 | 
						|
             Mtftp4,
 | 
						|
             NULL,
 | 
						|
             (UINT8*)FilePath,
 | 
						|
             NULL,
 | 
						|
             1,
 | 
						|
             ReqOpt,
 | 
						|
             &PktLen,
 | 
						|
             &Packet
 | 
						|
             );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = Mtftp4->ParseOptions (
 | 
						|
                     Mtftp4,
 | 
						|
                     PktLen,
 | 
						|
                     Packet,
 | 
						|
                     (UINT32 *) &OptCnt,
 | 
						|
                     &TableOfOptions
 | 
						|
                     );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
 | 
						|
  Option = TableOfOptions;
 | 
						|
  while (OptCnt != 0) {
 | 
						|
    if (AsciiStrnCmp ((CHAR8 *)Option->OptionStr, "tsize", 5) == 0) {
 | 
						|
      *FileSize = AsciiStrDecimalToUintn ((CHAR8 *)Option->ValueStr);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    OptCnt--;
 | 
						|
    Option++;
 | 
						|
  }
 | 
						|
  FreePool (TableOfOptions);
 | 
						|
 | 
						|
  if (OptCnt == 0) {
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
Error :
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Worker function that download the data of a file from a TFTP server given
 | 
						|
  the path of the file and its size.
 | 
						|
 | 
						|
  @param[in]   Mtftp4         MTFTP4 protocol interface
 | 
						|
  @param[in]   FilePath       Path of the file, Unicode encoded
 | 
						|
  @param[in]   AsciiFilePath  Path of the file, ASCII encoded
 | 
						|
  @param[in]   FileSize       Size of the file in number of bytes
 | 
						|
  @param[in]   BlockSize      Value of the TFTP blksize option
 | 
						|
  @param[out]  Data           Address where to store the address of the buffer
 | 
						|
                              where the data of the file were downloaded in
 | 
						|
                              case of success.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS           The file was downloaded.
 | 
						|
  @retval  EFI_OUT_OF_RESOURCES  A memory allocation failed.
 | 
						|
  @retval  Others                The downloading of the file from the server failed
 | 
						|
                                 (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes).
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
DownloadFile (
 | 
						|
  IN   EFI_MTFTP4_PROTOCOL  *Mtftp4,
 | 
						|
  IN   CONST CHAR16         *FilePath,
 | 
						|
  IN   CONST CHAR8          *AsciiFilePath,
 | 
						|
  IN   UINTN                FileSize,
 | 
						|
  IN   UINT16               BlockSize,
 | 
						|
  OUT  VOID                 **Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_PHYSICAL_ADDRESS  PagesAddress;
 | 
						|
  VOID                  *Buffer;
 | 
						|
  DOWNLOAD_CONTEXT      *TftpContext;
 | 
						|
  EFI_MTFTP4_TOKEN      Mtftp4Token;
 | 
						|
  EFI_MTFTP4_OPTION     ReqOpt;
 | 
						|
  UINT8                 OptBuf[10];
 | 
						|
 | 
						|
  // Downloaded file can be large. BS.AllocatePages() is more faster
 | 
						|
  // than AllocatePool() and avoid fragmentation.
 | 
						|
  // The downloaded file could be an EFI application. Marking the
 | 
						|
  // allocated page as EfiBootServicesCode would allow to execute a
 | 
						|
  // potential downloaded EFI application.
 | 
						|
  Status = gBS->AllocatePages (
 | 
						|
                   AllocateAnyPages,
 | 
						|
                   EfiBootServicesCode,
 | 
						|
                   EFI_SIZE_TO_PAGES (FileSize),
 | 
						|
                   &PagesAddress
 | 
						|
                   );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Buffer = (VOID*)(UINTN)PagesAddress;
 | 
						|
  TftpContext = AllocatePool (sizeof (DOWNLOAD_CONTEXT));
 | 
						|
  if (TftpContext == NULL) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
  TftpContext->FileSize = FileSize;
 | 
						|
  TftpContext->DownloadedNbOfBytes   = 0;
 | 
						|
  TftpContext->LastReportedNbOfBytes = 0;
 | 
						|
 | 
						|
  ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN));
 | 
						|
  Mtftp4Token.Filename    = (UINT8*)AsciiFilePath;
 | 
						|
  Mtftp4Token.BufferSize  = FileSize;
 | 
						|
  Mtftp4Token.Buffer      = Buffer;
 | 
						|
  Mtftp4Token.CheckPacket = CheckPacket;
 | 
						|
  Mtftp4Token.Context     = (VOID*)TftpContext;
 | 
						|
  if (BlockSize != MTFTP_DEFAULT_BLKSIZE) {
 | 
						|
    ReqOpt.OptionStr = (UINT8 *) "blksize";
 | 
						|
    AsciiSPrint ((CHAR8 *)OptBuf, sizeof (OptBuf), "%d", BlockSize);
 | 
						|
    ReqOpt.ValueStr  = OptBuf;
 | 
						|
 | 
						|
    Mtftp4Token.OptionCount = 1;
 | 
						|
    Mtftp4Token.OptionList  = &ReqOpt;
 | 
						|
  }
 | 
						|
 | 
						|
  ShellPrintHiiEx (
 | 
						|
    -1, -1, NULL, STRING_TOKEN (STR_TFTP_DOWNLOADING),
 | 
						|
    gShellTftpHiiHandle, FilePath
 | 
						|
    );
 | 
						|
 | 
						|
  Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token);
 | 
						|
  ShellPrintHiiEx (
 | 
						|
    -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF),
 | 
						|
    gShellTftpHiiHandle
 | 
						|
    );
 | 
						|
 | 
						|
Error :
 | 
						|
 | 
						|
  if (TftpContext == NULL) {
 | 
						|
    FreePool (TftpContext);
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    gBS->FreePages (PagesAddress, EFI_SIZE_TO_PAGES (FileSize));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  *Data = Buffer;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Update the progress of a file download
 | 
						|
  This procedure is called each time a new TFTP packet is received.
 | 
						|
 | 
						|
  @param[in]  This       MTFTP4 protocol interface
 | 
						|
  @param[in]  Token      Parameters for the download of the file
 | 
						|
  @param[in]  PacketLen  Length of the packet
 | 
						|
  @param[in]  Packet     Address of the packet
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS  All packets are accepted.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CheckPacket (
 | 
						|
  IN EFI_MTFTP4_PROTOCOL  *This,
 | 
						|
  IN EFI_MTFTP4_TOKEN     *Token,
 | 
						|
  IN UINT16               PacketLen,
 | 
						|
  IN EFI_MTFTP4_PACKET    *Packet
 | 
						|
  )
 | 
						|
{
 | 
						|
  DOWNLOAD_CONTEXT  *Context;
 | 
						|
  CHAR16            Progress[TFTP_PROGRESS_MESSAGE_SIZE];
 | 
						|
  UINTN             NbOfKb;
 | 
						|
  UINTN             Index;
 | 
						|
  UINTN             LastStep;
 | 
						|
  UINTN             Step;
 | 
						|
  EFI_STATUS        Status;
 | 
						|
 | 
						|
  if ((NTOHS (Packet->OpCode)) != EFI_MTFTP4_OPCODE_DATA) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Context = (DOWNLOAD_CONTEXT*)Token->Context;
 | 
						|
  if (Context->DownloadedNbOfBytes == 0) {
 | 
						|
    ShellPrintEx (-1, -1, L"%s       0 Kb", mTftpProgressFrame);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // The data in the packet are prepended with two UINT16 :
 | 
						|
  // . OpCode = EFI_MTFTP4_OPCODE_DATA
 | 
						|
  // . Block  = the number of this block of data
 | 
						|
  //
 | 
						|
  Context->DownloadedNbOfBytes += PacketLen - sizeof (Packet->OpCode)
 | 
						|
                                            - sizeof (Packet->Data.Block);
 | 
						|
  NbOfKb = Context->DownloadedNbOfBytes / 1024;
 | 
						|
 | 
						|
  Progress[0] = L'\0';
 | 
						|
  LastStep  = (Context->LastReportedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;
 | 
						|
  Step      = (Context->DownloadedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;
 | 
						|
 | 
						|
  if (Step <= LastStep) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  ShellPrintEx (-1, -1, L"%s", mTftpProgressDelete);
 | 
						|
 | 
						|
  Status = StrCpyS (Progress, TFTP_PROGRESS_MESSAGE_SIZE, mTftpProgressFrame);
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  for (Index = 1; Index < Step; Index++) {
 | 
						|
    Progress[Index] = L'=';
 | 
						|
  }
 | 
						|
  Progress[Step] = L'>';
 | 
						|
 | 
						|
  UnicodeSPrint (
 | 
						|
    Progress + (sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 1,
 | 
						|
    sizeof (Progress) - sizeof (mTftpProgressFrame),
 | 
						|
    L" %7d Kb",
 | 
						|
    NbOfKb
 | 
						|
    );
 | 
						|
  Context->LastReportedNbOfBytes = Context->DownloadedNbOfBytes;
 | 
						|
 | 
						|
  ShellPrintEx (-1, -1, L"%s", Progress);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |