Discussion:
[edk2] [PATCH V2] ShellPkg: Add optional 'tftp' EFI Shell command.
Olivier Martin
2015-07-15 15:12:25 UTC
Permalink
From: Ronald Cron <***@arm.com>

This 'tftp' command allows to download a file from a TFTP server.
A specific network interface can be chosen in case there are multiple
interfaces.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ronald Cron <***@arm.com>
Reviewed-by: Olivier Martin <***@arm.com>
---
ShellPkg/Include/Guid/ShellLibHiiGuid.h | 7 +
ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c | 880 +++++++++++++++++++++
.../UefiShellTftpCommandLib.c | 97 +++
.../UefiShellTftpCommandLib.h | 63 ++
.../UefiShellTftpCommandLib.inf | 61 ++
.../UefiShellTftpCommandLib.uni | Bin 0 -> 8748 bytes
ShellPkg/ShellPkg.dec | 1 +
ShellPkg/ShellPkg.dsc | 3 +
8 files changed, 1112 insertions(+)
create mode 100644 ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c
create mode 100644 ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.c
create mode 100644 ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.h
create mode 100644 ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf
create mode 100644 ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.uni

diff --git a/ShellPkg/Include/Guid/ShellLibHiiGuid.h b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
index dc694f2..62c2e72 100644
--- a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
+++ b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
@@ -54,6 +54,12 @@
{ \
0xf3d301bb, 0xf4a5, 0x45a8, { 0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae } \
}
+#define SHELL_TFTP_HII_GUID \
+ { \
+ 0x738a9314, 0x82c1, 0x4592, { 0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2, 0x0e, 0xd4 } \
+ }
+
+
#define SHELL_BCFG_HII_GUID \
{ \
0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6 } \
@@ -67,6 +73,7 @@ extern EFI_GUID gShellLevel1HiiGuid;
extern EFI_GUID gShellLevel2HiiGuid;
extern EFI_GUID gShellLevel3HiiGuid;
extern EFI_GUID gShellNetwork1HiiGuid;
+extern EFI_GUID gShellTftpHiiGuid;
extern EFI_GUID gShellBcfgHiiGuid;

#endif
diff --git a/ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c b/ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c
new file mode 100644
index 0000000..b872afd
--- /dev/null
+++ b/ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c
@@ -0,0 +1,880 @@
+/** @file
+ The implementation for the 'tftp' Shell command.
+
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<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"
+
+/*
+ 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";
+
+STATIC BOOLEAN StringToUint16 (
+ IN CONST CHAR16 *ValueStr,
+ OUT UINT16 *Value
+ );
+
+STATIC EFI_STATUS GetNicName (
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN Index,
+ OUT CHAR16 *NicName
+ );
+
+STATIC EFI_STATUS CreateServiceChildAndOpenProtocol (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_GUID *ServiceBindingProtocolGuid,
+ IN EFI_GUID *ProtocolGuid,
+ OUT EFI_HANDLE *ChildHandle,
+ OUT VOID **Interface
+ );
+
+STATIC VOID CloseProtocolAndDestroyServiceChild (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_GUID *ServiceBindingProtocolGuid,
+ IN EFI_GUID *ProtocolGuid,
+ IN EFI_HANDLE ChildHandle
+ );
+
+STATIC EFI_STATUS GetFileSize (
+ IN EFI_MTFTP4_PROTOCOL *Mtftp4,
+ IN CONST CHAR8 *FilePath,
+ OUT UINTN *FileSize
+ );
+
+STATIC EFI_STATUS DownloadFile (
+ IN EFI_MTFTP4_PROTOCOL *Mtftp4,
+ IN CONST CHAR16 *FilePath,
+ IN CONST CHAR8 *AsciiFilePath,
+ IN UINTN FileSize,
+ OUT VOID **Data
+ );
+
+STATIC EFI_STATUS 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},
+ {NULL , TypeMax}
+ };
+
+/**
+ 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;
+ CONST CHAR16 *Walker;
+ CONST CHAR16 *LocalFilePath;
+ EFI_MTFTP4_CONFIG_DATA Mtftp4ConfigData;
+ EFI_HANDLE *Handles;
+ UINTN HandleCount;
+ UINTN NicNumber;
+ CHAR16 NicName[IP4_NIC_NAME_LENGTH];
+ EFI_HANDLE ControllerHandle;
+ EFI_HANDLE Mtftp4ChildHandle;
+ EFI_MTFTP4_PROTOCOL *Mtftp4;
+ UINTN FileSize;
+ VOID *Data;
+ SHELL_FILE_HANDLE FileHandle;
+
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ ProblemParam = NULL;
+ NicFound = FALSE;
+ AsciiRemoteFilePath = NULL;
+ Handles = NULL;
+
+ //
+ // 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;
+ }
+
+ Mtftp4ConfigData = DefaultMtftp4ConfigData;
+
+ //
+ // 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);
+ AsciiRemoteFilePath = AllocatePool (
+ (StrLen (RemoteFilePath) + 1) * sizeof (CHAR8)
+ );
+ if (AsciiRemoteFilePath == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ UnicodeStrToAsciiStr (RemoteFilePath, AsciiRemoteFilePath);
+
+ 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;
+ }
+ }
+
+ //
+ // 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, &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 == FALSE)) {
+ 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 = 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_NIC_NAME_LENGTH bytes 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_NIC_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[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,
+ OUT VOID **Data
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PagesAddress;
+ VOID *Buffer;
+ DOWNLOAD_CONTEXT *TftpContext;
+ EFI_MTFTP4_TOKEN Mtftp4Token;
+
+ // 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;
+
+ 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
+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];
+ UINT64 NbOfKb;
+ UINTN Index;
+ UINTN LastStep;
+ UINTN Step;
+
+ 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);
+
+ StrCpy (Progress, mTftpProgressFrame);
+ 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;
+}
diff --git a/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.c b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.c
new file mode 100644
index 0000000..22c81b8
--- /dev/null
+++ b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.c
@@ -0,0 +1,97 @@
+/** @file
+ Main file for NULL named library for 'tftp' Shell command functions.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<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"
+
+CONST CHAR16 gShellTftpFileName[] = L"ShellCommand";
+EFI_HANDLE gShellTftpHiiHandle = NULL;
+
+/**
+ Return the file name of the help text file if not using HII.
+
+ @return The string pointer to the file name.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameTftp (
+ VOID
+ )
+{
+ return gShellTftpFileName;
+}
+
+/**
+ Constructor for the Shell Tftp Command library.
+
+ Install the handlers for Tftp UEFI Shell command.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+
+ @retval EFI_SUCCESS The Shell command handlers were installed sucessfully.
+ @retval EFI_UNSUPPORTED The Shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ShellTftpCommandLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ gShellTftpHiiHandle = NULL;
+
+ //
+ // check our bit of the profiles mask
+ //
+ if ((PcdGet8 (PcdShellProfileMask) & BIT3) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ gShellTftpHiiHandle = HiiAddPackages (
+ &gShellTftpHiiGuid, gImageHandle,
+ UefiShellTftpCommandLibStrings, NULL
+ );
+ if (gShellTftpHiiHandle == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Install our Shell command handler
+ //
+ ShellCommandRegisterCommandName (
+ L"tftp", ShellCommandRunTftp, ShellCommandGetManFileNameTftp, 0,
+ L"tftp", TRUE , gShellTftpHiiHandle, STRING_TOKEN (STR_GET_HELP_TFTP)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+ShellTftpCommandLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellTftpHiiHandle != NULL) {
+ HiiRemovePackages (gShellTftpHiiHandle);
+ }
+ return EFI_SUCCESS;
+}
diff --git a/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.h b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.h
new file mode 100644
index 0000000..a73b86c
--- /dev/null
+++ b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.h
@@ -0,0 +1,63 @@
+/** @file
+ header file for NULL named library for 'tftp' Shell command functions.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<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.
+
+**/
+
+#ifndef _UEFI_SHELL_TFTP_COMMAND_LIB_H_
+#define _UEFI_SHELL_TFTP_COMMAND_LIB_H_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/ShellLibHiiGuid.h>
+#include <Guid/NicIp4ConfigNvData.h>
+
+#include <Protocol/ServiceBinding.h>
+#include <Protocol/Mtftp4.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/NetLib.h>
+#include <Library/PrintLib.h>
+
+extern EFI_HANDLE gShellTftpHiiHandle;
+
+typedef struct {
+ UINT64 FileSize;
+ UINT64 DownloadedNbOfBytes;
+ UINT64 LastReportedNbOfBytes;
+} DOWNLOAD_CONTEXT;
+
+/**
+ 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).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTftp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif /* _UEFI_SHELL_TFTP_COMMAND_LIB_H_ */
diff --git a/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf
new file mode 100644
index 0000000..43b367d
--- /dev/null
+++ b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf
@@ -0,0 +1,61 @@
+## @file
+# Provides Shell 'tftp' command functions
+#
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved. <BR>
+# Copyright (c) 2015, ARM Ltd. All rights reserved.<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.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellTftpCommandLib
+ FILE_GUID = D2B61A25-9835-4E5D-906A-15615E1FF668
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellTftpCommandLibConstructor
+ DESTRUCTOR = ShellTftpCommandLibDestructor
+
+[Sources.common]
+ UefiShellTftpCommandLib.uni
+ UefiShellTftpCommandLib.c
+ UefiShellTftpCommandLib.h
+ Tftp.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ PcdLib
+ HiiLib
+ FileHandleLib
+ NetLib
+
+[Pcd]
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES
+
+[Protocols]
+ gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES
+ gEfiMtftp4ServiceBindingProtocolGuid ## CONSUMES
+
+[Guids]
+ gShellTftpHiiGuid ## CONSUMES ## HII
diff --git a/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.uni b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.uni
new file mode 100644
index 0000000000000000000000000000000000000000..607a3602d2a3aad30619c0844162e7399c0aba9a
GIT binary patch
literal 8748
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
Hj_Ug#{{Kd#

literal 0
HcmV?d00001

diff --git a/ShellPkg/ShellPkg.dec b/ShellPkg/ShellPkg.dec
index 2b1d128..32c0aff 100644
--- a/ShellPkg/ShellPkg.dec
+++ b/ShellPkg/ShellPkg.dec
@@ -53,6 +53,7 @@
gShellLevel2HiiGuid = {0xf95a7ccc, 0x4c55, 0x4426, {0xa7, 0xb4, 0xdc, 0x89, 0x61, 0x95, 0xb, 0xae}}
gShellLevel3HiiGuid = {0x4344558d, 0x4ef9, 0x4725, {0xb1, 0xe4, 0x33, 0x76, 0xe8, 0xd6, 0x97, 0x4f}}
gShellNetwork1HiiGuid = {0xf3d301bb, 0xf4a5, 0x45a8, {0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae}}
+ gShellTftpHiiGuid = {0x738a9314, 0x82c1, 0x4592, {0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2, 0x0e, 0xd4}}
gShellBcfgHiiGuid = {0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6}}

[Protocols]
diff --git a/ShellPkg/ShellPkg.dsc b/ShellPkg/ShellPkg.dsc
index 9d54acc..c2ce4f9 100644
--- a/ShellPkg/ShellPkg.dsc
+++ b/ShellPkg/ShellPkg.dsc
@@ -98,6 +98,9 @@
!ifdef $(INCLUDE_DP)
NULL|ShellPkg/Library/UefiDpLib/UefiDpLib.inf
!endif #$(INCLUDE_DP)
+!ifdef $(INCLUDE_TFTP_COMMAND)
+ NULL|ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf
+!endif #$(INCLUDE_TFTP_COMMAND)
!endif #$(NO_SHELL_PROFILES)
}
--
2.1.1
Carsey, Jaben
2015-07-15 15:31:46 UTC
Permalink
Looks good to me.
-----Original Message-----
Sent: Wednesday, July 15, 2015 8:12 AM
To: Carsey, Jaben
Subject: [PATCH V2] ShellPkg: Add optional 'tftp' EFI Shell command.
Importance: High
This 'tftp' command allows to download a file from a TFTP server.
A specific network interface can be chosen in case there are multiple
interfaces.
Contributed-under: TianoCore Contribution Agreement 1.0
---
ShellPkg/Include/Guid/ShellLibHiiGuid.h | 7 +
ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c | 880
+++++++++++++++++++++
.../UefiShellTftpCommandLib.c | 97 +++
.../UefiShellTftpCommandLib.h | 63 ++
.../UefiShellTftpCommandLib.inf | 61 ++
.../UefiShellTftpCommandLib.uni | Bin 0 -> 8748 bytes
ShellPkg/ShellPkg.dec | 1 +
ShellPkg/ShellPkg.dsc | 3 +
8 files changed, 1112 insertions(+)
create mode 100644 ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c
create mode 100644
ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.c
create mode 100644
ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.h
create mode 100644
ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf
create mode 100644
ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.uni
diff --git a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
index dc694f2..62c2e72 100644
--- a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
+++ b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
@@ -54,6 +54,12 @@
{ \
0xf3d301bb, 0xf4a5, 0x45a8, { 0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae } \
}
+#define SHELL_TFTP_HII_GUID \
+ { \
+ 0x738a9314, 0x82c1, 0x4592, { 0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2, 0x0e, 0xd4 } \
+ }
+
+
#define SHELL_BCFG_HII_GUID \
{ \
0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6 } \
@@ -67,6 +73,7 @@ extern EFI_GUID gShellLevel1HiiGuid;
extern EFI_GUID gShellLevel2HiiGuid;
extern EFI_GUID gShellLevel3HiiGuid;
extern EFI_GUID gShellNetwork1HiiGuid;
+extern EFI_GUID gShellTftpHiiGuid;
extern EFI_GUID gShellBcfgHiiGuid;
#endif
diff --git a/ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c
b/ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c
new file mode 100644
index 0000000..b872afd
--- /dev/null
+++ b/ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c
@@ -0,0 +1,880 @@
+ The implementation for the 'tftp' Shell command.
+
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<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"
+
+/*
+ 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
+// 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)
+
+// (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 BOOLEAN StringToUint16 (
+ IN CONST CHAR16 *ValueStr,
+ OUT UINT16 *Value
+ );
+
+STATIC EFI_STATUS GetNicName (
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN Index,
+ OUT CHAR16 *NicName
+ );
+
+STATIC EFI_STATUS CreateServiceChildAndOpenProtocol (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_GUID *ServiceBindingProtocolGuid,
+ IN EFI_GUID *ProtocolGuid,
+ OUT EFI_HANDLE *ChildHandle,
+ OUT VOID **Interface
+ );
+
+STATIC VOID CloseProtocolAndDestroyServiceChild (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_GUID *ServiceBindingProtocolGuid,
+ IN EFI_GUID *ProtocolGuid,
+ IN EFI_HANDLE ChildHandle
+ );
+
+STATIC EFI_STATUS GetFileSize (
+ IN EFI_MTFTP4_PROTOCOL *Mtftp4,
+ IN CONST CHAR8 *FilePath,
+ OUT UINTN *FileSize
+ );
+
+STATIC EFI_STATUS DownloadFile (
+ IN EFI_MTFTP4_PROTOCOL *Mtftp4,
+ IN CONST CHAR16 *FilePath,
+ IN CONST CHAR8 *AsciiFilePath,
+ IN UINTN FileSize,
+ OUT VOID **Data
+ );
+
+STATIC EFI_STATUS 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},
+ {NULL , TypeMax}
+ };
+
+/**
+ Function for 'tftp' command.
+
+
+ not valid.
+ 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;
+ CONST CHAR16 *Walker;
+ CONST CHAR16 *LocalFilePath;
+ EFI_MTFTP4_CONFIG_DATA Mtftp4ConfigData;
+ EFI_HANDLE *Handles;
+ UINTN HandleCount;
+ UINTN NicNumber;
+ CHAR16 NicName[IP4_NIC_NAME_LENGTH];
+ EFI_HANDLE ControllerHandle;
+ EFI_HANDLE Mtftp4ChildHandle;
+ EFI_MTFTP4_PROTOCOL *Mtftp4;
+ UINTN FileSize;
+ VOID *Data;
+ SHELL_FILE_HANDLE FileHandle;
+
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ ProblemParam = NULL;
+ NicFound = FALSE;
+ AsciiRemoteFilePath = NULL;
+ Handles = NULL;
+
+ //
+ // 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;
+ }
+
+ Mtftp4ConfigData = DefaultMtftp4ConfigData;
+
+ //
+ // 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);
+ AsciiRemoteFilePath = AllocatePool (
+ (StrLen (RemoteFilePath) + 1) * sizeof (CHAR8)
+ );
+ if (AsciiRemoteFilePath == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ UnicodeStrToAsciiStr (RemoteFilePath, AsciiRemoteFilePath);
+
+ 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;
+ }
+ }
+
+ //
+ // 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, &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);
+
+
+ if (Data != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Data,
EFI_SIZE_TO_PAGES (FileSize));
+ }
+
+ CloseProtocolAndDestroyServiceChild (
+ ControllerHandle,
+ &gEfiMtftp4ServiceBindingProtocolGuid,
+ &gEfiMtftp4ProtocolGuid,
+ Mtftp4ChildHandle
+ );
+ }
+
+ if ((UserNicName != NULL) && (NicFound == FALSE)) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND),
+ gShellTftpHiiHandle, UserNicName
+ );
+ }
+
+
+ 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
+
+
+**/
+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 = Val;
+ return TRUE;
+}
+
+/**
+ Get the name of the NIC.
+
+ The memory area has to be at least
+ IP4_NIC_NAME_LENGTH bytes wide.
+
+ 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_NIC_NAME_LENGTH,
+ SnpMode.IfType == NET_IFTYPE_ETHERNET ?
+ L"unk%d" ,
+ NicNumber
+ );
+
+ Status = EFI_SUCCESS;
+
+
+ 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.
+
+ service to be created.
+ created child is returned. NULL is
+ returned in case of error.
+ protocol interface is returned in
+ case of success.
+
+ 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.
+
+ service 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.
+
+ bytes.
+
+ (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;
+ }
+
+
+ return Status;
+}
+
+/**
+ Worker function that download the data of a file from a TFTP server given
+ the path of the file and its size.
+
+ where the data of the file were downloaded in
+ case of success.
+
+ (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,
+ OUT VOID **Data
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PagesAddress;
+ VOID *Buffer;
+ DOWNLOAD_CONTEXT *TftpContext;
+ EFI_MTFTP4_TOKEN Mtftp4Token;
+
+ // 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;
+
+ 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
+ );
+
+
+ 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.
+
+
+
+**/
+STATIC
+EFI_STATUS
+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];
+ UINT64 NbOfKb;
+ UINTN Index;
+ UINTN LastStep;
+ UINTN Step;
+
+ 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);
+ }
+
+ //
+ // . 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);
+
+ StrCpy (Progress, mTftpProgressFrame);
+ 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;
+}
diff --git
a/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.c
b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.c
new file mode 100644
index 0000000..22c81b8
--- /dev/null
+++
b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.c
@@ -0,0 +1,97 @@
+ Main file for NULL named library for 'tftp' Shell command functions.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<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"
+
+CONST CHAR16 gShellTftpFileName[] = L"ShellCommand";
+EFI_HANDLE gShellTftpHiiHandle = NULL;
+
+/**
+ Return the file name of the help text file if not using HII.
+
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameTftp (
+ VOID
+ )
+{
+ return gShellTftpFileName;
+}
+
+/**
+ Constructor for the Shell Tftp Command library.
+
+ Install the handlers for Tftp UEFI Shell command.
+
+
+**/
+EFI_STATUS
+EFIAPI
+ShellTftpCommandLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ gShellTftpHiiHandle = NULL;
+
+ //
+ // check our bit of the profiles mask
+ //
+ if ((PcdGet8 (PcdShellProfileMask) & BIT3) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ gShellTftpHiiHandle = HiiAddPackages (
+ &gShellTftpHiiGuid, gImageHandle,
+ UefiShellTftpCommandLibStrings, NULL
+ );
+ if (gShellTftpHiiHandle == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Install our Shell command handler
+ //
+ ShellCommandRegisterCommandName (
+ L"tftp", ShellCommandRunTftp, ShellCommandGetManFileNameTftp, 0,
+ L"tftp", TRUE , gShellTftpHiiHandle, STRING_TOKEN
(STR_GET_HELP_TFTP)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Destructor for the library. free any resources.
+
+**/
+EFI_STATUS
+EFIAPI
+ShellTftpCommandLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellTftpHiiHandle != NULL) {
+ HiiRemovePackages (gShellTftpHiiHandle);
+ }
+ return EFI_SUCCESS;
+}
diff --git
a/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.h
b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.h
new file mode 100644
index 0000000..a73b86c
--- /dev/null
+++
b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.h
@@ -0,0 +1,63 @@
+ header file for NULL named library for 'tftp' Shell command functions.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<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.
+
+**/
+
+#ifndef _UEFI_SHELL_TFTP_COMMAND_LIB_H_
+#define _UEFI_SHELL_TFTP_COMMAND_LIB_H_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/ShellLibHiiGuid.h>
+#include <Guid/NicIp4ConfigNvData.h>
+
+#include <Protocol/ServiceBinding.h>
+#include <Protocol/Mtftp4.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/NetLib.h>
+#include <Library/PrintLib.h>
+
+extern EFI_HANDLE gShellTftpHiiHandle;
+
+typedef struct {
+ UINT64 FileSize;
+ UINT64 DownloadedNbOfBytes;
+ UINT64 LastReportedNbOfBytes;
+} DOWNLOAD_CONTEXT;
+
+/**
+ Function for 'tftp' command.
+
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTftp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif /* _UEFI_SHELL_TFTP_COMMAND_LIB_H_ */
diff --git
a/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf
b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf
new file mode 100644
index 0000000..43b367d
--- /dev/null
+++
b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf
@@ -0,0 +1,61 @@
+# Provides Shell 'tftp' command functions
+#
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved. <BR>
+# Copyright (c) 2015, ARM Ltd. All rights reserved.<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.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellTftpCommandLib
+ FILE_GUID = D2B61A25-9835-4E5D-906A-15615E1FF668
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellTftpCommandLibConstructor
+ DESTRUCTOR = ShellTftpCommandLibDestructor
+
+[Sources.common]
+ UefiShellTftpCommandLib.uni
+ UefiShellTftpCommandLib.c
+ UefiShellTftpCommandLib.h
+ Tftp.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ PcdLib
+ HiiLib
+ FileHandleLib
+ NetLib
+
+[Pcd]
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES
+
+[Protocols]
+ gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES
+ gEfiMtftp4ServiceBindingProtocolGuid ## CONSUMES
+
+[Guids]
+ gShellTftpHiiGuid ## CONSUMES ## HII
diff --git
a/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.uni
b/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.uni
new file mode 100644
index
0000000000000000000000000000000000000000..607a3602d2a3aad30619c0844
162e7399c0aba9a
GIT binary patch
literal 8748
R_
8almZy>ePQ$dIqq)1Y#W>$al!Ro{rYC8a
zLUkbdT^(IWRu-
jnu1%
zg1Hltf$sDq71TZp$iUmZV}`qzp_6-VB{XGAtdz%+u--
&2j`YpEquO>QlNn*d_(E1+
z=V*N>oOz4DD(E}9ZngpQUm8=yG|G!{d8<)}!{;xD41j2m;}vfn$Yx8?_wjSQvM
-IV
zgb1eVI_}9n^Fol<x34RQ8rhb&joztimQ#J45&z9XOEJ<AsvUXtc6h1p<?xHnH^e
CM
zp6-KdJ4)nyS&~4urRy7-l{vPf^jA6qJJ*oe(kR9t)kdvrEKmNX-=B2{<V191D8;mB
zgkSIGNwaT=iye6tGS|er^X9*q?q7;;d;zc6k}b(1OBEw`b-
g2dHKPaNJ6pOkP=3Oi
HI8PqqXr<e0oqRwW;g)vBfjd2nObJukH(XCt}FNcO$Gz
z+boBYELK-
;&Gb|rZ>DUUNiKOKVRmMUzgf)amdowl58+AFiL)nS1FcV_Hwd%%hu_Z$
z6ZWX-
I`{GGz8I|Kp7mHY9nD|&<;(cPzPw>ufBUkOdx6b9`kfG53CW41Wl>_1KO>Kv
C<os
z6vG$dqZ2)v8cOAV9A+XCy!-
OwouOB+%LZIc`0vm6YK%EBTlKO^19mDk5%75ItMZgh
7OBeQ
zLhmcdr`F%pr}WP%)Zhg-
zbaFE>a`Bs)nER&5e`Vd1pIf|=!&mje-zV!%ET%ql5bfuE6cyX$J=bj38#9JVMz2k`
zS&mqXg~#Xw{;gPDU#h0jv7|_ttW%XeturQCsXEq;e=6-#j%q5-
e*XyC6}`1DJ^!xo
&
z=Oo)$?j$39NVmu45X<+L{aebT>#~)tTc*h&qrEvRmU6zQe%d}l+4H=rKBf{By^
OWX
z%UssLB9pDLR`4v?r!Vm;Fy02EHFsS1>e+N(eY&j_%P8G<rol^(J-
J`TqO4puW2JWt
zNlrSN%#cZ|X_dpO6J|R4yw?${o|<Ceco>rhI!}CcWPMgYbpEUdtnbK#pIXSiQc
rW%
z3LOA)no*8d_EDZ6E3Y`4OKWNcOeeG>>8!Ym<Fe9~q|qDc$CGJgU6&ShUHw
C!Q?WoV
Wh
t&PL
hwKG+
9D`W
zAIcT-
zK0DPn{2`wq=}He{JmWviFdO}5T*fc%&5##8-
&04udU}3Ixbqd1dO8`0*PvO+fVb=L
zTt{T`_RzQCoO|iLL772TiM}riS7?~>uruR2Ad6%6U-
57AHP45(vb>h>6F==(F<jGP
zw{P!Fe14mujE-
Jr{xa
zT35)<33>A5(Fn{lG0iRuv*T6dAhWvF410%!?p!VFX`|rE_M7c3XTs+U5g{oP*sS
GU
z1$)CtcCn74I3m5XEWYK!&(YKJMj0njLp1}#=o`IR$?6PqKWI-BiN&`K)7i`-p3FTR
`o!S
zQGU&13OjoaP7zC7Z%5SlJR0CFc%W5*Y4|`E`R%yU$A|^v2fbW(G-
zMD_+0pN3~p;ZL?&ve|f_mfl&pmTP)L*U&S($;4~vQHtz&4drbfyQaLmqnZ}S
m1Dd3
ZtSi8KLX49Dteq2md~qsN`9Qs
Hj_Ug#{{Kd#
literal 0
HcmV?d00001
diff --git a/ShellPkg/ShellPkg.dec b/ShellPkg/ShellPkg.dec
index 2b1d128..32c0aff 100644
--- a/ShellPkg/ShellPkg.dec
+++ b/ShellPkg/ShellPkg.dec
@@ -53,6 +53,7 @@
gShellLevel2HiiGuid = {0xf95a7ccc, 0x4c55, 0x4426, {0xa7, 0xb4, 0xdc,
0x89, 0x61, 0x95, 0xb, 0xae}}
gShellLevel3HiiGuid = {0x4344558d, 0x4ef9, 0x4725, {0xb1, 0xe4, 0x33,
0x76, 0xe8, 0xd6, 0x97, 0x4f}}
gShellNetwork1HiiGuid = {0xf3d301bb, 0xf4a5, 0x45a8, {0xb0, 0xb7,
0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae}}
+ gShellTftpHiiGuid = {0x738a9314, 0x82c1, 0x4592, {0x8f, 0xf7, 0xc1,
0xbd, 0xf1, 0xb2, 0x0e, 0xd4}}
gShellBcfgHiiGuid = {0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb,
0x12, 0xda, 0xb4, 0xa2, 0xb6}}
[Protocols]
diff --git a/ShellPkg/ShellPkg.dsc b/ShellPkg/ShellPkg.dsc
index 9d54acc..c2ce4f9 100644
--- a/ShellPkg/ShellPkg.dsc
+++ b/ShellPkg/ShellPkg.dsc
@@ -98,6 +98,9 @@
!ifdef $(INCLUDE_DP)
NULL|ShellPkg/Library/UefiDpLib/UefiDpLib.inf
!endif #$(INCLUDE_DP)
+!ifdef $(INCLUDE_TFTP_COMMAND)
+
NULL|ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib
.inf
+!endif #$(INCLUDE_TFTP_COMMAND)
!endif #$(NO_SHELL_PROFILES)
}
--
2.1.1
Loading...