2 The implementation for the 'tftp' Shell command.
4 Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
5 Copyright (c) 2015, Intel Corporation. All rights reserved. <BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php.
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "UefiShellTftpCommandLib.h"
18 #define EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32
21 Constant strings and definitions related to the message indicating the amount of
22 progress in the dowloading of a TFTP file.
25 // Frame for the progression slider
26 STATIC CONST CHAR16 mTftpProgressFrame
[] = L
"[ ]";
28 // Number of steps in the progression slider
29 #define TFTP_PROGRESS_SLIDER_STEPS ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 3)
31 // Size in number of characters plus one (final zero) of the message to
32 // indicate the progress of a TFTP download. The format is "[(progress slider:
33 // 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". There
34 // are thus the number of characters in mTftpProgressFrame[] plus 11 characters
35 // (2 // spaces, "Kb" and seven characters for the number of KBytes).
36 #define TFTP_PROGRESS_MESSAGE_SIZE ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) + 12)
38 // String to delete the TFTP progress message to be able to update it :
39 // (TFTP_PROGRESS_MESSAGE_SIZE-1) '\b'
40 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";
43 Check and convert the UINT16 option values of the 'tftp' command
45 @param[in] ValueStr Value as an Unicode encoded string
46 @param[out] Value UINT16 value
48 @return TRUE The value was returned.
49 @return FALSE A parsing error occured.
54 IN CONST CHAR16
*ValueStr
,
59 Get the name of the NIC.
61 @param[in] ControllerHandle The network physical device handle.
62 @param[in] NicNumber The network physical device number.
63 @param[out] NicName Address where to store the NIC name.
64 The memory area has to be at least
65 IP4_NIC_NAME_LENGTH bytes wide.
67 @return EFI_SUCCESS The name of the NIC was returned.
68 @return Others The creation of the child for the Managed
69 Network Service failed or the opening of
70 the Managed Network Protocol failed or
71 the operational parameters for the
72 Managed Network Protocol could not be
78 IN EFI_HANDLE ControllerHandle
,
84 Create a child for the service identified by its service binding protocol GUID
85 and get from the child the interface of the protocol identified by its GUID.
87 @param[in] ControllerHandle Controller handle.
88 @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the
89 service to be created.
90 @param[in] ProtocolGuid GUID of the protocol to be open.
91 @param[out] ChildHandle Address where the handler of the
92 created child is returned. NULL is
93 returned in case of error.
94 @param[out] Interface Address where a pointer to the
95 protocol interface is returned in
98 @return EFI_SUCCESS The child was created and the protocol opened.
99 @return Others Either the creation of the child or the opening
100 of the protocol failed.
104 CreateServiceChildAndOpenProtocol (
105 IN EFI_HANDLE ControllerHandle
,
106 IN EFI_GUID
*ServiceBindingProtocolGuid
,
107 IN EFI_GUID
*ProtocolGuid
,
108 OUT EFI_HANDLE
*ChildHandle
,
113 Close the protocol identified by its GUID on the child handle of the service
114 identified by its service binding protocol GUID, then destroy the child
117 @param[in] ControllerHandle Controller handle.
118 @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the
119 service to be destroyed.
120 @param[in] ProtocolGuid GUID of the protocol to be closed.
121 @param[in] ChildHandle Handle of the child to be destroyed.
126 CloseProtocolAndDestroyServiceChild (
127 IN EFI_HANDLE ControllerHandle
,
128 IN EFI_GUID
*ServiceBindingProtocolGuid
,
129 IN EFI_GUID
*ProtocolGuid
,
130 IN EFI_HANDLE ChildHandle
134 Worker function that gets the size in numbers of bytes of a file from a TFTP
135 server before to download the file.
137 @param[in] Mtftp4 MTFTP4 protocol interface
138 @param[in] FilePath Path of the file, ASCII encoded
139 @param[out] FileSize Address where to store the file size in number of
142 @retval EFI_SUCCESS The size of the file was returned.
143 @retval EFI_UNSUPPORTED The server does not support the "tsize" option.
144 @retval Others Error when retrieving the information from the server
145 (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes)
146 or error when parsing the response of the server.
151 IN EFI_MTFTP4_PROTOCOL
*Mtftp4
,
152 IN CONST CHAR8
*FilePath
,
157 Worker function that download the data of a file from a TFTP server given
158 the path of the file and its size.
160 @param[in] Mtftp4 MTFTP4 protocol interface
161 @param[in] FilePath Path of the file, Unicode encoded
162 @param[in] AsciiFilePath Path of the file, ASCII encoded
163 @param[in] FileSize Size of the file in number of bytes
164 @param[out] Data Address where to store the address of the buffer
165 where the data of the file were downloaded in
168 @retval EFI_SUCCESS The file was downloaded.
169 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
170 @retval Others The downloading of the file from the server failed
171 (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes).
177 IN EFI_MTFTP4_PROTOCOL
*Mtftp4
,
178 IN CONST CHAR16
*FilePath
,
179 IN CONST CHAR8
*AsciiFilePath
,
185 Update the progress of a file download
186 This procedure is called each time a new TFTP packet is received.
188 @param[in] This MTFTP4 protocol interface
189 @param[in] Token Parameters for the download of the file
190 @param[in] PacketLen Length of the packet
191 @param[in] Packet Address of the packet
193 @retval EFI_SUCCESS All packets are accepted.
199 IN EFI_MTFTP4_PROTOCOL
*This
,
200 IN EFI_MTFTP4_TOKEN
*Token
,
202 IN EFI_MTFTP4_PACKET
*Packet
205 EFI_MTFTP4_CONFIG_DATA DefaultMtftp4ConfigData
= {
206 TRUE
, // Use default setting
207 { { 0, 0, 0, 0 } }, // StationIp - Not relevant as UseDefaultSetting=TRUE
208 { { 0, 0, 0, 0 } }, // SubnetMask - Not relevant as UseDefaultSetting=TRUE
209 0, // LocalPort - Automatically assigned port number.
210 { { 0, 0, 0, 0 } }, // GatewayIp - Not relevant as UseDefaultSetting=TRUE
211 { { 0, 0, 0, 0 } }, // ServerIp - Not known yet
212 69, // InitialServerPort - Standard TFTP server port
213 6, // TryCount - Max number of retransmissions.
214 4 // TimeoutValue - Retransmission timeout in seconds.
217 STATIC CONST SHELL_PARAM_ITEM ParamList
[] = {
227 Function for 'tftp' command.
229 @param[in] ImageHandle Handle to the Image (NULL if Internal).
230 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
232 @return SHELL_SUCCESS The 'tftp' command completed successfully.
233 @return SHELL_ABORTED The Shell Library initialization failed.
234 @return SHELL_INVALID_PARAMETER At least one of the command's arguments is
236 @return SHELL_OUT_OF_RESOURCES A memory allocation failed.
237 @return SHELL_NOT_FOUND Network Interface Card not found or server
243 ShellCommandRunTftp (
244 IN EFI_HANDLE ImageHandle
,
245 IN EFI_SYSTEM_TABLE
*SystemTable
248 SHELL_STATUS ShellStatus
;
250 LIST_ENTRY
*CheckPackage
;
251 CHAR16
*ProblemParam
;
253 CONST CHAR16
*UserNicName
;
255 CONST CHAR16
*ValueStr
;
256 CONST CHAR16
*RemoteFilePath
;
257 CHAR8
*AsciiRemoteFilePath
;
258 CONST CHAR16
*Walker
;
259 CONST CHAR16
*LocalFilePath
;
260 EFI_MTFTP4_CONFIG_DATA Mtftp4ConfigData
;
264 CHAR16 NicName
[EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH
];
265 EFI_HANDLE ControllerHandle
;
266 EFI_HANDLE Mtftp4ChildHandle
;
267 EFI_MTFTP4_PROTOCOL
*Mtftp4
;
270 SHELL_FILE_HANDLE FileHandle
;
272 ShellStatus
= SHELL_INVALID_PARAMETER
;
275 AsciiRemoteFilePath
= NULL
;
279 // Initialize the Shell library (we must be in non-auto-init...)
281 Status
= ShellInitialize ();
282 if (EFI_ERROR (Status
)) {
283 ASSERT_EFI_ERROR (Status
);
284 return SHELL_ABORTED
;
288 // Parse the command line.
290 Status
= ShellCommandLineParse (ParamList
, &CheckPackage
, &ProblemParam
, TRUE
);
291 if (EFI_ERROR (Status
)) {
292 if ((Status
== EFI_VOLUME_CORRUPTED
) &&
293 (ProblemParam
!= NULL
) ) {
295 -1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellTftpHiiHandle
,
296 L
"tftp", ProblemParam
298 FreePool (ProblemParam
);
306 // Check the number of parameters
308 ParamCount
= ShellCommandLineGetCount (CheckPackage
);
309 if (ParamCount
> 4) {
311 -1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
),
312 gShellTftpHiiHandle
, L
"tftp"
316 if (ParamCount
< 3) {
318 -1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
),
319 gShellTftpHiiHandle
, L
"tftp"
324 Mtftp4ConfigData
= DefaultMtftp4ConfigData
;
327 // Check the host IPv4 address
329 ValueStr
= ShellCommandLineGetRawValue (CheckPackage
, 1);
330 Status
= NetLibStrToIp4 (ValueStr
, &Mtftp4ConfigData
.ServerIp
);
331 if (EFI_ERROR (Status
)) {
333 -1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
),
334 gShellTftpHiiHandle
, L
"tftp", ValueStr
339 RemoteFilePath
= ShellCommandLineGetRawValue (CheckPackage
, 2);
340 AsciiRemoteFilePath
= AllocatePool (
341 (StrLen (RemoteFilePath
) + 1) * sizeof (CHAR8
)
343 if (AsciiRemoteFilePath
== NULL
) {
344 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
347 UnicodeStrToAsciiStr (RemoteFilePath
, AsciiRemoteFilePath
);
349 if (ParamCount
== 4) {
350 LocalFilePath
= ShellCommandLineGetRawValue (CheckPackage
, 3);
352 Walker
= RemoteFilePath
+ StrLen (RemoteFilePath
);
353 while ((--Walker
) >= RemoteFilePath
) {
354 if ((*Walker
== L
'\\') ||
355 (*Walker
== L
'/' ) ) {
359 LocalFilePath
= Walker
+ 1;
363 // Get the name of the Network Interface Card to be used if any.
365 UserNicName
= ShellCommandLineGetValue (CheckPackage
, L
"-i");
367 ValueStr
= ShellCommandLineGetValue (CheckPackage
, L
"-l");
368 if (ValueStr
!= NULL
) {
369 if (!StringToUint16 (ValueStr
, &Mtftp4ConfigData
.LocalPort
)) {
374 ValueStr
= ShellCommandLineGetValue (CheckPackage
, L
"-r");
375 if (ValueStr
!= NULL
) {
376 if (!StringToUint16 (ValueStr
, &Mtftp4ConfigData
.InitialServerPort
)) {
381 ValueStr
= ShellCommandLineGetValue (CheckPackage
, L
"-c");
382 if (ValueStr
!= NULL
) {
383 if (!StringToUint16 (ValueStr
, &Mtftp4ConfigData
.TryCount
)) {
388 ValueStr
= ShellCommandLineGetValue (CheckPackage
, L
"-t");
389 if (ValueStr
!= NULL
) {
390 if (!StringToUint16 (ValueStr
, &Mtftp4ConfigData
.TimeoutValue
)) {
393 if (Mtftp4ConfigData
.TimeoutValue
== 0) {
395 -1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
),
396 gShellTftpHiiHandle
, L
"tftp", ValueStr
403 // Locate all MTFTP4 Service Binding protocols
405 ShellStatus
= SHELL_NOT_FOUND
;
406 Status
= gBS
->LocateHandleBuffer (
408 &gEfiManagedNetworkServiceBindingProtocolGuid
,
413 if (EFI_ERROR (Status
) || (HandleCount
== 0)) {
415 -1, -1, NULL
, STRING_TOKEN (STR_TFTP_ERR_NO_NIC
),
422 (NicNumber
< HandleCount
) && (ShellStatus
!= SHELL_SUCCESS
);
424 ControllerHandle
= Handles
[NicNumber
];
427 Status
= GetNicName (ControllerHandle
, NicNumber
, NicName
);
428 if (EFI_ERROR (Status
)) {
430 -1, -1, NULL
, STRING_TOKEN (STR_TFTP_ERR_NIC_NAME
),
431 gShellTftpHiiHandle
, NicNumber
, Status
436 if (UserNicName
!= NULL
) {
437 if (StrCmp (NicName
, UserNicName
) != 0) {
443 Status
= CreateServiceChildAndOpenProtocol (
445 &gEfiMtftp4ServiceBindingProtocolGuid
,
446 &gEfiMtftp4ProtocolGuid
,
450 if (EFI_ERROR (Status
)) {
452 -1, -1, NULL
, STRING_TOKEN (STR_TFTP_ERR_OPEN_PROTOCOL
),
453 gShellTftpHiiHandle
, NicName
, Status
458 Status
= Mtftp4
->Configure (Mtftp4
, &Mtftp4ConfigData
);
459 if (EFI_ERROR (Status
)) {
461 -1, -1, NULL
, STRING_TOKEN (STR_TFTP_ERR_CONFIGURE
),
462 gShellTftpHiiHandle
, NicName
, Status
467 Status
= GetFileSize (Mtftp4
, AsciiRemoteFilePath
, &FileSize
);
468 if (EFI_ERROR (Status
)) {
470 -1, -1, NULL
, STRING_TOKEN (STR_TFTP_ERR_FILE_SIZE
),
471 gShellTftpHiiHandle
, RemoteFilePath
, NicName
, Status
476 Status
= DownloadFile (Mtftp4
, RemoteFilePath
, AsciiRemoteFilePath
, FileSize
, &Data
);
477 if (EFI_ERROR (Status
)) {
479 -1, -1, NULL
, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD
),
480 gShellTftpHiiHandle
, RemoteFilePath
, NicName
, Status
485 if (!EFI_ERROR (ShellFileExists (LocalFilePath
))) {
486 ShellDeleteFileByName (LocalFilePath
);
489 Status
= ShellOpenFileByName (
492 EFI_FILE_MODE_CREATE
|
493 EFI_FILE_MODE_WRITE
|
497 if (EFI_ERROR (Status
)) {
499 -1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL
),
500 gShellTftpHiiHandle
, L
"tftp", LocalFilePath
505 Status
= ShellWriteFile (FileHandle
, &FileSize
, Data
);
506 if (!EFI_ERROR (Status
)) {
507 ShellStatus
= SHELL_SUCCESS
;
510 -1, -1, NULL
, STRING_TOKEN (STR_TFTP_ERR_WRITE
),
511 gShellTftpHiiHandle
, LocalFilePath
, Status
514 ShellCloseFile (&FileHandle
);
519 gBS
->FreePages ((EFI_PHYSICAL_ADDRESS
)(UINTN
)Data
, EFI_SIZE_TO_PAGES (FileSize
));
522 CloseProtocolAndDestroyServiceChild (
524 &gEfiMtftp4ServiceBindingProtocolGuid
,
525 &gEfiMtftp4ProtocolGuid
,
530 if ((UserNicName
!= NULL
) && (!NicFound
)) {
532 -1, -1, NULL
, STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND
),
533 gShellTftpHiiHandle
, UserNicName
539 ShellCommandLineFreeVarList (CheckPackage
);
540 if (AsciiRemoteFilePath
!= NULL
) {
541 FreePool (AsciiRemoteFilePath
);
543 if (Handles
!= NULL
) {
551 Check and convert the UINT16 option values of the 'tftp' command
553 @param[in] ValueStr Value as an Unicode encoded string
554 @param[out] Value UINT16 value
556 @return TRUE The value was returned.
557 @return FALSE A parsing error occured.
562 IN CONST CHAR16
*ValueStr
,
568 Val
= ShellStrToUintn (ValueStr
);
569 if (Val
> MAX_UINT16
) {
571 -1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
),
572 gShellTftpHiiHandle
, L
"tftp", ValueStr
577 *Value
= (UINT16
)Val
;
582 Get the name of the NIC.
584 @param[in] ControllerHandle The network physical device handle.
585 @param[in] NicNumber The network physical device number.
586 @param[out] NicName Address where to store the NIC name.
587 The memory area has to be at least
588 IP4_NIC_NAME_LENGTH bytes wide.
590 @return EFI_SUCCESS The name of the NIC was returned.
591 @return Others The creation of the child for the Managed
592 Network Service failed or the opening of
593 the Managed Network Protocol failed or
594 the operational parameters for the
595 Managed Network Protocol could not be
601 IN EFI_HANDLE ControllerHandle
,
607 EFI_HANDLE MnpHandle
;
608 EFI_MANAGED_NETWORK_PROTOCOL
*Mnp
;
609 EFI_SIMPLE_NETWORK_MODE SnpMode
;
611 Status
= CreateServiceChildAndOpenProtocol (
613 &gEfiManagedNetworkServiceBindingProtocolGuid
,
614 &gEfiManagedNetworkProtocolGuid
,
618 if (EFI_ERROR (Status
)) {
622 Status
= Mnp
->GetModeData (Mnp
, NULL
, &SnpMode
);
623 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_STARTED
)) {
629 EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH
,
630 SnpMode
.IfType
== NET_IFTYPE_ETHERNET
?
636 Status
= EFI_SUCCESS
;
640 if (MnpHandle
!= NULL
) {
641 CloseProtocolAndDestroyServiceChild (
643 &gEfiManagedNetworkServiceBindingProtocolGuid
,
644 &gEfiManagedNetworkProtocolGuid
,
653 Create a child for the service identified by its service binding protocol GUID
654 and get from the child the interface of the protocol identified by its GUID.
656 @param[in] ControllerHandle Controller handle.
657 @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the
658 service to be created.
659 @param[in] ProtocolGuid GUID of the protocol to be open.
660 @param[out] ChildHandle Address where the handler of the
661 created child is returned. NULL is
662 returned in case of error.
663 @param[out] Interface Address where a pointer to the
664 protocol interface is returned in
667 @return EFI_SUCCESS The child was created and the protocol opened.
668 @return Others Either the creation of the child or the opening
669 of the protocol failed.
673 CreateServiceChildAndOpenProtocol (
674 IN EFI_HANDLE ControllerHandle
,
675 IN EFI_GUID
*ServiceBindingProtocolGuid
,
676 IN EFI_GUID
*ProtocolGuid
,
677 OUT EFI_HANDLE
*ChildHandle
,
684 Status
= NetLibCreateServiceChild (
687 ServiceBindingProtocolGuid
,
690 if (!EFI_ERROR (Status
)) {
691 Status
= gBS
->OpenProtocol (
697 EFI_OPEN_PROTOCOL_GET_PROTOCOL
699 if (EFI_ERROR (Status
)) {
700 NetLibDestroyServiceChild (
703 ServiceBindingProtocolGuid
,
714 Close the protocol identified by its GUID on the child handle of the service
715 identified by its service binding protocol GUID, then destroy the child
718 @param[in] ControllerHandle Controller handle.
719 @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the
720 service to be destroyed.
721 @param[in] ProtocolGuid GUID of the protocol to be closed.
722 @param[in] ChildHandle Handle of the child to be destroyed.
727 CloseProtocolAndDestroyServiceChild (
728 IN EFI_HANDLE ControllerHandle
,
729 IN EFI_GUID
*ServiceBindingProtocolGuid
,
730 IN EFI_GUID
*ProtocolGuid
,
731 IN EFI_HANDLE ChildHandle
741 NetLibDestroyServiceChild (
744 ServiceBindingProtocolGuid
,
750 Worker function that gets the size in numbers of bytes of a file from a TFTP
751 server before to download the file.
753 @param[in] Mtftp4 MTFTP4 protocol interface
754 @param[in] FilePath Path of the file, ASCII encoded
755 @param[out] FileSize Address where to store the file size in number of
758 @retval EFI_SUCCESS The size of the file was returned.
759 @retval EFI_UNSUPPORTED The server does not support the "tsize" option.
760 @retval Others Error when retrieving the information from the server
761 (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes)
762 or error when parsing the response of the server.
767 IN EFI_MTFTP4_PROTOCOL
*Mtftp4
,
768 IN CONST CHAR8
*FilePath
,
773 EFI_MTFTP4_OPTION ReqOpt
[1];
774 EFI_MTFTP4_PACKET
*Packet
;
776 EFI_MTFTP4_OPTION
*TableOfOptions
;
777 EFI_MTFTP4_OPTION
*Option
;
781 ReqOpt
[0].OptionStr
= (UINT8
*)"tsize";
784 ReqOpt
[0].ValueStr
= OptBuf
;
786 Status
= Mtftp4
->GetInfo (
797 if (EFI_ERROR (Status
)) {
801 Status
= Mtftp4
->ParseOptions (
808 if (EFI_ERROR (Status
)) {
812 Option
= TableOfOptions
;
813 while (OptCnt
!= 0) {
814 if (AsciiStrnCmp ((CHAR8
*)Option
->OptionStr
, "tsize", 5) == 0) {
815 *FileSize
= AsciiStrDecimalToUintn ((CHAR8
*)Option
->ValueStr
);
821 FreePool (TableOfOptions
);
824 Status
= EFI_UNSUPPORTED
;
833 Worker function that download the data of a file from a TFTP server given
834 the path of the file and its size.
836 @param[in] Mtftp4 MTFTP4 protocol interface
837 @param[in] FilePath Path of the file, Unicode encoded
838 @param[in] AsciiFilePath Path of the file, ASCII encoded
839 @param[in] FileSize Size of the file in number of bytes
840 @param[out] Data Address where to store the address of the buffer
841 where the data of the file were downloaded in
844 @retval EFI_SUCCESS The file was downloaded.
845 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
846 @retval Others The downloading of the file from the server failed
847 (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes).
853 IN EFI_MTFTP4_PROTOCOL
*Mtftp4
,
854 IN CONST CHAR16
*FilePath
,
855 IN CONST CHAR8
*AsciiFilePath
,
861 EFI_PHYSICAL_ADDRESS PagesAddress
;
863 DOWNLOAD_CONTEXT
*TftpContext
;
864 EFI_MTFTP4_TOKEN Mtftp4Token
;
866 // Downloaded file can be large. BS.AllocatePages() is more faster
867 // than AllocatePool() and avoid fragmentation.
868 // The downloaded file could be an EFI application. Marking the
869 // allocated page as EfiBootServicesCode would allow to execute a
870 // potential downloaded EFI application.
871 Status
= gBS
->AllocatePages (
874 EFI_SIZE_TO_PAGES (FileSize
),
877 if (EFI_ERROR (Status
)) {
881 Buffer
= (VOID
*)(UINTN
)PagesAddress
;
882 TftpContext
= AllocatePool (sizeof (DOWNLOAD_CONTEXT
));
883 if (TftpContext
== NULL
) {
884 Status
= EFI_OUT_OF_RESOURCES
;
887 TftpContext
->FileSize
= FileSize
;
888 TftpContext
->DownloadedNbOfBytes
= 0;
889 TftpContext
->LastReportedNbOfBytes
= 0;
891 ZeroMem (&Mtftp4Token
, sizeof (EFI_MTFTP4_TOKEN
));
892 Mtftp4Token
.Filename
= (UINT8
*)AsciiFilePath
;
893 Mtftp4Token
.BufferSize
= FileSize
;
894 Mtftp4Token
.Buffer
= Buffer
;
895 Mtftp4Token
.CheckPacket
= CheckPacket
;
896 Mtftp4Token
.Context
= (VOID
*)TftpContext
;
899 -1, -1, NULL
, STRING_TOKEN (STR_TFTP_DOWNLOADING
),
900 gShellTftpHiiHandle
, FilePath
903 Status
= Mtftp4
->ReadFile (Mtftp4
, &Mtftp4Token
);
905 -1, -1, NULL
, STRING_TOKEN (STR_GEN_CRLF
),
911 if (TftpContext
== NULL
) {
912 FreePool (TftpContext
);
915 if (EFI_ERROR (Status
)) {
916 gBS
->FreePages (PagesAddress
, EFI_SIZE_TO_PAGES (FileSize
));
926 Update the progress of a file download
927 This procedure is called each time a new TFTP packet is received.
929 @param[in] This MTFTP4 protocol interface
930 @param[in] Token Parameters for the download of the file
931 @param[in] PacketLen Length of the packet
932 @param[in] Packet Address of the packet
934 @retval EFI_SUCCESS All packets are accepted.
940 IN EFI_MTFTP4_PROTOCOL
*This
,
941 IN EFI_MTFTP4_TOKEN
*Token
,
943 IN EFI_MTFTP4_PACKET
*Packet
946 DOWNLOAD_CONTEXT
*Context
;
947 CHAR16 Progress
[TFTP_PROGRESS_MESSAGE_SIZE
];
953 if ((NTOHS (Packet
->OpCode
)) != EFI_MTFTP4_OPCODE_DATA
) {
957 Context
= (DOWNLOAD_CONTEXT
*)Token
->Context
;
958 if (Context
->DownloadedNbOfBytes
== 0) {
959 ShellPrintEx (-1, -1, L
"%s 0 Kb", mTftpProgressFrame
);
963 // The data in the packet are prepended with two UINT16 :
964 // . OpCode = EFI_MTFTP4_OPCODE_DATA
965 // . Block = the number of this block of data
967 Context
->DownloadedNbOfBytes
+= PacketLen
- sizeof (Packet
->OpCode
)
968 - sizeof (Packet
->Data
.Block
);
969 NbOfKb
= Context
->DownloadedNbOfBytes
/ 1024;
972 LastStep
= (Context
->LastReportedNbOfBytes
* TFTP_PROGRESS_SLIDER_STEPS
) /
974 Step
= (Context
->DownloadedNbOfBytes
* TFTP_PROGRESS_SLIDER_STEPS
) /
976 if (Step
<= LastStep
) {
980 ShellPrintEx (-1, -1, L
"%s", mTftpProgressDelete
);
982 StrCpy (Progress
, mTftpProgressFrame
);
983 for (Index
= 1; Index
< Step
; Index
++) {
984 Progress
[Index
] = L
'=';
986 Progress
[Step
] = L
'>';
989 Progress
+ (sizeof (mTftpProgressFrame
) / sizeof (CHAR16
)) - 1,
990 sizeof (Progress
) - sizeof (mTftpProgressFrame
),
994 Context
->LastReportedNbOfBytes
= Context
->DownloadedNbOfBytes
;
996 ShellPrintEx (-1, -1, L
"%s", Progress
);