]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.c
ShellPkg: Apply uncrustify changes
[mirror_edk2.git] / ShellPkg / DynamicCommand / TftpDynamicCommand / Tftp.c
CommitLineData
68074260
RC
1/** @file\r
2 The implementation for the 'tftp' Shell command.\r
3\r
4 Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>\r
ba0014b9 5 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved. <BR>\r
6add86ab 6 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
68074260 7\r
56ba3746 8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
68074260
RC
9**/\r
10\r
09610023 11#include "Tftp.h"\r
68074260 12\r
47d20b54
MK
13#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32\r
14EFI_HII_HANDLE mTftpHiiHandle;\r
6add86ab 15\r
68074260
RC
16/*\r
17 Constant strings and definitions related to the message indicating the amount of\r
f16bd394 18 progress in the downloading of a TFTP file.\r
68074260
RC
19*/\r
20\r
21// Frame for the progression slider\r
47d20b54 22STATIC CONST CHAR16 mTftpProgressFrame[] = L"[ ]";\r
68074260
RC
23\r
24// Number of steps in the progression slider\r
25#define TFTP_PROGRESS_SLIDER_STEPS ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 3)\r
26\r
27// Size in number of characters plus one (final zero) of the message to\r
28// indicate the progress of a TFTP download. The format is "[(progress slider:\r
29// 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". There\r
30// are thus the number of characters in mTftpProgressFrame[] plus 11 characters\r
31// (2 // spaces, "Kb" and seven characters for the number of KBytes).\r
32#define TFTP_PROGRESS_MESSAGE_SIZE ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) + 12)\r
33\r
34// String to delete the TFTP progress message to be able to update it :\r
35// (TFTP_PROGRESS_MESSAGE_SIZE-1) '\b'\r
47d20b54 36STATIC CONST CHAR16 mTftpProgressDelete[] = L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";\r
68074260 37\r
b85c8fb4 38// Local File Handle\r
47d20b54 39SHELL_FILE_HANDLE mFileHandle;\r
b85c8fb4
AL
40\r
41// Path of the local file, Unicode encoded\r
47d20b54 42CONST CHAR16 *mLocalFilePath;\r
b85c8fb4 43\r
0fcf66a4
QS
44/**\r
45 Check and convert the UINT16 option values of the 'tftp' command\r
46\r
47 @param[in] ValueStr Value as an Unicode encoded string\r
48 @param[out] Value UINT16 value\r
49\r
50 @return TRUE The value was returned.\r
f16bd394 51 @return FALSE A parsing error occurred.\r
0fcf66a4 52**/\r
ba0014b9
LG
53STATIC\r
54BOOLEAN\r
0fcf66a4 55StringToUint16 (\r
68074260
RC
56 IN CONST CHAR16 *ValueStr,\r
57 OUT UINT16 *Value\r
58 );\r
59\r
0fcf66a4
QS
60/**\r
61 Get the name of the NIC.\r
62\r
63 @param[in] ControllerHandle The network physical device handle.\r
64 @param[in] NicNumber The network physical device number.\r
65 @param[out] NicName Address where to store the NIC name.\r
66 The memory area has to be at least\r
ba0014b9 67 IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH\r
6add86ab 68 double byte wide.\r
0fcf66a4
QS
69\r
70 @return EFI_SUCCESS The name of the NIC was returned.\r
71 @return Others The creation of the child for the Managed\r
72 Network Service failed or the opening of\r
73 the Managed Network Protocol failed or\r
74 the operational parameters for the\r
75 Managed Network Protocol could not be\r
76 read.\r
77**/\r
ba0014b9
LG
78STATIC\r
79EFI_STATUS\r
0fcf66a4 80GetNicName (\r
68074260 81 IN EFI_HANDLE ControllerHandle,\r
a0f2af3a 82 IN UINTN NicNumber,\r
68074260
RC
83 OUT CHAR16 *NicName\r
84 );\r
85\r
0fcf66a4
QS
86/**\r
87 Create a child for the service identified by its service binding protocol GUID\r
88 and get from the child the interface of the protocol identified by its GUID.\r
89\r
90 @param[in] ControllerHandle Controller handle.\r
91 @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the\r
92 service to be created.\r
93 @param[in] ProtocolGuid GUID of the protocol to be open.\r
94 @param[out] ChildHandle Address where the handler of the\r
95 created child is returned. NULL is\r
96 returned in case of error.\r
97 @param[out] Interface Address where a pointer to the\r
98 protocol interface is returned in\r
99 case of success.\r
100\r
101 @return EFI_SUCCESS The child was created and the protocol opened.\r
102 @return Others Either the creation of the child or the opening\r
103 of the protocol failed.\r
104**/\r
ba0014b9
LG
105STATIC\r
106EFI_STATUS\r
0fcf66a4 107CreateServiceChildAndOpenProtocol (\r
68074260
RC
108 IN EFI_HANDLE ControllerHandle,\r
109 IN EFI_GUID *ServiceBindingProtocolGuid,\r
110 IN EFI_GUID *ProtocolGuid,\r
111 OUT EFI_HANDLE *ChildHandle,\r
112 OUT VOID **Interface\r
113 );\r
114\r
0fcf66a4
QS
115/**\r
116 Close the protocol identified by its GUID on the child handle of the service\r
117 identified by its service binding protocol GUID, then destroy the child\r
118 handle.\r
119\r
120 @param[in] ControllerHandle Controller handle.\r
121 @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the\r
122 service to be destroyed.\r
123 @param[in] ProtocolGuid GUID of the protocol to be closed.\r
124 @param[in] ChildHandle Handle of the child to be destroyed.\r
125\r
126**/\r
ba0014b9
LG
127STATIC\r
128VOID\r
0fcf66a4 129CloseProtocolAndDestroyServiceChild (\r
68074260
RC
130 IN EFI_HANDLE ControllerHandle,\r
131 IN EFI_GUID *ServiceBindingProtocolGuid,\r
132 IN EFI_GUID *ProtocolGuid,\r
133 IN EFI_HANDLE ChildHandle\r
134 );\r
135\r
0fcf66a4
QS
136/**\r
137 Worker function that gets the size in numbers of bytes of a file from a TFTP\r
138 server before to download the file.\r
139\r
140 @param[in] Mtftp4 MTFTP4 protocol interface\r
141 @param[in] FilePath Path of the file, ASCII encoded\r
142 @param[out] FileSize Address where to store the file size in number of\r
143 bytes.\r
144\r
145 @retval EFI_SUCCESS The size of the file was returned.\r
146 @retval EFI_UNSUPPORTED The server does not support the "tsize" option.\r
147 @retval Others Error when retrieving the information from the server\r
148 (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes)\r
149 or error when parsing the response of the server.\r
150**/\r
ba0014b9
LG
151STATIC\r
152EFI_STATUS\r
0fcf66a4 153GetFileSize (\r
68074260
RC
154 IN EFI_MTFTP4_PROTOCOL *Mtftp4,\r
155 IN CONST CHAR8 *FilePath,\r
156 OUT UINTN *FileSize\r
157 );\r
158\r
0fcf66a4
QS
159/**\r
160 Worker function that download the data of a file from a TFTP server given\r
161 the path of the file and its size.\r
162\r
163 @param[in] Mtftp4 MTFTP4 protocol interface\r
164 @param[in] FilePath Path of the file, Unicode encoded\r
165 @param[in] AsciiFilePath Path of the file, ASCII encoded\r
166 @param[in] FileSize Size of the file in number of bytes\r
2be45bfe 167 @param[in] BlockSize Value of the TFTP blksize option\r
a7ab1c31 168 @param[in] WindowSize Value of the TFTP window size option\r
0fcf66a4
QS
169\r
170 @retval EFI_SUCCESS The file was downloaded.\r
171 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
172 @retval Others The downloading of the file from the server failed\r
173 (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes).\r
174\r
175**/\r
ba0014b9
LG
176STATIC\r
177EFI_STATUS\r
0fcf66a4 178DownloadFile (\r
68074260
RC
179 IN EFI_MTFTP4_PROTOCOL *Mtftp4,\r
180 IN CONST CHAR16 *FilePath,\r
181 IN CONST CHAR8 *AsciiFilePath,\r
182 IN UINTN FileSize,\r
2be45bfe 183 IN UINT16 BlockSize,\r
b85c8fb4 184 IN UINT16 WindowSize\r
68074260
RC
185 );\r
186\r
0fcf66a4
QS
187/**\r
188 Update the progress of a file download\r
189 This procedure is called each time a new TFTP packet is received.\r
190\r
191 @param[in] This MTFTP4 protocol interface\r
192 @param[in] Token Parameters for the download of the file\r
193 @param[in] PacketLen Length of the packet\r
194 @param[in] Packet Address of the packet\r
195\r
196 @retval EFI_SUCCESS All packets are accepted.\r
197\r
198**/\r
ba0014b9
LG
199STATIC\r
200EFI_STATUS\r
7367e66f 201EFIAPI\r
0fcf66a4 202CheckPacket (\r
68074260
RC
203 IN EFI_MTFTP4_PROTOCOL *This,\r
204 IN EFI_MTFTP4_TOKEN *Token,\r
205 IN UINT16 PacketLen,\r
206 IN EFI_MTFTP4_PACKET *Packet\r
207 );\r
208\r
47d20b54 209EFI_MTFTP4_CONFIG_DATA DefaultMtftp4ConfigData = {\r
68074260 210 TRUE, // Use default setting\r
47d20b54
MK
211 {\r
212 { 0, 0, 0, 0 }\r
213 }, // StationIp - Not relevant as UseDefaultSetting=TRUE\r
214 {\r
215 { 0, 0, 0, 0 }\r
216 }, // SubnetMask - Not relevant as UseDefaultSetting=TRUE\r
68074260 217 0, // LocalPort - Automatically assigned port number.\r
47d20b54
MK
218 {\r
219 { 0, 0, 0, 0 }\r
220 }, // GatewayIp - Not relevant as UseDefaultSetting=TRUE\r
221 {\r
222 { 0, 0, 0, 0 }\r
223 }, // ServerIp - Not known yet\r
68074260 224 69, // InitialServerPort - Standard TFTP server port\r
62ea70e3 225 6, // TryCount - The number of times to transmit request packets and wait for a response.\r
68074260
RC
226 4 // TimeoutValue - Retransmission timeout in seconds.\r
227};\r
228\r
47d20b54
MK
229STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
230 { L"-i", TypeValue },\r
231 { L"-l", TypeValue },\r
232 { L"-r", TypeValue },\r
233 { L"-c", TypeValue },\r
234 { L"-t", TypeValue },\r
235 { L"-s", TypeValue },\r
236 { L"-w", TypeValue },\r
237 { NULL, TypeMax }\r
238};\r
68074260 239\r
2be45bfe
FS
240///\r
241/// The default block size (512) of tftp is defined in the RFC1350.\r
242///\r
47d20b54 243#define MTFTP_DEFAULT_BLKSIZE 512\r
2be45bfe
FS
244///\r
245/// The valid range of block size option is defined in the RFC2348.\r
246///\r
47d20b54
MK
247#define MTFTP_MIN_BLKSIZE 8\r
248#define MTFTP_MAX_BLKSIZE 65464\r
5c6fdb5e
JW
249///\r
250/// The default windowsize (1) of tftp.\r
251///\r
47d20b54 252#define MTFTP_DEFAULT_WINDOWSIZE 1\r
5c6fdb5e
JW
253///\r
254/// The valid range of window size option.\r
255/// Note that: RFC 7440 does not mention max window size value, but for the\r
256/// stability reason, the value is limited to 64.\r
257///\r
47d20b54
MK
258#define MTFTP_MIN_WINDOWSIZE 1\r
259#define MTFTP_MAX_WINDOWSIZE 64\r
2be45bfe 260\r
68074260
RC
261/**\r
262 Function for 'tftp' command.\r
263\r
264 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
265 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
266\r
267 @return SHELL_SUCCESS The 'tftp' command completed successfully.\r
268 @return SHELL_ABORTED The Shell Library initialization failed.\r
269 @return SHELL_INVALID_PARAMETER At least one of the command's arguments is\r
270 not valid.\r
271 @return SHELL_OUT_OF_RESOURCES A memory allocation failed.\r
272 @return SHELL_NOT_FOUND Network Interface Card not found or server\r
273 error or file error.\r
274\r
275**/\r
276SHELL_STATUS\r
09610023 277RunTftp (\r
68074260
RC
278 IN EFI_HANDLE ImageHandle,\r
279 IN EFI_SYSTEM_TABLE *SystemTable\r
280 )\r
281{\r
282 SHELL_STATUS ShellStatus;\r
283 EFI_STATUS Status;\r
284 LIST_ENTRY *CheckPackage;\r
285 CHAR16 *ProblemParam;\r
286 UINTN ParamCount;\r
287 CONST CHAR16 *UserNicName;\r
288 BOOLEAN NicFound;\r
289 CONST CHAR16 *ValueStr;\r
290 CONST CHAR16 *RemoteFilePath;\r
291 CHAR8 *AsciiRemoteFilePath;\r
46213c8e 292 UINTN FilePathSize;\r
68074260 293 CONST CHAR16 *Walker;\r
68074260
RC
294 EFI_MTFTP4_CONFIG_DATA Mtftp4ConfigData;\r
295 EFI_HANDLE *Handles;\r
296 UINTN HandleCount;\r
297 UINTN NicNumber;\r
6add86ab 298 CHAR16 NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];\r
68074260
RC
299 EFI_HANDLE ControllerHandle;\r
300 EFI_HANDLE Mtftp4ChildHandle;\r
301 EFI_MTFTP4_PROTOCOL *Mtftp4;\r
302 UINTN FileSize;\r
2be45bfe 303 UINT16 BlockSize;\r
5c6fdb5e 304 UINT16 WindowSize;\r
68074260
RC
305\r
306 ShellStatus = SHELL_INVALID_PARAMETER;\r
307 ProblemParam = NULL;\r
308 NicFound = FALSE;\r
309 AsciiRemoteFilePath = NULL;\r
310 Handles = NULL;\r
6add86ab 311 FileSize = 0;\r
2be45bfe 312 BlockSize = MTFTP_DEFAULT_BLKSIZE;\r
5c6fdb5e 313 WindowSize = MTFTP_DEFAULT_WINDOWSIZE;\r
68074260
RC
314\r
315 //\r
316 // Initialize the Shell library (we must be in non-auto-init...)\r
317 //\r
318 Status = ShellInitialize ();\r
319 if (EFI_ERROR (Status)) {\r
320 ASSERT_EFI_ERROR (Status);\r
321 return SHELL_ABORTED;\r
322 }\r
323\r
324 //\r
325 // Parse the command line.\r
326 //\r
327 Status = ShellCommandLineParse (ParamList, &CheckPackage, &ProblemParam, TRUE);\r
328 if (EFI_ERROR (Status)) {\r
329 if ((Status == EFI_VOLUME_CORRUPTED) &&\r
47d20b54
MK
330 (ProblemParam != NULL))\r
331 {\r
68074260 332 ShellPrintHiiEx (\r
47d20b54
MK
333 -1,\r
334 -1,\r
335 NULL,\r
336 STRING_TOKEN (STR_GEN_PROBLEM),\r
337 mTftpHiiHandle,\r
338 L"tftp",\r
339 ProblemParam\r
68074260
RC
340 );\r
341 FreePool (ProblemParam);\r
342 } else {\r
343 ASSERT (FALSE);\r
344 }\r
47d20b54 345\r
68074260
RC
346 goto Error;\r
347 }\r
348\r
349 //\r
350 // Check the number of parameters\r
351 //\r
352 ParamCount = ShellCommandLineGetCount (CheckPackage);\r
353 if (ParamCount > 4) {\r
354 ShellPrintHiiEx (\r
47d20b54
MK
355 -1,\r
356 -1,\r
357 NULL,\r
358 STRING_TOKEN (STR_GEN_TOO_MANY),\r
359 mTftpHiiHandle,\r
360 L"tftp"\r
68074260
RC
361 );\r
362 goto Error;\r
363 }\r
47d20b54 364\r
68074260
RC
365 if (ParamCount < 3) {\r
366 ShellPrintHiiEx (\r
47d20b54
MK
367 -1,\r
368 -1,\r
369 NULL,\r
370 STRING_TOKEN (STR_GEN_TOO_FEW),\r
371 mTftpHiiHandle,\r
372 L"tftp"\r
68074260
RC
373 );\r
374 goto Error;\r
375 }\r
376\r
ba601bdd 377 CopyMem (&Mtftp4ConfigData, &DefaultMtftp4ConfigData, sizeof (EFI_MTFTP4_CONFIG_DATA));\r
68074260
RC
378\r
379 //\r
380 // Check the host IPv4 address\r
381 //\r
382 ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1);\r
47d20b54 383 Status = NetLibStrToIp4 (ValueStr, &Mtftp4ConfigData.ServerIp);\r
68074260
RC
384 if (EFI_ERROR (Status)) {\r
385 ShellPrintHiiEx (\r
47d20b54
MK
386 -1,\r
387 -1,\r
388 NULL,\r
389 STRING_TOKEN (STR_GEN_PARAM_INV),\r
390 mTftpHiiHandle,\r
391 L"tftp",\r
392 ValueStr\r
393 );\r
68074260
RC
394 goto Error;\r
395 }\r
396\r
397 RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);\r
47d20b54
MK
398 ASSERT (RemoteFilePath != NULL);\r
399 FilePathSize = StrLen (RemoteFilePath) + 1;\r
46213c8e 400 AsciiRemoteFilePath = AllocatePool (FilePathSize);\r
68074260
RC
401 if (AsciiRemoteFilePath == NULL) {\r
402 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
403 goto Error;\r
404 }\r
47d20b54 405\r
46213c8e 406 UnicodeStrToAsciiStrS (RemoteFilePath, AsciiRemoteFilePath, FilePathSize);\r
68074260
RC
407\r
408 if (ParamCount == 4) {\r
b85c8fb4 409 mLocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3);\r
68074260
RC
410 } else {\r
411 Walker = RemoteFilePath + StrLen (RemoteFilePath);\r
412 while ((--Walker) >= RemoteFilePath) {\r
413 if ((*Walker == L'\\') ||\r
47d20b54
MK
414 (*Walker == L'/'))\r
415 {\r
68074260
RC
416 break;\r
417 }\r
418 }\r
47d20b54 419\r
b85c8fb4 420 mLocalFilePath = Walker + 1;\r
68074260
RC
421 }\r
422\r
423 //\r
424 // Get the name of the Network Interface Card to be used if any.\r
425 //\r
426 UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i");\r
427\r
428 ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l");\r
429 if (ValueStr != NULL) {\r
430 if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.LocalPort)) {\r
431 goto Error;\r
432 }\r
433 }\r
434\r
435 ValueStr = ShellCommandLineGetValue (CheckPackage, L"-r");\r
436 if (ValueStr != NULL) {\r
437 if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.InitialServerPort)) {\r
438 goto Error;\r
439 }\r
440 }\r
441\r
442 ValueStr = ShellCommandLineGetValue (CheckPackage, L"-c");\r
443 if (ValueStr != NULL) {\r
444 if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TryCount)) {\r
445 goto Error;\r
446 }\r
62ea70e3
JW
447\r
448 if (Mtftp4ConfigData.TryCount == 0) {\r
449 Mtftp4ConfigData.TryCount = 6;\r
450 }\r
68074260
RC
451 }\r
452\r
453 ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");\r
454 if (ValueStr != NULL) {\r
455 if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TimeoutValue)) {\r
456 goto Error;\r
457 }\r
47d20b54 458\r
68074260
RC
459 if (Mtftp4ConfigData.TimeoutValue == 0) {\r
460 ShellPrintHiiEx (\r
47d20b54
MK
461 -1,\r
462 -1,\r
463 NULL,\r
464 STRING_TOKEN (STR_GEN_PARAM_INV),\r
465 mTftpHiiHandle,\r
466 L"tftp",\r
467 ValueStr\r
468 );\r
68074260
RC
469 goto Error;\r
470 }\r
471 }\r
472\r
2be45bfe
FS
473 ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");\r
474 if (ValueStr != NULL) {\r
475 if (!StringToUint16 (ValueStr, &BlockSize)) {\r
476 goto Error;\r
477 }\r
47d20b54
MK
478\r
479 if ((BlockSize < MTFTP_MIN_BLKSIZE) || (BlockSize > MTFTP_MAX_BLKSIZE)) {\r
2be45bfe 480 ShellPrintHiiEx (\r
47d20b54
MK
481 -1,\r
482 -1,\r
483 NULL,\r
484 STRING_TOKEN (STR_GEN_PARAM_INV),\r
485 mTftpHiiHandle,\r
486 L"tftp",\r
487 ValueStr\r
488 );\r
2be45bfe
FS
489 goto Error;\r
490 }\r
491 }\r
492\r
5c6fdb5e
JW
493 ValueStr = ShellCommandLineGetValue (CheckPackage, L"-w");\r
494 if (ValueStr != NULL) {\r
495 if (!StringToUint16 (ValueStr, &WindowSize)) {\r
496 goto Error;\r
497 }\r
47d20b54
MK
498\r
499 if ((WindowSize < MTFTP_MIN_WINDOWSIZE) || (WindowSize > MTFTP_MAX_WINDOWSIZE)) {\r
5c6fdb5e 500 ShellPrintHiiEx (\r
47d20b54
MK
501 -1,\r
502 -1,\r
503 NULL,\r
504 STRING_TOKEN (STR_GEN_PARAM_INV),\r
505 mTftpHiiHandle,\r
506 L"tftp",\r
507 ValueStr\r
508 );\r
5c6fdb5e
JW
509 goto Error;\r
510 }\r
511 }\r
512\r
68074260
RC
513 //\r
514 // Locate all MTFTP4 Service Binding protocols\r
515 //\r
516 ShellStatus = SHELL_NOT_FOUND;\r
47d20b54
MK
517 Status = gBS->LocateHandleBuffer (\r
518 ByProtocol,\r
519 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
520 NULL,\r
521 &HandleCount,\r
522 &Handles\r
523 );\r
68074260
RC
524 if (EFI_ERROR (Status) || (HandleCount == 0)) {\r
525 ShellPrintHiiEx (\r
47d20b54
MK
526 -1,\r
527 -1,\r
528 NULL,\r
529 STRING_TOKEN (STR_TFTP_ERR_NO_NIC),\r
09610023 530 mTftpHiiHandle\r
47d20b54 531 );\r
68074260
RC
532 goto Error;\r
533 }\r
534\r
535 for (NicNumber = 0;\r
536 (NicNumber < HandleCount) && (ShellStatus != SHELL_SUCCESS);\r
47d20b54
MK
537 NicNumber++)\r
538 {\r
68074260 539 ControllerHandle = Handles[NicNumber];\r
68074260
RC
540\r
541 Status = GetNicName (ControllerHandle, NicNumber, NicName);\r
542 if (EFI_ERROR (Status)) {\r
543 ShellPrintHiiEx (\r
47d20b54
MK
544 -1,\r
545 -1,\r
546 NULL,\r
547 STRING_TOKEN (STR_TFTP_ERR_NIC_NAME),\r
548 mTftpHiiHandle,\r
549 NicNumber,\r
550 Status\r
551 );\r
68074260
RC
552 continue;\r
553 }\r
554\r
555 if (UserNicName != NULL) {\r
556 if (StrCmp (NicName, UserNicName) != 0) {\r
557 continue;\r
558 }\r
47d20b54 559\r
68074260
RC
560 NicFound = TRUE;\r
561 }\r
562\r
563 Status = CreateServiceChildAndOpenProtocol (\r
564 ControllerHandle,\r
565 &gEfiMtftp4ServiceBindingProtocolGuid,\r
566 &gEfiMtftp4ProtocolGuid,\r
567 &Mtftp4ChildHandle,\r
47d20b54 568 (VOID **)&Mtftp4\r
68074260
RC
569 );\r
570 if (EFI_ERROR (Status)) {\r
571 ShellPrintHiiEx (\r
47d20b54
MK
572 -1,\r
573 -1,\r
574 NULL,\r
575 STRING_TOKEN (STR_TFTP_ERR_OPEN_PROTOCOL),\r
576 mTftpHiiHandle,\r
577 NicName,\r
578 Status\r
579 );\r
68074260
RC
580 continue;\r
581 }\r
582\r
583 Status = Mtftp4->Configure (Mtftp4, &Mtftp4ConfigData);\r
584 if (EFI_ERROR (Status)) {\r
585 ShellPrintHiiEx (\r
47d20b54
MK
586 -1,\r
587 -1,\r
588 NULL,\r
589 STRING_TOKEN (STR_TFTP_ERR_CONFIGURE),\r
590 mTftpHiiHandle,\r
591 NicName,\r
592 Status\r
593 );\r
68074260
RC
594 goto NextHandle;\r
595 }\r
596\r
597 Status = GetFileSize (Mtftp4, AsciiRemoteFilePath, &FileSize);\r
598 if (EFI_ERROR (Status)) {\r
599 ShellPrintHiiEx (\r
47d20b54
MK
600 -1,\r
601 -1,\r
602 NULL,\r
603 STRING_TOKEN (STR_TFTP_ERR_FILE_SIZE),\r
604 mTftpHiiHandle,\r
605 RemoteFilePath,\r
606 NicName,\r
607 Status\r
608 );\r
68074260
RC
609 goto NextHandle;\r
610 }\r
611\r
b85c8fb4 612 Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, BlockSize, WindowSize);\r
68074260
RC
613 if (EFI_ERROR (Status)) {\r
614 ShellPrintHiiEx (\r
47d20b54
MK
615 -1,\r
616 -1,\r
617 NULL,\r
618 STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD),\r
619 mTftpHiiHandle,\r
620 RemoteFilePath,\r
621 NicName,\r
622 Status\r
623 );\r
68074260
RC
624 goto NextHandle;\r
625 }\r
626\r
83463154
VO
627 ShellStatus = SHELL_SUCCESS;\r
628\r
47d20b54 629NextHandle:\r
68074260 630\r
68074260
RC
631 CloseProtocolAndDestroyServiceChild (\r
632 ControllerHandle,\r
633 &gEfiMtftp4ServiceBindingProtocolGuid,\r
634 &gEfiMtftp4ProtocolGuid,\r
635 Mtftp4ChildHandle\r
636 );\r
637 }\r
638\r
a0f2af3a 639 if ((UserNicName != NULL) && (!NicFound)) {\r
68074260 640 ShellPrintHiiEx (\r
47d20b54
MK
641 -1,\r
642 -1,\r
643 NULL,\r
644 STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND),\r
645 mTftpHiiHandle,\r
646 UserNicName\r
647 );\r
68074260
RC
648 }\r
649\r
47d20b54 650Error:\r
68074260
RC
651\r
652 ShellCommandLineFreeVarList (CheckPackage);\r
653 if (AsciiRemoteFilePath != NULL) {\r
654 FreePool (AsciiRemoteFilePath);\r
655 }\r
47d20b54 656\r
68074260
RC
657 if (Handles != NULL) {\r
658 FreePool (Handles);\r
659 }\r
660\r
47d20b54 661 if ((ShellStatus != SHELL_SUCCESS) && (EFI_ERROR (Status))) {\r
83463154
VO
662 ShellStatus = Status & ~MAX_BIT;\r
663 }\r
664\r
68074260
RC
665 return ShellStatus;\r
666}\r
667\r
668/**\r
669 Check and convert the UINT16 option values of the 'tftp' command\r
670\r
671 @param[in] ValueStr Value as an Unicode encoded string\r
672 @param[out] Value UINT16 value\r
673\r
674 @return TRUE The value was returned.\r
f16bd394 675 @return FALSE A parsing error occurred.\r
68074260
RC
676**/\r
677STATIC\r
678BOOLEAN\r
679StringToUint16 (\r
680 IN CONST CHAR16 *ValueStr,\r
681 OUT UINT16 *Value\r
682 )\r
683{\r
684 UINTN Val;\r
685\r
686 Val = ShellStrToUintn (ValueStr);\r
687 if (Val > MAX_UINT16) {\r
688 ShellPrintHiiEx (\r
47d20b54
MK
689 -1,\r
690 -1,\r
691 NULL,\r
692 STRING_TOKEN (STR_GEN_PARAM_INV),\r
693 mTftpHiiHandle,\r
694 L"tftp",\r
695 ValueStr\r
696 );\r
68074260
RC
697 return FALSE;\r
698 }\r
699\r
6add86ab 700 *Value = (UINT16)Val;\r
68074260
RC
701 return TRUE;\r
702}\r
703\r
704/**\r
705 Get the name of the NIC.\r
706\r
707 @param[in] ControllerHandle The network physical device handle.\r
708 @param[in] NicNumber The network physical device number.\r
709 @param[out] NicName Address where to store the NIC name.\r
710 The memory area has to be at least\r
ba0014b9 711 IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH\r
6add86ab 712 double byte wide.\r
68074260
RC
713\r
714 @return EFI_SUCCESS The name of the NIC was returned.\r
715 @return Others The creation of the child for the Managed\r
716 Network Service failed or the opening of\r
717 the Managed Network Protocol failed or\r
718 the operational parameters for the\r
719 Managed Network Protocol could not be\r
720 read.\r
721**/\r
722STATIC\r
723EFI_STATUS\r
724GetNicName (\r
725 IN EFI_HANDLE ControllerHandle,\r
726 IN UINTN NicNumber,\r
727 OUT CHAR16 *NicName\r
728 )\r
729{\r
730 EFI_STATUS Status;\r
731 EFI_HANDLE MnpHandle;\r
732 EFI_MANAGED_NETWORK_PROTOCOL *Mnp;\r
733 EFI_SIMPLE_NETWORK_MODE SnpMode;\r
734\r
735 Status = CreateServiceChildAndOpenProtocol (\r
736 ControllerHandle,\r
737 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
738 &gEfiManagedNetworkProtocolGuid,\r
739 &MnpHandle,\r
47d20b54 740 (VOID **)&Mnp\r
68074260
RC
741 );\r
742 if (EFI_ERROR (Status)) {\r
743 goto Error;\r
744 }\r
745\r
746 Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);\r
747 if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {\r
748 goto Error;\r
749 }\r
750\r
751 UnicodeSPrint (\r
752 NicName,\r
6add86ab 753 IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH,\r
68074260
RC
754 SnpMode.IfType == NET_IFTYPE_ETHERNET ?\r
755 L"eth%d" :\r
47d20b54 756 L"unk%d",\r
68074260
RC
757 NicNumber\r
758 );\r
759\r
760 Status = EFI_SUCCESS;\r
761\r
762Error:\r
763\r
764 if (MnpHandle != NULL) {\r
765 CloseProtocolAndDestroyServiceChild (\r
766 ControllerHandle,\r
767 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
768 &gEfiManagedNetworkProtocolGuid,\r
769 MnpHandle\r
770 );\r
771 }\r
772\r
773 return Status;\r
774}\r
775\r
776/**\r
777 Create a child for the service identified by its service binding protocol GUID\r
778 and get from the child the interface of the protocol identified by its GUID.\r
779\r
780 @param[in] ControllerHandle Controller handle.\r
781 @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the\r
782 service to be created.\r
783 @param[in] ProtocolGuid GUID of the protocol to be open.\r
784 @param[out] ChildHandle Address where the handler of the\r
785 created child is returned. NULL is\r
786 returned in case of error.\r
787 @param[out] Interface Address where a pointer to the\r
788 protocol interface is returned in\r
789 case of success.\r
790\r
791 @return EFI_SUCCESS The child was created and the protocol opened.\r
792 @return Others Either the creation of the child or the opening\r
793 of the protocol failed.\r
794**/\r
795STATIC\r
796EFI_STATUS\r
797CreateServiceChildAndOpenProtocol (\r
798 IN EFI_HANDLE ControllerHandle,\r
799 IN EFI_GUID *ServiceBindingProtocolGuid,\r
800 IN EFI_GUID *ProtocolGuid,\r
801 OUT EFI_HANDLE *ChildHandle,\r
802 OUT VOID **Interface\r
803 )\r
804{\r
805 EFI_STATUS Status;\r
806\r
807 *ChildHandle = NULL;\r
47d20b54
MK
808 Status = NetLibCreateServiceChild (\r
809 ControllerHandle,\r
810 gImageHandle,\r
811 ServiceBindingProtocolGuid,\r
812 ChildHandle\r
813 );\r
68074260
RC
814 if (!EFI_ERROR (Status)) {\r
815 Status = gBS->OpenProtocol (\r
816 *ChildHandle,\r
817 ProtocolGuid,\r
818 Interface,\r
819 gImageHandle,\r
820 ControllerHandle,\r
821 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
822 );\r
823 if (EFI_ERROR (Status)) {\r
824 NetLibDestroyServiceChild (\r
825 ControllerHandle,\r
826 gImageHandle,\r
827 ServiceBindingProtocolGuid,\r
828 *ChildHandle\r
829 );\r
830 *ChildHandle = NULL;\r
831 }\r
832 }\r
833\r
834 return Status;\r
835}\r
836\r
837/**\r
838 Close the protocol identified by its GUID on the child handle of the service\r
839 identified by its service binding protocol GUID, then destroy the child\r
840 handle.\r
841\r
842 @param[in] ControllerHandle Controller handle.\r
843 @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the\r
844 service to be destroyed.\r
845 @param[in] ProtocolGuid GUID of the protocol to be closed.\r
846 @param[in] ChildHandle Handle of the child to be destroyed.\r
847\r
848**/\r
849STATIC\r
850VOID\r
851CloseProtocolAndDestroyServiceChild (\r
852 IN EFI_HANDLE ControllerHandle,\r
853 IN EFI_GUID *ServiceBindingProtocolGuid,\r
854 IN EFI_GUID *ProtocolGuid,\r
855 IN EFI_HANDLE ChildHandle\r
856 )\r
857{\r
858 gBS->CloseProtocol (\r
859 ChildHandle,\r
860 ProtocolGuid,\r
861 gImageHandle,\r
862 ControllerHandle\r
863 );\r
864\r
865 NetLibDestroyServiceChild (\r
866 ControllerHandle,\r
867 gImageHandle,\r
868 ServiceBindingProtocolGuid,\r
869 ChildHandle\r
870 );\r
871}\r
872\r
873/**\r
874 Worker function that gets the size in numbers of bytes of a file from a TFTP\r
875 server before to download the file.\r
876\r
877 @param[in] Mtftp4 MTFTP4 protocol interface\r
878 @param[in] FilePath Path of the file, ASCII encoded\r
879 @param[out] FileSize Address where to store the file size in number of\r
880 bytes.\r
881\r
882 @retval EFI_SUCCESS The size of the file was returned.\r
883 @retval EFI_UNSUPPORTED The server does not support the "tsize" option.\r
884 @retval Others Error when retrieving the information from the server\r
885 (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes)\r
886 or error when parsing the response of the server.\r
887**/\r
888STATIC\r
889EFI_STATUS\r
890GetFileSize (\r
891 IN EFI_MTFTP4_PROTOCOL *Mtftp4,\r
892 IN CONST CHAR8 *FilePath,\r
893 OUT UINTN *FileSize\r
894 )\r
895{\r
896 EFI_STATUS Status;\r
897 EFI_MTFTP4_OPTION ReqOpt[1];\r
898 EFI_MTFTP4_PACKET *Packet;\r
899 UINT32 PktLen;\r
900 EFI_MTFTP4_OPTION *TableOfOptions;\r
901 EFI_MTFTP4_OPTION *Option;\r
902 UINT32 OptCnt;\r
903 UINT8 OptBuf[128];\r
904\r
47d20b54
MK
905 ReqOpt[0].OptionStr = (UINT8 *)"tsize";\r
906 OptBuf[0] = '0';\r
907 OptBuf[1] = 0;\r
908 ReqOpt[0].ValueStr = OptBuf;\r
68074260
RC
909\r
910 Status = Mtftp4->GetInfo (\r
47d20b54
MK
911 Mtftp4,\r
912 NULL,\r
913 (UINT8 *)FilePath,\r
914 NULL,\r
915 1,\r
916 ReqOpt,\r
917 &PktLen,\r
918 &Packet\r
919 );\r
68074260
RC
920\r
921 if (EFI_ERROR (Status)) {\r
922 goto Error;\r
923 }\r
924\r
925 Status = Mtftp4->ParseOptions (\r
926 Mtftp4,\r
927 PktLen,\r
928 Packet,\r
47d20b54 929 (UINT32 *)&OptCnt,\r
68074260
RC
930 &TableOfOptions\r
931 );\r
932 if (EFI_ERROR (Status)) {\r
933 goto Error;\r
934 }\r
935\r
936 Option = TableOfOptions;\r
937 while (OptCnt != 0) {\r
938 if (AsciiStrnCmp ((CHAR8 *)Option->OptionStr, "tsize", 5) == 0) {\r
939 *FileSize = AsciiStrDecimalToUintn ((CHAR8 *)Option->ValueStr);\r
940 break;\r
941 }\r
47d20b54 942\r
68074260
RC
943 OptCnt--;\r
944 Option++;\r
945 }\r
47d20b54 946\r
68074260
RC
947 FreePool (TableOfOptions);\r
948\r
949 if (OptCnt == 0) {\r
950 Status = EFI_UNSUPPORTED;\r
951 }\r
952\r
47d20b54 953Error:\r
68074260
RC
954\r
955 return Status;\r
956}\r
957\r
958/**\r
959 Worker function that download the data of a file from a TFTP server given\r
960 the path of the file and its size.\r
961\r
962 @param[in] Mtftp4 MTFTP4 protocol interface\r
963 @param[in] FilePath Path of the file, Unicode encoded\r
964 @param[in] AsciiFilePath Path of the file, ASCII encoded\r
965 @param[in] FileSize Size of the file in number of bytes\r
2be45bfe 966 @param[in] BlockSize Value of the TFTP blksize option\r
a7ab1c31 967 @param[in] WindowSize Value of the TFTP window size option\r
68074260
RC
968\r
969 @retval EFI_SUCCESS The file was downloaded.\r
970 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
971 @retval Others The downloading of the file from the server failed\r
972 (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes).\r
973\r
974**/\r
975STATIC\r
976EFI_STATUS\r
977DownloadFile (\r
978 IN EFI_MTFTP4_PROTOCOL *Mtftp4,\r
979 IN CONST CHAR16 *FilePath,\r
980 IN CONST CHAR8 *AsciiFilePath,\r
981 IN UINTN FileSize,\r
2be45bfe 982 IN UINT16 BlockSize,\r
b85c8fb4 983 IN UINT16 WindowSize\r
68074260
RC
984 )\r
985{\r
47d20b54
MK
986 EFI_STATUS Status;\r
987 DOWNLOAD_CONTEXT *TftpContext;\r
988 EFI_MTFTP4_TOKEN Mtftp4Token;\r
989 UINT8 BlksizeBuf[10];\r
990 UINT8 WindowsizeBuf[10];\r
68074260 991\r
61d3f100
JW
992 ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN));\r
993\r
68074260
RC
994 TftpContext = AllocatePool (sizeof (DOWNLOAD_CONTEXT));\r
995 if (TftpContext == NULL) {\r
996 Status = EFI_OUT_OF_RESOURCES;\r
997 goto Error;\r
998 }\r
47d20b54
MK
999\r
1000 TftpContext->FileSize = FileSize;\r
68074260
RC
1001 TftpContext->DownloadedNbOfBytes = 0;\r
1002 TftpContext->LastReportedNbOfBytes = 0;\r
1003\r
47d20b54 1004 Mtftp4Token.Filename = (UINT8 *)AsciiFilePath;\r
68074260 1005 Mtftp4Token.CheckPacket = CheckPacket;\r
47d20b54 1006 Mtftp4Token.Context = (VOID *)TftpContext;\r
5c6fdb5e
JW
1007 Mtftp4Token.OptionCount = 0;\r
1008 Mtftp4Token.OptionList = AllocatePool (sizeof (EFI_MTFTP4_OPTION) * 2);\r
1009 if (Mtftp4Token.OptionList == NULL) {\r
1010 Status = EFI_OUT_OF_RESOURCES;\r
1011 goto Error;\r
1012 }\r
1013\r
2be45bfe 1014 if (BlockSize != MTFTP_DEFAULT_BLKSIZE) {\r
47d20b54
MK
1015 Mtftp4Token.OptionList[Mtftp4Token.OptionCount].OptionStr = (UINT8 *)"blksize";\r
1016 AsciiSPrint ((CHAR8 *)BlksizeBuf, sizeof (BlksizeBuf), "%d", BlockSize);\r
1017 Mtftp4Token.OptionList[Mtftp4Token.OptionCount].ValueStr = BlksizeBuf;\r
1018 Mtftp4Token.OptionCount++;\r
5c6fdb5e 1019 }\r
2be45bfe 1020\r
5c6fdb5e 1021 if (WindowSize != MTFTP_DEFAULT_WINDOWSIZE) {\r
47d20b54
MK
1022 Mtftp4Token.OptionList[Mtftp4Token.OptionCount].OptionStr = (UINT8 *)"windowsize";\r
1023 AsciiSPrint ((CHAR8 *)WindowsizeBuf, sizeof (WindowsizeBuf), "%d", WindowSize);\r
1024 Mtftp4Token.OptionList[Mtftp4Token.OptionCount].ValueStr = WindowsizeBuf;\r
1025 Mtftp4Token.OptionCount++;\r
2be45bfe 1026 }\r
68074260
RC
1027\r
1028 ShellPrintHiiEx (\r
47d20b54
MK
1029 -1,\r
1030 -1,\r
1031 NULL,\r
1032 STRING_TOKEN (STR_TFTP_DOWNLOADING),\r
1033 mTftpHiiHandle,\r
1034 FilePath\r
68074260
RC
1035 );\r
1036\r
b85c8fb4
AL
1037 //\r
1038 // OPEN FILE\r
1039 //\r
1040 if (!EFI_ERROR (ShellFileExists (mLocalFilePath))) {\r
1041 ShellDeleteFileByName (mLocalFilePath);\r
1042 }\r
1043\r
1044 Status = ShellOpenFileByName (\r
47d20b54
MK
1045 mLocalFilePath,\r
1046 &mFileHandle,\r
1047 EFI_FILE_MODE_CREATE |\r
1048 EFI_FILE_MODE_WRITE |\r
1049 EFI_FILE_MODE_READ,\r
1050 0\r
1051 );\r
b85c8fb4
AL
1052 if (EFI_ERROR (Status)) {\r
1053 ShellPrintHiiEx (\r
47d20b54
MK
1054 -1,\r
1055 -1,\r
1056 NULL,\r
1057 STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),\r
1058 mTftpHiiHandle,\r
1059 L"tftp",\r
1060 mLocalFilePath\r
1061 );\r
b85c8fb4
AL
1062 goto Error;\r
1063 }\r
1064\r
68074260
RC
1065 Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token);\r
1066 ShellPrintHiiEx (\r
47d20b54
MK
1067 -1,\r
1068 -1,\r
1069 NULL,\r
1070 STRING_TOKEN (STR_GEN_CRLF),\r
09610023 1071 mTftpHiiHandle\r
68074260
RC
1072 );\r
1073\r
b85c8fb4
AL
1074 //\r
1075 // CLOSE FILE\r
1076 //\r
1077 ShellCloseFile (&mFileHandle);\r
68074260 1078\r
47d20b54 1079Error:\r
5c6fdb5e 1080 if (TftpContext != NULL) {\r
68074260
RC
1081 FreePool (TftpContext);\r
1082 }\r
1083\r
5c6fdb5e
JW
1084 if (Mtftp4Token.OptionList != NULL) {\r
1085 FreePool (Mtftp4Token.OptionList);\r
1086 }\r
1087\r
b85c8fb4 1088 return Status;\r
68074260
RC
1089}\r
1090\r
1091/**\r
1092 Update the progress of a file download\r
1093 This procedure is called each time a new TFTP packet is received.\r
1094\r
1095 @param[in] This MTFTP4 protocol interface\r
1096 @param[in] Token Parameters for the download of the file\r
1097 @param[in] PacketLen Length of the packet\r
1098 @param[in] Packet Address of the packet\r
1099\r
1100 @retval EFI_SUCCESS All packets are accepted.\r
1101\r
1102**/\r
1103STATIC\r
1104EFI_STATUS\r
7367e66f 1105EFIAPI\r
68074260
RC
1106CheckPacket (\r
1107 IN EFI_MTFTP4_PROTOCOL *This,\r
1108 IN EFI_MTFTP4_TOKEN *Token,\r
1109 IN UINT16 PacketLen,\r
1110 IN EFI_MTFTP4_PACKET *Packet\r
1111 )\r
1112{\r
1113 DOWNLOAD_CONTEXT *Context;\r
1114 CHAR16 Progress[TFTP_PROGRESS_MESSAGE_SIZE];\r
6add86ab 1115 UINTN NbOfKb;\r
68074260 1116 UINTN Index;\r
310b053a
JC
1117 UINTN LastStep;\r
1118 UINTN Step;\r
b85c8fb4 1119 UINTN DownloadLen;\r
da6b8feb 1120 EFI_STATUS Status;\r
68074260
RC
1121\r
1122 if ((NTOHS (Packet->OpCode)) != EFI_MTFTP4_OPCODE_DATA) {\r
1123 return EFI_SUCCESS;\r
1124 }\r
1125\r
47d20b54 1126 Context = (DOWNLOAD_CONTEXT *)Token->Context;\r
68074260
RC
1127\r
1128 //\r
1129 // The data in the packet are prepended with two UINT16 :\r
1130 // . OpCode = EFI_MTFTP4_OPCODE_DATA\r
1131 // . Block = the number of this block of data\r
1132 //\r
b85c8fb4
AL
1133 DownloadLen = (UINTN)PacketLen - sizeof (Packet->OpCode) - sizeof (Packet->Data.Block);\r
1134\r
47d20b54 1135 ShellSetFilePosition (mFileHandle, Context->DownloadedNbOfBytes);\r
b85c8fb4
AL
1136 Status = ShellWriteFile (mFileHandle, &DownloadLen, Packet->Data.Data);\r
1137 if (EFI_ERROR (Status)) {\r
1138 if (Context->DownloadedNbOfBytes > 0) {\r
1139 ShellPrintHiiEx (\r
47d20b54
MK
1140 -1,\r
1141 -1,\r
1142 NULL,\r
1143 STRING_TOKEN (STR_GEN_CRLF),\r
b85c8fb4 1144 mTftpHiiHandle\r
47d20b54 1145 );\r
b85c8fb4 1146 }\r
47d20b54 1147\r
b85c8fb4 1148 ShellPrintHiiEx (\r
47d20b54
MK
1149 -1,\r
1150 -1,\r
1151 NULL,\r
1152 STRING_TOKEN (STR_TFTP_ERR_WRITE),\r
1153 mTftpHiiHandle,\r
1154 mLocalFilePath,\r
1155 Status\r
1156 );\r
b85c8fb4
AL
1157 return Status;\r
1158 }\r
1159\r
1160 if (Context->DownloadedNbOfBytes == 0) {\r
1161 ShellPrintEx (-1, -1, L"%s 0 Kb", mTftpProgressFrame);\r
1162 }\r
1163\r
1164 Context->DownloadedNbOfBytes += DownloadLen;\r
47d20b54 1165 NbOfKb = Context->DownloadedNbOfBytes / 1024;\r
68074260
RC
1166\r
1167 Progress[0] = L'\0';\r
47d20b54
MK
1168 LastStep = (Context->LastReportedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;\r
1169 Step = (Context->DownloadedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;\r
6add86ab 1170\r
68074260
RC
1171 if (Step <= LastStep) {\r
1172 return EFI_SUCCESS;\r
1173 }\r
1174\r
1175 ShellPrintEx (-1, -1, L"%s", mTftpProgressDelete);\r
1176\r
da6b8feb 1177 Status = StrCpyS (Progress, TFTP_PROGRESS_MESSAGE_SIZE, mTftpProgressFrame);\r
47d20b54 1178 if (EFI_ERROR (Status)) {\r
da6b8feb
QS
1179 return Status;\r
1180 }\r
47d20b54 1181\r
68074260
RC
1182 for (Index = 1; Index < Step; Index++) {\r
1183 Progress[Index] = L'=';\r
1184 }\r
47d20b54 1185\r
68074260
RC
1186 Progress[Step] = L'>';\r
1187\r
1188 UnicodeSPrint (\r
1189 Progress + (sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 1,\r
1190 sizeof (Progress) - sizeof (mTftpProgressFrame),\r
1191 L" %7d Kb",\r
1192 NbOfKb\r
1193 );\r
1194 Context->LastReportedNbOfBytes = Context->DownloadedNbOfBytes;\r
1195\r
1196 ShellPrintEx (-1, -1, L"%s", Progress);\r
1197\r
1198 return EFI_SUCCESS;\r
1199}\r
09610023
RN
1200\r
1201/**\r
f16bd394 1202 Retrieve HII package list from ImageHandle and publish to HII database.\r
09610023
RN
1203\r
1204 @param ImageHandle The image handle of the process.\r
1205\r
1206 @return HII handle.\r
1207**/\r
c44501b3 1208EFI_HII_HANDLE\r
09610023 1209InitializeHiiPackage (\r
47d20b54 1210 EFI_HANDLE ImageHandle\r
09610023
RN
1211 )\r
1212{\r
47d20b54
MK
1213 EFI_STATUS Status;\r
1214 EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
1215 EFI_HII_HANDLE HiiHandle;\r
09610023
RN
1216\r
1217 //\r
1218 // Retrieve HII package list from ImageHandle\r
1219 //\r
1220 Status = gBS->OpenProtocol (\r
1221 ImageHandle,\r
1222 &gEfiHiiPackageListProtocolGuid,\r
1223 (VOID **)&PackageList,\r
1224 ImageHandle,\r
1225 NULL,\r
1226 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1227 );\r
1228 ASSERT_EFI_ERROR (Status);\r
1229 if (EFI_ERROR (Status)) {\r
1230 return NULL;\r
1231 }\r
1232\r
1233 //\r
1234 // Publish HII package list to HII Database.\r
1235 //\r
1236 Status = gHiiDatabase->NewPackageList (\r
1237 gHiiDatabase,\r
1238 PackageList,\r
1239 NULL,\r
1240 &HiiHandle\r
1241 );\r
1242 ASSERT_EFI_ERROR (Status);\r
1243 if (EFI_ERROR (Status)) {\r
1244 return NULL;\r
1245 }\r
47d20b54 1246\r
09610023
RN
1247 return HiiHandle;\r
1248}\r