X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ShellPkg%2FDynamicCommand%2FTftpDynamicCommand%2FTftp.c;h=7e5c73b3daaa82b11a2e1904f841f5a85f58b32e;hb=HEAD;hp=44be6d4e76f4bd754b007ba00d024797664a684f;hpb=280f49b81170aee9176a47085b168ff3bc9fd3e7;p=mirror_edk2.git diff --git a/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.c b/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.c index 44be6d4e76..7e5c73b3da 100644 --- a/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.c +++ b/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.c @@ -5,27 +5,21 @@ Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
(C) Copyright 2015 Hewlett Packard Enterprise Development LP
- 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. + SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "Tftp.h" -#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32 -EFI_HANDLE mTftpHiiHandle; +#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 dowloading of a TFTP file. + progress in the downloading of a TFTP file. */ // Frame for the progression slider -STATIC CONST CHAR16 mTftpProgressFrame[] = L"[ ]"; +STATIC CONST CHAR16 mTftpProgressFrame[] = L"[ ]"; // Number of steps in the progression slider #define TFTP_PROGRESS_SLIDER_STEPS ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 3) @@ -39,7 +33,13 @@ STATIC CONST CHAR16 mTftpProgressFrame[] = L"[ // 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"; +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 @@ -48,7 +48,7 @@ STATIC CONST CHAR16 mTftpProgressDelete[] = L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b @param[out] Value UINT16 value @return TRUE The value was returned. - @return FALSE A parsing error occured. + @return FALSE A parsing error occurred. **/ STATIC BOOLEAN @@ -165,9 +165,7 @@ GetFileSize ( @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. + @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. @@ -183,7 +181,7 @@ DownloadFile ( IN CONST CHAR8 *AsciiFilePath, IN UINTN FileSize, IN UINT16 BlockSize, - OUT VOID **Data + IN UINT16 WindowSize ); /** @@ -208,38 +206,57 @@ CheckPacket ( IN EFI_MTFTP4_PACKET *Packet ); -EFI_MTFTP4_CONFIG_DATA DefaultMtftp4ConfigData = { +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, 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 + { + { 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. + 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}, - {NULL , TypeMax} - }; +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 +#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 - +#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. @@ -274,7 +291,6 @@ RunTftp ( CHAR8 *AsciiRemoteFilePath; UINTN FilePathSize; CONST CHAR16 *Walker; - CONST CHAR16 *LocalFilePath; EFI_MTFTP4_CONFIG_DATA Mtftp4ConfigData; EFI_HANDLE *Handles; UINTN HandleCount; @@ -284,10 +300,8 @@ RunTftp ( EFI_HANDLE Mtftp4ChildHandle; EFI_MTFTP4_PROTOCOL *Mtftp4; UINTN FileSize; - UINTN DataSize; - VOID *Data; - SHELL_FILE_HANDLE FileHandle; UINT16 BlockSize; + UINT16 WindowSize; ShellStatus = SHELL_INVALID_PARAMETER; ProblemParam = NULL; @@ -295,8 +309,8 @@ RunTftp ( AsciiRemoteFilePath = NULL; Handles = NULL; FileSize = 0; - DataSize = 0; BlockSize = MTFTP_DEFAULT_BLKSIZE; + WindowSize = MTFTP_DEFAULT_WINDOWSIZE; // // Initialize the Shell library (we must be in non-auto-init...) @@ -313,15 +327,22 @@ RunTftp ( Status = ShellCommandLineParse (ParamList, &CheckPackage, &ProblemParam, TRUE); if (EFI_ERROR (Status)) { if ((Status == EFI_VOLUME_CORRUPTED) && - (ProblemParam != NULL) ) { + (ProblemParam != NULL)) + { ShellPrintHiiEx ( - -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), mTftpHiiHandle, - L"tftp", ProblemParam + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PROBLEM), + mTftpHiiHandle, + L"tftp", + ProblemParam ); FreePool (ProblemParam); } else { ASSERT (FALSE); } + goto Error; } @@ -331,15 +352,24 @@ RunTftp ( ParamCount = ShellCommandLineGetCount (CheckPackage); if (ParamCount > 4) { ShellPrintHiiEx ( - -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), - mTftpHiiHandle, L"tftp" + -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" + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_TOO_FEW), + mTftpHiiHandle, + L"tftp" ); goto Error; } @@ -350,36 +380,44 @@ RunTftp ( // Check the host IPv4 address // ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1); - Status = NetLibStrToIp4 (ValueStr, &Mtftp4ConfigData.ServerIp); + Status = NetLibStrToIp4 (ValueStr, &Mtftp4ConfigData.ServerIp); if (EFI_ERROR (Status)) { ShellPrintHiiEx ( - -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), - mTftpHiiHandle, L"tftp", ValueStr - ); + -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; + 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); + mLocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3); } else { Walker = RemoteFilePath + StrLen (RemoteFilePath); while ((--Walker) >= RemoteFilePath) { if ((*Walker == L'\\') || - (*Walker == L'/' ) ) { + (*Walker == L'/')) + { break; } } - LocalFilePath = Walker + 1; + + mLocalFilePath = Walker + 1; } // @@ -406,6 +444,10 @@ RunTftp ( if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TryCount)) { goto Error; } + + if (Mtftp4ConfigData.TryCount == 0) { + Mtftp4ConfigData.TryCount = 6; + } } ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t"); @@ -413,11 +455,17 @@ RunTftp ( 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 - ); + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PARAM_INV), + mTftpHiiHandle, + L"tftp", + ValueStr + ); goto Error; } } @@ -427,11 +475,37 @@ RunTftp ( if (!StringToUint16 (ValueStr, &BlockSize)) { goto Error; } - if (BlockSize < MTFTP_MIN_BLKSIZE || BlockSize > MTFTP_MAX_BLKSIZE) { + + if ((BlockSize < MTFTP_MIN_BLKSIZE) || (BlockSize > MTFTP_MAX_BLKSIZE)) { ShellPrintHiiEx ( - -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), - mTftpHiiHandle, L"tftp", ValueStr - ); + -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; } } @@ -440,33 +514,41 @@ RunTftp ( // Locate all MTFTP4 Service Binding protocols // ShellStatus = SHELL_NOT_FOUND; - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiManagedNetworkServiceBindingProtocolGuid, - NULL, - &HandleCount, - &Handles - ); + 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), + -1, + -1, + NULL, + STRING_TOKEN (STR_TFTP_ERR_NO_NIC), mTftpHiiHandle - ); + ); goto Error; } for (NicNumber = 0; (NicNumber < HandleCount) && (ShellStatus != SHELL_SUCCESS); - NicNumber++) { + 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), - mTftpHiiHandle, NicNumber, Status - ); + -1, + -1, + NULL, + STRING_TOKEN (STR_TFTP_ERR_NIC_NAME), + mTftpHiiHandle, + NicNumber, + Status + ); continue; } @@ -474,6 +556,7 @@ RunTftp ( if (StrCmp (NicName, UserNicName) != 0) { continue; } + NicFound = TRUE; } @@ -482,81 +565,68 @@ RunTftp ( &gEfiMtftp4ServiceBindingProtocolGuid, &gEfiMtftp4ProtocolGuid, &Mtftp4ChildHandle, - (VOID**)&Mtftp4 + (VOID **)&Mtftp4 ); if (EFI_ERROR (Status)) { ShellPrintHiiEx ( - -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_OPEN_PROTOCOL), - mTftpHiiHandle, NicName, Status - ); + -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 - ); + -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, &Data); - if (EFI_ERROR (Status)) { - ShellPrintHiiEx ( - -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD), - mTftpHiiHandle, RemoteFilePath, NicName, Status - ); + -1, + -1, + NULL, + STRING_TOKEN (STR_TFTP_ERR_FILE_SIZE), + mTftpHiiHandle, + RemoteFilePath, + NicName, + Status + ); goto NextHandle; } - DataSize = FileSize; - - if (!EFI_ERROR (ShellFileExists (LocalFilePath))) { - ShellDeleteFileByName (LocalFilePath); - } - - Status = ShellOpenFileByName ( - LocalFilePath, - &FileHandle, - EFI_FILE_MODE_CREATE | - EFI_FILE_MODE_WRITE | - EFI_FILE_MODE_READ, - 0 - ); + Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, BlockSize, WindowSize); if (EFI_ERROR (Status)) { ShellPrintHiiEx ( - -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), - mTftpHiiHandle, L"tftp", LocalFilePath - ); + -1, + -1, + NULL, + STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD), + mTftpHiiHandle, + RemoteFilePath, + NicName, + Status + ); 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), - mTftpHiiHandle, LocalFilePath, Status - ); - } - ShellCloseFile (&FileHandle); + ShellStatus = SHELL_SUCCESS; - NextHandle: - - if (Data != NULL) { - gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Data, EFI_SIZE_TO_PAGES (DataSize)); - } +NextHandle: CloseProtocolAndDestroyServiceChild ( ControllerHandle, @@ -568,21 +638,30 @@ RunTftp ( if ((UserNicName != NULL) && (!NicFound)) { ShellPrintHiiEx ( - -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND), - mTftpHiiHandle, UserNicName - ); + -1, + -1, + NULL, + STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND), + mTftpHiiHandle, + UserNicName + ); } - Error: +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; } @@ -593,7 +672,7 @@ RunTftp ( @param[out] Value UINT16 value @return TRUE The value was returned. - @return FALSE A parsing error occured. + @return FALSE A parsing error occurred. **/ STATIC BOOLEAN @@ -607,9 +686,14 @@ StringToUint16 ( Val = ShellStrToUintn (ValueStr); if (Val > MAX_UINT16) { ShellPrintHiiEx ( - -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), - mTftpHiiHandle, L"tftp", ValueStr - ); + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PARAM_INV), + mTftpHiiHandle, + L"tftp", + ValueStr + ); return FALSE; } @@ -653,7 +737,7 @@ GetNicName ( &gEfiManagedNetworkServiceBindingProtocolGuid, &gEfiManagedNetworkProtocolGuid, &MnpHandle, - (VOID**)&Mnp + (VOID **)&Mnp ); if (EFI_ERROR (Status)) { goto Error; @@ -669,7 +753,7 @@ GetNicName ( IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH, SnpMode.IfType == NET_IFTYPE_ETHERNET ? L"eth%d" : - L"unk%d" , + L"unk%d", NicNumber ); @@ -721,12 +805,12 @@ CreateServiceChildAndOpenProtocol ( EFI_STATUS Status; *ChildHandle = NULL; - Status = NetLibCreateServiceChild ( - ControllerHandle, - gImageHandle, - ServiceBindingProtocolGuid, - ChildHandle - ); + Status = NetLibCreateServiceChild ( + ControllerHandle, + gImageHandle, + ServiceBindingProtocolGuid, + ChildHandle + ); if (!EFI_ERROR (Status)) { Status = gBS->OpenProtocol ( *ChildHandle, @@ -818,21 +902,21 @@ GetFileSize ( UINT32 OptCnt; UINT8 OptBuf[128]; - ReqOpt[0].OptionStr = (UINT8*)"tsize"; - OptBuf[0] = '0'; - OptBuf[1] = 0; - ReqOpt[0].ValueStr = OptBuf; + 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 - ); + Mtftp4, + NULL, + (UINT8 *)FilePath, + NULL, + 1, + ReqOpt, + &PktLen, + &Packet + ); if (EFI_ERROR (Status)) { goto Error; @@ -842,7 +926,7 @@ GetFileSize ( Mtftp4, PktLen, Packet, - (UINT32 *) &OptCnt, + (UINT32 *)&OptCnt, &TableOfOptions ); if (EFI_ERROR (Status)) { @@ -855,16 +939,18 @@ GetFileSize ( *FileSize = AsciiStrDecimalToUintn ((CHAR8 *)Option->ValueStr); break; } + OptCnt--; Option++; } + FreePool (TableOfOptions); if (OptCnt == 0) { Status = EFI_UNSUPPORTED; } -Error : +Error: return Status; } @@ -878,9 +964,7 @@ Error : @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. + @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. @@ -896,82 +980,112 @@ DownloadFile ( IN CONST CHAR8 *AsciiFilePath, IN UINTN FileSize, IN UINT16 BlockSize, - OUT VOID **Data + IN UINT16 WindowSize ) { - 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; - } + EFI_STATUS Status; + DOWNLOAD_CONTEXT *TftpContext; + EFI_MTFTP4_TOKEN Mtftp4Token; + UINT8 BlksizeBuf[10]; + UINT8 WindowsizeBuf[10]; + + ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN)); - Buffer = (VOID*)(UINTN)PagesAddress; TftpContext = AllocatePool (sizeof (DOWNLOAD_CONTEXT)); if (TftpContext == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } - TftpContext->FileSize = FileSize; + + 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.Filename = (UINT8 *)AsciiFilePath; Mtftp4Token.CheckPacket = CheckPacket; - Mtftp4Token.Context = (VOID*)TftpContext; + 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) { - ReqOpt.OptionStr = (UINT8 *) "blksize"; - AsciiSPrint ((CHAR8 *)OptBuf, sizeof (OptBuf), "%d", BlockSize); - ReqOpt.ValueStr = OptBuf; + Mtftp4Token.OptionList[Mtftp4Token.OptionCount].OptionStr = (UINT8 *)"blksize"; + AsciiSPrint ((CHAR8 *)BlksizeBuf, sizeof (BlksizeBuf), "%d", BlockSize); + Mtftp4Token.OptionList[Mtftp4Token.OptionCount].ValueStr = BlksizeBuf; + Mtftp4Token.OptionCount++; + } - Mtftp4Token.OptionCount = 1; - Mtftp4Token.OptionList = &ReqOpt; + 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 + -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), + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_CRLF), mTftpHiiHandle ); -Error : + // + // CLOSE FILE + // + ShellCloseFile (&mFileHandle); - if (TftpContext == NULL) { +Error: + if (TftpContext != NULL) { FreePool (TftpContext); } - if (EFI_ERROR (Status)) { - gBS->FreePages (PagesAddress, EFI_SIZE_TO_PAGES (FileSize)); - return Status; + if (Mtftp4Token.OptionList != NULL) { + FreePool (Mtftp4Token.OptionList); } - *Data = Buffer; - - return EFI_SUCCESS; + return Status; } /** @@ -1002,29 +1116,57 @@ CheckPacket ( 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; - if (Context->DownloadedNbOfBytes == 0) { - ShellPrintEx (-1, -1, L"%s 0 Kb", mTftpProgressFrame); - } + 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 // - Context->DownloadedNbOfBytes += PacketLen - sizeof (Packet->OpCode) - - sizeof (Packet->Data.Block); - NbOfKb = Context->DownloadedNbOfBytes / 1024; + 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; + LastStep = (Context->LastReportedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize; + Step = (Context->DownloadedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize; if (Step <= LastStep) { return EFI_SUCCESS; @@ -1033,12 +1175,14 @@ CheckPacket ( ShellPrintEx (-1, -1, L"%s", mTftpProgressDelete); Status = StrCpyS (Progress, TFTP_PROGRESS_MESSAGE_SIZE, mTftpProgressFrame); - if (EFI_ERROR(Status)) { + if (EFI_ERROR (Status)) { return Status; } + for (Index = 1; Index < Step; Index++) { Progress[Index] = L'='; } + Progress[Step] = L'>'; UnicodeSPrint ( @@ -1055,20 +1199,20 @@ CheckPacket ( } /** - Retrive HII package list from ImageHandle and publish to HII database. + Retrieve HII package list from ImageHandle and publish to HII database. @param ImageHandle The image handle of the process. @return HII handle. **/ -EFI_HANDLE +EFI_HII_HANDLE InitializeHiiPackage ( - EFI_HANDLE ImageHandle + EFI_HANDLE ImageHandle ) { - EFI_STATUS Status; - EFI_HII_PACKAGE_LIST_HEADER *PackageList; - EFI_HANDLE HiiHandle; + EFI_STATUS Status; + EFI_HII_PACKAGE_LIST_HEADER *PackageList; + EFI_HII_HANDLE HiiHandle; // // Retrieve HII package list from ImageHandle @@ -1099,5 +1243,6 @@ InitializeHiiPackage ( if (EFI_ERROR (Status)) { return NULL; } + return HiiHandle; }