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