]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c
ShellPkg/ShellLib: Constructor doesn't depend on ShellParameters
[mirror_edk2.git] / ShellPkg / Library / UefiShellTftpCommandLib / Tftp.c
old mode 100644 (file)
new mode 100755 (executable)
index d2f7046..fbde3bf
@@ -2,6 +2,8 @@
   The implementation for the 'tftp' Shell command.\r
 \r
   Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>\r
+  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved. <BR>\r
+  (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -14,6 +16,8 @@
 \r
 #include "UefiShellTftpCommandLib.h"\r
 \r
+#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32\r
+\r
 /*\r
    Constant strings and definitions related to the message indicating the amount of\r
    progress in the dowloading of a TFTP file.\r
@@ -59,7 +63,8 @@ StringToUint16 (
   @param[in]   NicNumber         The network physical device number.\r
   @param[out]  NicName           Address where to store the NIC name.\r
                                  The memory area has to be at least\r
-                                 IP4_NIC_NAME_LENGTH bytes wide.\r
+                                 IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH \r
+                                 double byte wide.\r
 \r
   @return  EFI_SUCCESS  The name of the NIC was returned.\r
   @return  Others       The creation of the child for the Managed\r
@@ -158,6 +163,7 @@ GetFileSize (
   @param[in]   FilePath       Path of the file, Unicode encoded\r
   @param[in]   AsciiFilePath  Path of the file, ASCII encoded\r
   @param[in]   FileSize       Size of the file in number of bytes\r
+  @param[in]   BlockSize      Value of the TFTP blksize option\r
   @param[out]  Data           Address where to store the address of the buffer\r
                               where the data of the file were downloaded in\r
                               case of success.\r
@@ -175,6 +181,7 @@ DownloadFile (
   IN   CONST CHAR16         *FilePath,\r
   IN   CONST CHAR8          *AsciiFilePath,\r
   IN   UINTN                FileSize,\r
+  IN   UINT16               BlockSize,\r
   OUT  VOID                 **Data\r
   );\r
 \r
@@ -192,6 +199,7 @@ DownloadFile (
 **/\r
 STATIC \r
 EFI_STATUS \r
+EFIAPI\r
 CheckPacket (\r
   IN EFI_MTFTP4_PROTOCOL  *This,\r
   IN EFI_MTFTP4_TOKEN     *Token,\r
@@ -217,9 +225,21 @@ STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
   {L"-r", TypeValue},\r
   {L"-c", TypeValue},\r
   {L"-t", TypeValue},\r
+  {L"-s", TypeValue},\r
   {NULL , TypeMax}\r
   };\r
 \r
+///\r
+/// The default block size (512) of tftp is defined in the RFC1350.\r
+///\r
+#define MTFTP_DEFAULT_BLKSIZE      512\r
+///\r
+/// The valid range of block size option is defined in the RFC2348.\r
+///\r
+#define MTFTP_MIN_BLKSIZE          8\r
+#define MTFTP_MAX_BLKSIZE          65464\r
+\r
+\r
 /**\r
   Function for 'tftp' command.\r
 \r
@@ -252,25 +272,31 @@ ShellCommandRunTftp (
   CONST CHAR16            *ValueStr;\r
   CONST CHAR16            *RemoteFilePath;\r
   CHAR8                   *AsciiRemoteFilePath;\r
+  UINTN                   FilePathSize;\r
   CONST CHAR16            *Walker;\r
   CONST CHAR16            *LocalFilePath;\r
   EFI_MTFTP4_CONFIG_DATA  Mtftp4ConfigData;\r
   EFI_HANDLE              *Handles;\r
   UINTN                   HandleCount;\r
   UINTN                   NicNumber;\r
-  CHAR16                  NicName[IP4_NIC_NAME_LENGTH];\r
+  CHAR16                  NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];\r
   EFI_HANDLE              ControllerHandle;\r
   EFI_HANDLE              Mtftp4ChildHandle;\r
   EFI_MTFTP4_PROTOCOL     *Mtftp4;\r
   UINTN                   FileSize;\r
+  UINTN                   DataSize;\r
   VOID                    *Data;\r
   SHELL_FILE_HANDLE       FileHandle;\r
+  UINT16                  BlockSize;\r
 \r
   ShellStatus         = SHELL_INVALID_PARAMETER;\r
   ProblemParam        = NULL;\r
   NicFound            = FALSE;\r
   AsciiRemoteFilePath = NULL;\r
   Handles             = NULL;\r
+  FileSize            = 0;\r
+  DataSize            = 0;\r
+  BlockSize           = MTFTP_DEFAULT_BLKSIZE;\r
 \r
   //\r
   // Initialize the Shell library (we must be in non-auto-init...)\r
@@ -318,7 +344,7 @@ ShellCommandRunTftp (
     goto Error;\r
   }\r
 \r
-  Mtftp4ConfigData = DefaultMtftp4ConfigData;\r
+  CopyMem (&Mtftp4ConfigData, &DefaultMtftp4ConfigData, sizeof (EFI_MTFTP4_CONFIG_DATA));\r
 \r
   //\r
   // Check the host IPv4 address\r
@@ -334,14 +360,14 @@ ShellCommandRunTftp (
   }\r
 \r
   RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);\r
-  AsciiRemoteFilePath = AllocatePool (\r
-                          (StrLen (RemoteFilePath) + 1) * sizeof (CHAR8)\r
-                          );\r
+  ASSERT(RemoteFilePath != NULL);\r
+  FilePathSize = StrLen (RemoteFilePath) + 1;\r
+  AsciiRemoteFilePath = AllocatePool (FilePathSize);\r
   if (AsciiRemoteFilePath == NULL) {\r
     ShellStatus = SHELL_OUT_OF_RESOURCES;\r
     goto Error;\r
   }\r
-  UnicodeStrToAsciiStr (RemoteFilePath, AsciiRemoteFilePath);\r
+  UnicodeStrToAsciiStrS (RemoteFilePath, AsciiRemoteFilePath, FilePathSize);\r
 \r
   if (ParamCount == 4) {\r
     LocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3);\r
@@ -396,6 +422,20 @@ ShellCommandRunTftp (
     }\r
   }\r
 \r
+  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");\r
+  if (ValueStr != NULL) {\r
+    if (!StringToUint16 (ValueStr, &BlockSize)) {\r
+      goto Error;\r
+    }\r
+    if (BlockSize < MTFTP_MIN_BLKSIZE || BlockSize > MTFTP_MAX_BLKSIZE) {\r
+      ShellPrintHiiEx (\r
+        -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),\r
+        gShellTftpHiiHandle, L"tftp", ValueStr\r
+      );\r
+      goto Error;\r
+    }\r
+  }\r
+\r
   //\r
   // Locate all MTFTP4 Service Binding protocols\r
   //\r
@@ -470,7 +510,7 @@ ShellCommandRunTftp (
       goto NextHandle;\r
     }\r
 \r
-    Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, &Data);\r
+    Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, BlockSize, &Data);\r
     if (EFI_ERROR (Status)) {\r
       ShellPrintHiiEx (\r
         -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD),\r
@@ -499,6 +539,7 @@ ShellCommandRunTftp (
       goto NextHandle;\r
     }\r
 \r
+    DataSize = FileSize;\r
     Status = ShellWriteFile (FileHandle, &FileSize, Data);\r
     if (!EFI_ERROR (Status)) {\r
       ShellStatus = SHELL_SUCCESS;\r
@@ -513,7 +554,7 @@ ShellCommandRunTftp (
     NextHandle:\r
 \r
     if (Data != NULL) {\r
-      gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Data, EFI_SIZE_TO_PAGES (FileSize));\r
+      gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Data, EFI_SIZE_TO_PAGES (DataSize));\r
     }\r
 \r
     CloseProtocolAndDestroyServiceChild (\r
@@ -571,7 +612,7 @@ StringToUint16 (
     return FALSE;\r
   }\r
 \r
-  *Value = Val;\r
+  *Value = (UINT16)Val;\r
   return TRUE;\r
 }\r
 \r
@@ -582,7 +623,8 @@ StringToUint16 (
   @param[in]   NicNumber         The network physical device number.\r
   @param[out]  NicName           Address where to store the NIC name.\r
                                  The memory area has to be at least\r
-                                 IP4_NIC_NAME_LENGTH bytes wide.\r
+                                 IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH \r
+                                 double byte wide.\r
 \r
   @return  EFI_SUCCESS  The name of the NIC was returned.\r
   @return  Others       The creation of the child for the Managed\r
@@ -623,7 +665,7 @@ GetNicName (
 \r
   UnicodeSPrint (\r
     NicName,\r
-    IP4_NIC_NAME_LENGTH,\r
+    IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH,\r
     SnpMode.IfType == NET_IFTYPE_ETHERNET ?\r
     L"eth%d" :\r
     L"unk%d" ,\r
@@ -834,6 +876,7 @@ Error :
   @param[in]   FilePath       Path of the file, Unicode encoded\r
   @param[in]   AsciiFilePath  Path of the file, ASCII encoded\r
   @param[in]   FileSize       Size of the file in number of bytes\r
+  @param[in]   BlockSize      Value of the TFTP blksize option\r
   @param[out]  Data           Address where to store the address of the buffer\r
                               where the data of the file were downloaded in\r
                               case of success.\r
@@ -851,6 +894,7 @@ DownloadFile (
   IN   CONST CHAR16         *FilePath,\r
   IN   CONST CHAR8          *AsciiFilePath,\r
   IN   UINTN                FileSize,\r
+  IN   UINT16               BlockSize,\r
   OUT  VOID                 **Data\r
   )\r
 {\r
@@ -859,6 +903,8 @@ DownloadFile (
   VOID                  *Buffer;\r
   DOWNLOAD_CONTEXT      *TftpContext;\r
   EFI_MTFTP4_TOKEN      Mtftp4Token;\r
+  EFI_MTFTP4_OPTION     ReqOpt;\r
+  UINT8                 OptBuf[10];\r
 \r
   // Downloaded file can be large. BS.AllocatePages() is more faster\r
   // than AllocatePool() and avoid fragmentation.\r
@@ -891,6 +937,14 @@ DownloadFile (
   Mtftp4Token.Buffer      = Buffer;\r
   Mtftp4Token.CheckPacket = CheckPacket;\r
   Mtftp4Token.Context     = (VOID*)TftpContext;\r
+  if (BlockSize != MTFTP_DEFAULT_BLKSIZE) {\r
+    ReqOpt.OptionStr = (UINT8 *) "blksize";\r
+    AsciiSPrint ((CHAR8 *)OptBuf, sizeof (OptBuf), "%d", BlockSize);\r
+    ReqOpt.ValueStr  = OptBuf;\r
+\r
+    Mtftp4Token.OptionCount = 1;\r
+    Mtftp4Token.OptionList  = &ReqOpt;\r
+  }\r
 \r
   ShellPrintHiiEx (\r
     -1, -1, NULL, STRING_TOKEN (STR_TFTP_DOWNLOADING),\r
@@ -933,6 +987,7 @@ Error :
 **/\r
 STATIC\r
 EFI_STATUS\r
+EFIAPI\r
 CheckPacket (\r
   IN EFI_MTFTP4_PROTOCOL  *This,\r
   IN EFI_MTFTP4_TOKEN     *Token,\r
@@ -942,10 +997,11 @@ CheckPacket (
 {\r
   DOWNLOAD_CONTEXT  *Context;\r
   CHAR16            Progress[TFTP_PROGRESS_MESSAGE_SIZE];\r
-  UINT64            NbOfKb;\r
+  UINT            NbOfKb;\r
   UINTN             Index;\r
   UINTN             LastStep;\r
   UINTN             Step;\r
+  EFI_STATUS        Status;\r
 \r
   if ((NTOHS (Packet->OpCode)) != EFI_MTFTP4_OPCODE_DATA) {\r
     return EFI_SUCCESS;\r
@@ -966,17 +1022,19 @@ CheckPacket (
   NbOfKb = Context->DownloadedNbOfBytes / 1024;\r
 \r
   Progress[0] = L'\0';\r
-  LastStep  = (Context->LastReportedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) /\r
-              Context->FileSize;\r
-  Step      = (Context->DownloadedNbOfBytes   * TFTP_PROGRESS_SLIDER_STEPS) /\r
-              Context->FileSize;\r
+  LastStep  = (Context->LastReportedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;\r
+  Step      = (Context->DownloadedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;\r
+\r
   if (Step <= LastStep) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
   ShellPrintEx (-1, -1, L"%s", mTftpProgressDelete);\r
 \r
-  StrCpy (Progress, mTftpProgressFrame);\r
+  Status = StrCpyS (Progress, TFTP_PROGRESS_MESSAGE_SIZE, mTftpProgressFrame);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
   for (Index = 1; Index < Step; Index++) {\r
     Progress[Index] = L'=';\r
   }\r