]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.c
ShellPkg/TftpDynamicCommand: Change file writing method in tftp
[mirror_edk2.git] / ShellPkg / DynamicCommand / TftpDynamicCommand / Tftp.c
index ed081b5bad7cf5a4b5f16ee506d259a20ad6e178..ba753a279b00747ed342a95d27a8a111be30e270 100644 (file)
@@ -41,6 +41,12 @@ STATIC CONST CHAR16 mTftpProgressFrame[] = L"[
 // (TFTP_PROGRESS_MESSAGE_SIZE-1) '\b'\r
 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";\r
 \r
+// Local File Handle\r
+SHELL_FILE_HANDLE     mFileHandle;\r
+\r
+// Path of the local file, Unicode encoded\r
+CONST CHAR16         *mLocalFilePath;\r
+\r
 /**\r
   Check and convert the UINT16 option values of the 'tftp' command\r
 \r
@@ -166,9 +172,6 @@ GetFileSize (
   @param[in]   FileSize       Size of the file in number of bytes\r
   @param[in]   BlockSize      Value of the TFTP blksize option\r
   @param[in]   WindowSize     Value of the TFTP window size 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
 \r
   @retval  EFI_SUCCESS           The file was downloaded.\r
   @retval  EFI_OUT_OF_RESOURCES  A memory allocation failed.\r
@@ -184,8 +187,7 @@ DownloadFile (
   IN   CONST CHAR8          *AsciiFilePath,\r
   IN   UINTN                FileSize,\r
   IN   UINT16               BlockSize,\r
-  IN   UINT16               WindowSize,\r
-  OUT  VOID                 **Data\r
+  IN   UINT16               WindowSize\r
   );\r
 \r
 /**\r
@@ -287,7 +289,6 @@ RunTftp (
   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
@@ -297,9 +298,6 @@ RunTftp (
   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
   UINT16                  WindowSize;\r
 \r
@@ -309,7 +307,6 @@ RunTftp (
   AsciiRemoteFilePath = NULL;\r
   Handles             = NULL;\r
   FileSize            = 0;\r
-  DataSize            = 0;\r
   BlockSize           = MTFTP_DEFAULT_BLKSIZE;\r
   WindowSize          = MTFTP_DEFAULT_WINDOWSIZE;\r
 \r
@@ -385,7 +382,7 @@ RunTftp (
   UnicodeStrToAsciiStrS (RemoteFilePath, AsciiRemoteFilePath, FilePathSize);\r
 \r
   if (ParamCount == 4) {\r
-    LocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3);\r
+    mLocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3);\r
   } else {\r
     Walker = RemoteFilePath + StrLen (RemoteFilePath);\r
     while ((--Walker) >= RemoteFilePath) {\r
@@ -394,7 +391,7 @@ RunTftp (
         break;\r
       }\r
     }\r
-    LocalFilePath = Walker + 1;\r
+    mLocalFilePath = Walker + 1;\r
   }\r
 \r
   //\r
@@ -492,7 +489,6 @@ RunTftp (
        (NicNumber < HandleCount) && (ShellStatus != SHELL_SUCCESS);\r
        NicNumber++) {\r
     ControllerHandle = Handles[NicNumber];\r
-    Data = NULL;\r
 \r
     Status = GetNicName (ControllerHandle, NicNumber, NicName);\r
     if (EFI_ERROR (Status)) {\r
@@ -543,7 +539,7 @@ RunTftp (
       goto NextHandle;\r
     }\r
 \r
-    Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, BlockSize, WindowSize, &Data);\r
+    Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, BlockSize, WindowSize);\r
     if (EFI_ERROR (Status)) {\r
       ShellPrintHiiEx (\r
         -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD),\r
@@ -552,45 +548,8 @@ RunTftp (
       goto NextHandle;\r
     }\r
 \r
-    DataSize = FileSize;\r
-\r
-    if (!EFI_ERROR (ShellFileExists (LocalFilePath))) {\r
-      ShellDeleteFileByName (LocalFilePath);\r
-    }\r
-\r
-    Status = ShellOpenFileByName (\r
-               LocalFilePath,\r
-               &FileHandle,\r
-               EFI_FILE_MODE_CREATE |\r
-               EFI_FILE_MODE_WRITE  |\r
-               EFI_FILE_MODE_READ,\r
-               0\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      ShellPrintHiiEx (\r
-        -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),\r
-        mTftpHiiHandle, L"tftp", LocalFilePath\r
-      );\r
-      goto NextHandle;\r
-    }\r
-\r
-    Status = ShellWriteFile (FileHandle, &FileSize, Data);\r
-    if (!EFI_ERROR (Status)) {\r
-      ShellStatus = SHELL_SUCCESS;\r
-    } else {\r
-      ShellPrintHiiEx (\r
-        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_WRITE),\r
-        mTftpHiiHandle, LocalFilePath, Status\r
-      );\r
-    }\r
-    ShellCloseFile (&FileHandle);\r
-\r
     NextHandle:\r
 \r
-    if (Data != NULL) {\r
-      gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Data, EFI_SIZE_TO_PAGES (DataSize));\r
-    }\r
-\r
     CloseProtocolAndDestroyServiceChild (\r
       ControllerHandle,\r
       &gEfiMtftp4ServiceBindingProtocolGuid,\r
@@ -912,9 +871,6 @@ Error :
   @param[in]   FileSize       Size of the file in number of bytes\r
   @param[in]   BlockSize      Value of the TFTP blksize option\r
   @param[in]   WindowSize     Value of the TFTP window size 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
 \r
   @retval  EFI_SUCCESS           The file was downloaded.\r
   @retval  EFI_OUT_OF_RESOURCES  A memory allocation failed.\r
@@ -930,13 +886,10 @@ DownloadFile (
   IN   CONST CHAR8          *AsciiFilePath,\r
   IN   UINTN                FileSize,\r
   IN   UINT16               BlockSize,\r
-  IN   UINT16               WindowSize,\r
-  OUT  VOID                 **Data\r
+  IN   UINT16               WindowSize\r
   )\r
 {\r
   EFI_STATUS            Status;\r
-  EFI_PHYSICAL_ADDRESS  PagesAddress;\r
-  VOID                  *Buffer;\r
   DOWNLOAD_CONTEXT      *TftpContext;\r
   EFI_MTFTP4_TOKEN      Mtftp4Token;\r
   UINT8                 BlksizeBuf[10];\r
@@ -944,22 +897,6 @@ DownloadFile (
 \r
   ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN));\r
 \r
-  // Downloaded file can be large. BS.AllocatePages() is more faster\r
-  // than AllocatePool() and avoid fragmentation.\r
-  // The downloaded file could be an EFI application. Marking the\r
-  // allocated page as EfiBootServicesCode would allow to execute a\r
-  // potential downloaded EFI application.\r
-  Status = gBS->AllocatePages (\r
-                   AllocateAnyPages,\r
-                   EfiBootServicesCode,\r
-                   EFI_SIZE_TO_PAGES (FileSize),\r
-                   &PagesAddress\r
-                   );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Buffer = (VOID*)(UINTN)PagesAddress;\r
   TftpContext = AllocatePool (sizeof (DOWNLOAD_CONTEXT));\r
   if (TftpContext == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
@@ -970,8 +907,6 @@ DownloadFile (
   TftpContext->LastReportedNbOfBytes = 0;\r
 \r
   Mtftp4Token.Filename    = (UINT8*)AsciiFilePath;\r
-  Mtftp4Token.BufferSize  = FileSize;\r
-  Mtftp4Token.Buffer      = Buffer;\r
   Mtftp4Token.CheckPacket = CheckPacket;\r
   Mtftp4Token.Context     = (VOID*)TftpContext;\r
   Mtftp4Token.OptionCount = 0;\r
@@ -1000,14 +935,41 @@ DownloadFile (
     mTftpHiiHandle, FilePath\r
     );\r
 \r
+  //\r
+  // OPEN FILE\r
+  //\r
+  if (!EFI_ERROR (ShellFileExists (mLocalFilePath))) {\r
+    ShellDeleteFileByName (mLocalFilePath);\r
+  }\r
+\r
+  Status = ShellOpenFileByName (\r
+              mLocalFilePath,\r
+              &mFileHandle,\r
+              EFI_FILE_MODE_CREATE |\r
+              EFI_FILE_MODE_WRITE  |\r
+              EFI_FILE_MODE_READ,\r
+              0\r
+              );\r
+  if (EFI_ERROR (Status)) {\r
+    ShellPrintHiiEx (\r
+      -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),\r
+      mTftpHiiHandle, L"tftp", mLocalFilePath\r
+    );\r
+    goto Error;\r
+  }\r
+\r
   Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token);\r
   ShellPrintHiiEx (\r
     -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF),\r
     mTftpHiiHandle\r
     );\r
 \r
-Error :\r
+  //\r
+  // CLOSE FILE\r
+  //\r
+  ShellCloseFile (&mFileHandle);\r
 \r
+Error :\r
   if (TftpContext != NULL) {\r
     FreePool (TftpContext);\r
   }\r
@@ -1016,14 +978,7 @@ Error :
     FreePool (Mtftp4Token.OptionList);\r
   }\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    gBS->FreePages (PagesAddress, EFI_SIZE_TO_PAGES (FileSize));\r
-    return Status;\r
-  }\r
-\r
-  *Data = Buffer;\r
-\r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -1054,6 +1009,7 @@ CheckPacket (
   UINTN             Index;\r
   UINTN             LastStep;\r
   UINTN             Step;\r
+  UINTN             DownloadLen;\r
   EFI_STATUS        Status;\r
 \r
   if ((NTOHS (Packet->OpCode)) != EFI_MTFTP4_OPCODE_DATA) {\r
@@ -1061,17 +1017,35 @@ CheckPacket (
   }\r
 \r
   Context = (DOWNLOAD_CONTEXT*)Token->Context;\r
-  if (Context->DownloadedNbOfBytes == 0) {\r
-    ShellPrintEx (-1, -1, L"%s       0 Kb", mTftpProgressFrame);\r
-  }\r
 \r
   //\r
   // The data in the packet are prepended with two UINT16 :\r
   // . OpCode = EFI_MTFTP4_OPCODE_DATA\r
   // . Block  = the number of this block of data\r
   //\r
-  Context->DownloadedNbOfBytes += PacketLen - sizeof (Packet->OpCode)\r
-                                            - sizeof (Packet->Data.Block);\r
+  DownloadLen = (UINTN)PacketLen - sizeof (Packet->OpCode) - sizeof (Packet->Data.Block);\r
+\r
+  ShellSetFilePosition(mFileHandle, Context->DownloadedNbOfBytes);\r
+  Status = ShellWriteFile (mFileHandle, &DownloadLen, Packet->Data.Data);\r
+  if (EFI_ERROR (Status)) {\r
+    if (Context->DownloadedNbOfBytes > 0) {\r
+      ShellPrintHiiEx (\r
+        -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF),\r
+        mTftpHiiHandle\r
+      );\r
+    }\r
+    ShellPrintHiiEx (\r
+      -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_WRITE),\r
+      mTftpHiiHandle, mLocalFilePath, Status\r
+    );\r
+    return Status;\r
+  }\r
+\r
+  if (Context->DownloadedNbOfBytes == 0) {\r
+    ShellPrintEx (-1, -1, L"%s       0 Kb", mTftpProgressFrame);\r
+  }\r
+\r
+  Context->DownloadedNbOfBytes += DownloadLen;\r
   NbOfKb = Context->DownloadedNbOfBytes / 1024;\r
 \r
   Progress[0] = L'\0';\r