Fix various typos in comments and documentation. Cc: Ray Ni <ray.ni@intel.com> Cc: Zhichao Gao <zhichao.gao@intel.com> Signed-off-by: Antoine Coeur <coeur@gmx.fr> Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com> Reviewed-by: Zhichao Gao <zhichao.gao@intel.com> Signed-off-by: Philippe Mathieu-Daude <philmd@redhat.com> Message-Id: <20200207010831.9046-69-philmd@redhat.com>
		
			
				
	
	
		
			1130 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1130 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   The implementation for the 'tftp' Shell command.
 | |
| 
 | |
|   Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
 | |
|   Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved. <BR>
 | |
|   (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
 | |
| 
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| **/
 | |
| 
 | |
| #include "Tftp.h"
 | |
| 
 | |
| #define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32
 | |
| EFI_HII_HANDLE   mTftpHiiHandle;
 | |
| 
 | |
| /*
 | |
|    Constant strings and definitions related to the message indicating the amount of
 | |
|    progress in the downloading 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";
 | |
| 
 | |
| // Local File Handle
 | |
| SHELL_FILE_HANDLE     mFileHandle;
 | |
| 
 | |
| // Path of the local file, Unicode encoded
 | |
| CONST CHAR16         *mLocalFilePath;
 | |
| 
 | |
| /**
 | |
|   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 occurred.
 | |
| **/
 | |
| 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[in]   WindowSize     Value of the TFTP window size option
 | |
| 
 | |
|   @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,
 | |
|   IN   UINT16               WindowSize
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   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          - The number of times to transmit request packets and wait for a response.
 | |
|   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},
 | |
|   {L"-w", 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
 | |
| ///
 | |
| /// The default windowsize (1) of tftp.
 | |
| ///
 | |
| #define MTFTP_DEFAULT_WINDOWSIZE   1
 | |
| ///
 | |
| /// The valid range of window size option.
 | |
| /// Note that: RFC 7440 does not mention max window size value, but for the
 | |
| /// stability reason, the value is limited to 64.
 | |
| ///
 | |
| #define MTFTP_MIN_WINDOWSIZE       1
 | |
| #define MTFTP_MAX_WINDOWSIZE       64
 | |
| 
 | |
| /**
 | |
|   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
 | |
| RunTftp (
 | |
|   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;
 | |
|   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;
 | |
|   UINT16                  BlockSize;
 | |
|   UINT16                  WindowSize;
 | |
| 
 | |
|   ShellStatus         = SHELL_INVALID_PARAMETER;
 | |
|   ProblemParam        = NULL;
 | |
|   NicFound            = FALSE;
 | |
|   AsciiRemoteFilePath = NULL;
 | |
|   Handles             = NULL;
 | |
|   FileSize            = 0;
 | |
|   BlockSize           = MTFTP_DEFAULT_BLKSIZE;
 | |
|   WindowSize          = MTFTP_DEFAULT_WINDOWSIZE;
 | |
| 
 | |
|   //
 | |
|   // 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), mTftpHiiHandle,
 | |
|         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),
 | |
|       mTftpHiiHandle, L"tftp"
 | |
|       );
 | |
|     goto Error;
 | |
|   }
 | |
|   if (ParamCount < 3) {
 | |
|     ShellPrintHiiEx (
 | |
|       -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW),
 | |
|       mTftpHiiHandle, 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),
 | |
|       mTftpHiiHandle, 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) {
 | |
|     mLocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3);
 | |
|   } else {
 | |
|     Walker = RemoteFilePath + StrLen (RemoteFilePath);
 | |
|     while ((--Walker) >= RemoteFilePath) {
 | |
|       if ((*Walker == L'\\') ||
 | |
|           (*Walker == L'/' )    ) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     mLocalFilePath = 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;
 | |
|     }
 | |
| 
 | |
|     if (Mtftp4ConfigData.TryCount == 0) {
 | |
|       Mtftp4ConfigData.TryCount = 6;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   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),
 | |
|         mTftpHiiHandle, 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),
 | |
|         mTftpHiiHandle, L"tftp", ValueStr
 | |
|       );
 | |
|       goto Error;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   ValueStr = ShellCommandLineGetValue (CheckPackage, L"-w");
 | |
|   if (ValueStr != NULL) {
 | |
|     if (!StringToUint16 (ValueStr, &WindowSize)) {
 | |
|       goto Error;
 | |
|     }
 | |
|     if (WindowSize < MTFTP_MIN_WINDOWSIZE || WindowSize > MTFTP_MAX_WINDOWSIZE) {
 | |
|       ShellPrintHiiEx (
 | |
|         -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
 | |
|         mTftpHiiHandle, 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),
 | |
|       mTftpHiiHandle
 | |
|     );
 | |
|     goto Error;
 | |
|   }
 | |
| 
 | |
|   for (NicNumber = 0;
 | |
|        (NicNumber < HandleCount) && (ShellStatus != SHELL_SUCCESS);
 | |
|        NicNumber++) {
 | |
|     ControllerHandle = Handles[NicNumber];
 | |
| 
 | |
|     Status = GetNicName (ControllerHandle, NicNumber, NicName);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       ShellPrintHiiEx (
 | |
|         -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NAME),
 | |
|         mTftpHiiHandle, 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),
 | |
|         mTftpHiiHandle, NicName, Status
 | |
|       );
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     Status = Mtftp4->Configure (Mtftp4, &Mtftp4ConfigData);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       ShellPrintHiiEx (
 | |
|         -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_CONFIGURE),
 | |
|         mTftpHiiHandle, NicName, Status
 | |
|       );
 | |
|       goto NextHandle;
 | |
|     }
 | |
| 
 | |
|     Status = GetFileSize (Mtftp4, AsciiRemoteFilePath, &FileSize);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       ShellPrintHiiEx (
 | |
|         -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_FILE_SIZE),
 | |
|         mTftpHiiHandle, RemoteFilePath, NicName, Status
 | |
|       );
 | |
|       goto NextHandle;
 | |
|     }
 | |
| 
 | |
|     Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, BlockSize, WindowSize);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       ShellPrintHiiEx (
 | |
|         -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD),
 | |
|         mTftpHiiHandle, RemoteFilePath, NicName, Status
 | |
|       );
 | |
|       goto NextHandle;
 | |
|     }
 | |
| 
 | |
|     ShellStatus = SHELL_SUCCESS;
 | |
| 
 | |
|     NextHandle:
 | |
| 
 | |
|     CloseProtocolAndDestroyServiceChild (
 | |
|       ControllerHandle,
 | |
|       &gEfiMtftp4ServiceBindingProtocolGuid,
 | |
|       &gEfiMtftp4ProtocolGuid,
 | |
|       Mtftp4ChildHandle
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   if ((UserNicName != NULL) && (!NicFound)) {
 | |
|     ShellPrintHiiEx (
 | |
|       -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND),
 | |
|       mTftpHiiHandle, UserNicName
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Error:
 | |
| 
 | |
|   ShellCommandLineFreeVarList (CheckPackage);
 | |
|   if (AsciiRemoteFilePath != NULL) {
 | |
|     FreePool (AsciiRemoteFilePath);
 | |
|   }
 | |
|   if (Handles != NULL) {
 | |
|     FreePool (Handles);
 | |
|   }
 | |
| 
 | |
|   if ((ShellStatus != SHELL_SUCCESS) && (EFI_ERROR(Status))) {
 | |
|     ShellStatus = Status & ~MAX_BIT;
 | |
|   }
 | |
| 
 | |
|   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 occurred.
 | |
| **/
 | |
| 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),
 | |
|       mTftpHiiHandle, 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[in]   WindowSize     Value of the TFTP window size option
 | |
| 
 | |
|   @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,
 | |
|   IN   UINT16               WindowSize
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS            Status;
 | |
|   DOWNLOAD_CONTEXT      *TftpContext;
 | |
|   EFI_MTFTP4_TOKEN      Mtftp4Token;
 | |
|   UINT8                 BlksizeBuf[10];
 | |
|   UINT8                 WindowsizeBuf[10];
 | |
| 
 | |
|   ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN));
 | |
| 
 | |
|   TftpContext = AllocatePool (sizeof (DOWNLOAD_CONTEXT));
 | |
|   if (TftpContext == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Error;
 | |
|   }
 | |
|   TftpContext->FileSize = FileSize;
 | |
|   TftpContext->DownloadedNbOfBytes   = 0;
 | |
|   TftpContext->LastReportedNbOfBytes = 0;
 | |
| 
 | |
|   Mtftp4Token.Filename    = (UINT8*)AsciiFilePath;
 | |
|   Mtftp4Token.CheckPacket = CheckPacket;
 | |
|   Mtftp4Token.Context     = (VOID*)TftpContext;
 | |
|   Mtftp4Token.OptionCount = 0;
 | |
|   Mtftp4Token.OptionList  = AllocatePool (sizeof (EFI_MTFTP4_OPTION) * 2);
 | |
|   if (Mtftp4Token.OptionList == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Error;
 | |
|   }
 | |
| 
 | |
|   if (BlockSize != MTFTP_DEFAULT_BLKSIZE) {
 | |
|     Mtftp4Token.OptionList[Mtftp4Token.OptionCount].OptionStr = (UINT8 *) "blksize";
 | |
|     AsciiSPrint ((CHAR8 *) BlksizeBuf, sizeof (BlksizeBuf), "%d", BlockSize);
 | |
|     Mtftp4Token.OptionList[Mtftp4Token.OptionCount].ValueStr  = BlksizeBuf;
 | |
|     Mtftp4Token.OptionCount ++;
 | |
|   }
 | |
| 
 | |
|   if (WindowSize != MTFTP_DEFAULT_WINDOWSIZE) {
 | |
|     Mtftp4Token.OptionList[Mtftp4Token.OptionCount].OptionStr = (UINT8 *) "windowsize";
 | |
|     AsciiSPrint ((CHAR8 *) WindowsizeBuf, sizeof (WindowsizeBuf), "%d", WindowSize);
 | |
|     Mtftp4Token.OptionList[Mtftp4Token.OptionCount].ValueStr  = WindowsizeBuf;
 | |
|     Mtftp4Token.OptionCount ++;
 | |
|   }
 | |
| 
 | |
|   ShellPrintHiiEx (
 | |
|     -1, -1, NULL, STRING_TOKEN (STR_TFTP_DOWNLOADING),
 | |
|     mTftpHiiHandle, FilePath
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // OPEN FILE
 | |
|   //
 | |
|   if (!EFI_ERROR (ShellFileExists (mLocalFilePath))) {
 | |
|     ShellDeleteFileByName (mLocalFilePath);
 | |
|   }
 | |
| 
 | |
|   Status = ShellOpenFileByName (
 | |
|               mLocalFilePath,
 | |
|               &mFileHandle,
 | |
|               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),
 | |
|       mTftpHiiHandle, L"tftp", mLocalFilePath
 | |
|     );
 | |
|     goto Error;
 | |
|   }
 | |
| 
 | |
|   Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token);
 | |
|   ShellPrintHiiEx (
 | |
|     -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF),
 | |
|     mTftpHiiHandle
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // CLOSE FILE
 | |
|   //
 | |
|   ShellCloseFile (&mFileHandle);
 | |
| 
 | |
| Error :
 | |
|   if (TftpContext != NULL) {
 | |
|     FreePool (TftpContext);
 | |
|   }
 | |
| 
 | |
|   if (Mtftp4Token.OptionList != NULL) {
 | |
|     FreePool (Mtftp4Token.OptionList);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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;
 | |
|   UINTN             DownloadLen;
 | |
|   EFI_STATUS        Status;
 | |
| 
 | |
|   if ((NTOHS (Packet->OpCode)) != EFI_MTFTP4_OPCODE_DATA) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Context = (DOWNLOAD_CONTEXT*)Token->Context;
 | |
| 
 | |
|   //
 | |
|   // The data in the packet are prepended with two UINT16 :
 | |
|   // . OpCode = EFI_MTFTP4_OPCODE_DATA
 | |
|   // . Block  = the number of this block of data
 | |
|   //
 | |
|   DownloadLen = (UINTN)PacketLen - sizeof (Packet->OpCode) - sizeof (Packet->Data.Block);
 | |
| 
 | |
|   ShellSetFilePosition(mFileHandle, Context->DownloadedNbOfBytes);
 | |
|   Status = ShellWriteFile (mFileHandle, &DownloadLen, Packet->Data.Data);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     if (Context->DownloadedNbOfBytes > 0) {
 | |
|       ShellPrintHiiEx (
 | |
|         -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF),
 | |
|         mTftpHiiHandle
 | |
|       );
 | |
|     }
 | |
|     ShellPrintHiiEx (
 | |
|       -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_WRITE),
 | |
|       mTftpHiiHandle, mLocalFilePath, Status
 | |
|     );
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (Context->DownloadedNbOfBytes == 0) {
 | |
|     ShellPrintEx (-1, -1, L"%s       0 Kb", mTftpProgressFrame);
 | |
|   }
 | |
| 
 | |
|   Context->DownloadedNbOfBytes += DownloadLen;
 | |
|   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;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Retrieve HII package list from ImageHandle and publish to HII database.
 | |
| 
 | |
|   @param ImageHandle            The image handle of the process.
 | |
| 
 | |
|   @return HII handle.
 | |
| **/
 | |
| EFI_HII_HANDLE
 | |
| InitializeHiiPackage (
 | |
|   EFI_HANDLE                  ImageHandle
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_HII_PACKAGE_LIST_HEADER *PackageList;
 | |
|   EFI_HII_HANDLE              HiiHandle;
 | |
| 
 | |
|   //
 | |
|   // Retrieve HII package list from ImageHandle
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   ImageHandle,
 | |
|                   &gEfiHiiPackageListProtocolGuid,
 | |
|                   (VOID **)&PackageList,
 | |
|                   ImageHandle,
 | |
|                   NULL,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Publish HII package list to HII Database.
 | |
|   //
 | |
|   Status = gHiiDatabase->NewPackageList (
 | |
|                            gHiiDatabase,
 | |
|                            PackageList,
 | |
|                            NULL,
 | |
|                            &HiiHandle
 | |
|                            );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return NULL;
 | |
|   }
 | |
|   return HiiHandle;
 | |
| }
 |