]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.c
MdeModulePkg/Mtftp4Dxe: Fix invalid configuration of MTFTP local port.
[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
221 6, // TryCount - Max number of retransmissions.\r
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
424 }\r
425\r
426 ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");\r
427 if (ValueStr != NULL) {\r
428 if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TimeoutValue)) {\r
429 goto Error;\r
430 }\r
431 if (Mtftp4ConfigData.TimeoutValue == 0) {\r
432 ShellPrintHiiEx (\r
433 -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),\r
09610023 434 mTftpHiiHandle, L"tftp", ValueStr\r
68074260
RC
435 );\r
436 goto Error;\r
437 }\r
438 }\r
439\r
2be45bfe
FS
440 ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");\r
441 if (ValueStr != NULL) {\r
442 if (!StringToUint16 (ValueStr, &BlockSize)) {\r
443 goto Error;\r
444 }\r
445 if (BlockSize < MTFTP_MIN_BLKSIZE || BlockSize > MTFTP_MAX_BLKSIZE) {\r
446 ShellPrintHiiEx (\r
447 -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),\r
09610023 448 mTftpHiiHandle, L"tftp", ValueStr\r
2be45bfe
FS
449 );\r
450 goto Error;\r
451 }\r
452 }\r
453\r
5c6fdb5e
JW
454 ValueStr = ShellCommandLineGetValue (CheckPackage, L"-w");\r
455 if (ValueStr != NULL) {\r
456 if (!StringToUint16 (ValueStr, &WindowSize)) {\r
457 goto Error;\r
458 }\r
459 if (WindowSize < MTFTP_MIN_WINDOWSIZE || WindowSize > MTFTP_MAX_WINDOWSIZE) {\r
460 ShellPrintHiiEx (\r
461 -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),\r
462 mTftpHiiHandle, L"tftp", ValueStr\r
463 );\r
464 goto Error;\r
465 }\r
466 }\r
467\r
68074260
RC
468 //\r
469 // Locate all MTFTP4 Service Binding protocols\r
470 //\r
471 ShellStatus = SHELL_NOT_FOUND;\r
472 Status = gBS->LocateHandleBuffer (\r
473 ByProtocol,\r
474 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
475 NULL,\r
476 &HandleCount,\r
477 &Handles\r
478 );\r
479 if (EFI_ERROR (Status) || (HandleCount == 0)) {\r
480 ShellPrintHiiEx (\r
481 -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NO_NIC),\r
09610023 482 mTftpHiiHandle\r
68074260
RC
483 );\r
484 goto Error;\r
485 }\r
486\r
487 for (NicNumber = 0;\r
488 (NicNumber < HandleCount) && (ShellStatus != SHELL_SUCCESS);\r
489 NicNumber++) {\r
490 ControllerHandle = Handles[NicNumber];\r
491 Data = NULL;\r
492\r
493 Status = GetNicName (ControllerHandle, NicNumber, NicName);\r
494 if (EFI_ERROR (Status)) {\r
495 ShellPrintHiiEx (\r
496 -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NAME),\r
09610023 497 mTftpHiiHandle, NicNumber, Status\r
68074260
RC
498 );\r
499 continue;\r
500 }\r
501\r
502 if (UserNicName != NULL) {\r
503 if (StrCmp (NicName, UserNicName) != 0) {\r
504 continue;\r
505 }\r
506 NicFound = TRUE;\r
507 }\r
508\r
509 Status = CreateServiceChildAndOpenProtocol (\r
510 ControllerHandle,\r
511 &gEfiMtftp4ServiceBindingProtocolGuid,\r
512 &gEfiMtftp4ProtocolGuid,\r
513 &Mtftp4ChildHandle,\r
514 (VOID**)&Mtftp4\r
515 );\r
516 if (EFI_ERROR (Status)) {\r
517 ShellPrintHiiEx (\r
518 -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_OPEN_PROTOCOL),\r
09610023 519 mTftpHiiHandle, NicName, Status\r
68074260
RC
520 );\r
521 continue;\r
522 }\r
523\r
524 Status = Mtftp4->Configure (Mtftp4, &Mtftp4ConfigData);\r
525 if (EFI_ERROR (Status)) {\r
526 ShellPrintHiiEx (\r
527 -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_CONFIGURE),\r
09610023 528 mTftpHiiHandle, NicName, Status\r
68074260
RC
529 );\r
530 goto NextHandle;\r
531 }\r
532\r
533 Status = GetFileSize (Mtftp4, AsciiRemoteFilePath, &FileSize);\r
534 if (EFI_ERROR (Status)) {\r
535 ShellPrintHiiEx (\r
536 -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_FILE_SIZE),\r
09610023 537 mTftpHiiHandle, RemoteFilePath, NicName, Status\r
68074260
RC
538 );\r
539 goto NextHandle;\r
540 }\r
541\r
5c6fdb5e 542 Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, BlockSize, WindowSize, &Data);\r
68074260
RC
543 if (EFI_ERROR (Status)) {\r
544 ShellPrintHiiEx (\r
545 -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD),\r
09610023 546 mTftpHiiHandle, RemoteFilePath, NicName, Status\r
68074260
RC
547 );\r
548 goto NextHandle;\r
549 }\r
550\r
280f49b8
JW
551 DataSize = FileSize;\r
552\r
68074260
RC
553 if (!EFI_ERROR (ShellFileExists (LocalFilePath))) {\r
554 ShellDeleteFileByName (LocalFilePath);\r
555 }\r
556\r
557 Status = ShellOpenFileByName (\r
558 LocalFilePath,\r
559 &FileHandle,\r
560 EFI_FILE_MODE_CREATE |\r
561 EFI_FILE_MODE_WRITE |\r
562 EFI_FILE_MODE_READ,\r
563 0\r
564 );\r
565 if (EFI_ERROR (Status)) {\r
566 ShellPrintHiiEx (\r
567 -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),\r
09610023 568 mTftpHiiHandle, L"tftp", LocalFilePath\r
68074260
RC
569 );\r
570 goto NextHandle;\r
571 }\r
572\r
573 Status = ShellWriteFile (FileHandle, &FileSize, Data);\r
574 if (!EFI_ERROR (Status)) {\r
575 ShellStatus = SHELL_SUCCESS;\r
576 } else {\r
577 ShellPrintHiiEx (\r
578 -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_WRITE),\r
09610023 579 mTftpHiiHandle, LocalFilePath, Status\r
68074260
RC
580 );\r
581 }\r
582 ShellCloseFile (&FileHandle);\r
583\r
584 NextHandle:\r
585\r
586 if (Data != NULL) {\r
34cd44d4 587 gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Data, EFI_SIZE_TO_PAGES (DataSize));\r
68074260
RC
588 }\r
589\r
590 CloseProtocolAndDestroyServiceChild (\r
591 ControllerHandle,\r
592 &gEfiMtftp4ServiceBindingProtocolGuid,\r
593 &gEfiMtftp4ProtocolGuid,\r
594 Mtftp4ChildHandle\r
595 );\r
596 }\r
597\r
a0f2af3a 598 if ((UserNicName != NULL) && (!NicFound)) {\r
68074260
RC
599 ShellPrintHiiEx (\r
600 -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND),\r
09610023 601 mTftpHiiHandle, UserNicName\r
68074260
RC
602 );\r
603 }\r
604\r
605 Error:\r
606\r
607 ShellCommandLineFreeVarList (CheckPackage);\r
608 if (AsciiRemoteFilePath != NULL) {\r
609 FreePool (AsciiRemoteFilePath);\r
610 }\r
611 if (Handles != NULL) {\r
612 FreePool (Handles);\r
613 }\r
614\r
615 return ShellStatus;\r
616}\r
617\r
618/**\r
619 Check and convert the UINT16 option values of the 'tftp' command\r
620\r
621 @param[in] ValueStr Value as an Unicode encoded string\r
622 @param[out] Value UINT16 value\r
623\r
624 @return TRUE The value was returned.\r
625 @return FALSE A parsing error occured.\r
626**/\r
627STATIC\r
628BOOLEAN\r
629StringToUint16 (\r
630 IN CONST CHAR16 *ValueStr,\r
631 OUT UINT16 *Value\r
632 )\r
633{\r
634 UINTN Val;\r
635\r
636 Val = ShellStrToUintn (ValueStr);\r
637 if (Val > MAX_UINT16) {\r
638 ShellPrintHiiEx (\r
639 -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),\r
09610023 640 mTftpHiiHandle, L"tftp", ValueStr\r
68074260
RC
641 );\r
642 return FALSE;\r
643 }\r
644\r
6add86ab 645 *Value = (UINT16)Val;\r
68074260
RC
646 return TRUE;\r
647}\r
648\r
649/**\r
650 Get the name of the NIC.\r
651\r
652 @param[in] ControllerHandle The network physical device handle.\r
653 @param[in] NicNumber The network physical device number.\r
654 @param[out] NicName Address where to store the NIC name.\r
655 The memory area has to be at least\r
ba0014b9 656 IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH\r
6add86ab 657 double byte wide.\r
68074260
RC
658\r
659 @return EFI_SUCCESS The name of the NIC was returned.\r
660 @return Others The creation of the child for the Managed\r
661 Network Service failed or the opening of\r
662 the Managed Network Protocol failed or\r
663 the operational parameters for the\r
664 Managed Network Protocol could not be\r
665 read.\r
666**/\r
667STATIC\r
668EFI_STATUS\r
669GetNicName (\r
670 IN EFI_HANDLE ControllerHandle,\r
671 IN UINTN NicNumber,\r
672 OUT CHAR16 *NicName\r
673 )\r
674{\r
675 EFI_STATUS Status;\r
676 EFI_HANDLE MnpHandle;\r
677 EFI_MANAGED_NETWORK_PROTOCOL *Mnp;\r
678 EFI_SIMPLE_NETWORK_MODE SnpMode;\r
679\r
680 Status = CreateServiceChildAndOpenProtocol (\r
681 ControllerHandle,\r
682 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
683 &gEfiManagedNetworkProtocolGuid,\r
684 &MnpHandle,\r
685 (VOID**)&Mnp\r
686 );\r
687 if (EFI_ERROR (Status)) {\r
688 goto Error;\r
689 }\r
690\r
691 Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);\r
692 if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {\r
693 goto Error;\r
694 }\r
695\r
696 UnicodeSPrint (\r
697 NicName,\r
6add86ab 698 IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH,\r
68074260
RC
699 SnpMode.IfType == NET_IFTYPE_ETHERNET ?\r
700 L"eth%d" :\r
701 L"unk%d" ,\r
702 NicNumber\r
703 );\r
704\r
705 Status = EFI_SUCCESS;\r
706\r
707Error:\r
708\r
709 if (MnpHandle != NULL) {\r
710 CloseProtocolAndDestroyServiceChild (\r
711 ControllerHandle,\r
712 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
713 &gEfiManagedNetworkProtocolGuid,\r
714 MnpHandle\r
715 );\r
716 }\r
717\r
718 return Status;\r
719}\r
720\r
721/**\r
722 Create a child for the service identified by its service binding protocol GUID\r
723 and get from the child the interface of the protocol identified by its GUID.\r
724\r
725 @param[in] ControllerHandle Controller handle.\r
726 @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the\r
727 service to be created.\r
728 @param[in] ProtocolGuid GUID of the protocol to be open.\r
729 @param[out] ChildHandle Address where the handler of the\r
730 created child is returned. NULL is\r
731 returned in case of error.\r
732 @param[out] Interface Address where a pointer to the\r
733 protocol interface is returned in\r
734 case of success.\r
735\r
736 @return EFI_SUCCESS The child was created and the protocol opened.\r
737 @return Others Either the creation of the child or the opening\r
738 of the protocol failed.\r
739**/\r
740STATIC\r
741EFI_STATUS\r
742CreateServiceChildAndOpenProtocol (\r
743 IN EFI_HANDLE ControllerHandle,\r
744 IN EFI_GUID *ServiceBindingProtocolGuid,\r
745 IN EFI_GUID *ProtocolGuid,\r
746 OUT EFI_HANDLE *ChildHandle,\r
747 OUT VOID **Interface\r
748 )\r
749{\r
750 EFI_STATUS Status;\r
751\r
752 *ChildHandle = NULL;\r
753 Status = NetLibCreateServiceChild (\r
754 ControllerHandle,\r
755 gImageHandle,\r
756 ServiceBindingProtocolGuid,\r
757 ChildHandle\r
758 );\r
759 if (!EFI_ERROR (Status)) {\r
760 Status = gBS->OpenProtocol (\r
761 *ChildHandle,\r
762 ProtocolGuid,\r
763 Interface,\r
764 gImageHandle,\r
765 ControllerHandle,\r
766 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
767 );\r
768 if (EFI_ERROR (Status)) {\r
769 NetLibDestroyServiceChild (\r
770 ControllerHandle,\r
771 gImageHandle,\r
772 ServiceBindingProtocolGuid,\r
773 *ChildHandle\r
774 );\r
775 *ChildHandle = NULL;\r
776 }\r
777 }\r
778\r
779 return Status;\r
780}\r
781\r
782/**\r
783 Close the protocol identified by its GUID on the child handle of the service\r
784 identified by its service binding protocol GUID, then destroy the child\r
785 handle.\r
786\r
787 @param[in] ControllerHandle Controller handle.\r
788 @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the\r
789 service to be destroyed.\r
790 @param[in] ProtocolGuid GUID of the protocol to be closed.\r
791 @param[in] ChildHandle Handle of the child to be destroyed.\r
792\r
793**/\r
794STATIC\r
795VOID\r
796CloseProtocolAndDestroyServiceChild (\r
797 IN EFI_HANDLE ControllerHandle,\r
798 IN EFI_GUID *ServiceBindingProtocolGuid,\r
799 IN EFI_GUID *ProtocolGuid,\r
800 IN EFI_HANDLE ChildHandle\r
801 )\r
802{\r
803 gBS->CloseProtocol (\r
804 ChildHandle,\r
805 ProtocolGuid,\r
806 gImageHandle,\r
807 ControllerHandle\r
808 );\r
809\r
810 NetLibDestroyServiceChild (\r
811 ControllerHandle,\r
812 gImageHandle,\r
813 ServiceBindingProtocolGuid,\r
814 ChildHandle\r
815 );\r
816}\r
817\r
818/**\r
819 Worker function that gets the size in numbers of bytes of a file from a TFTP\r
820 server before to download the file.\r
821\r
822 @param[in] Mtftp4 MTFTP4 protocol interface\r
823 @param[in] FilePath Path of the file, ASCII encoded\r
824 @param[out] FileSize Address where to store the file size in number of\r
825 bytes.\r
826\r
827 @retval EFI_SUCCESS The size of the file was returned.\r
828 @retval EFI_UNSUPPORTED The server does not support the "tsize" option.\r
829 @retval Others Error when retrieving the information from the server\r
830 (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes)\r
831 or error when parsing the response of the server.\r
832**/\r
833STATIC\r
834EFI_STATUS\r
835GetFileSize (\r
836 IN EFI_MTFTP4_PROTOCOL *Mtftp4,\r
837 IN CONST CHAR8 *FilePath,\r
838 OUT UINTN *FileSize\r
839 )\r
840{\r
841 EFI_STATUS Status;\r
842 EFI_MTFTP4_OPTION ReqOpt[1];\r
843 EFI_MTFTP4_PACKET *Packet;\r
844 UINT32 PktLen;\r
845 EFI_MTFTP4_OPTION *TableOfOptions;\r
846 EFI_MTFTP4_OPTION *Option;\r
847 UINT32 OptCnt;\r
848 UINT8 OptBuf[128];\r
849\r
850 ReqOpt[0].OptionStr = (UINT8*)"tsize";\r
851 OptBuf[0] = '0';\r
852 OptBuf[1] = 0;\r
853 ReqOpt[0].ValueStr = OptBuf;\r
854\r
855 Status = Mtftp4->GetInfo (\r
856 Mtftp4,\r
857 NULL,\r
858 (UINT8*)FilePath,\r
859 NULL,\r
860 1,\r
861 ReqOpt,\r
862 &PktLen,\r
863 &Packet\r
864 );\r
865\r
866 if (EFI_ERROR (Status)) {\r
867 goto Error;\r
868 }\r
869\r
870 Status = Mtftp4->ParseOptions (\r
871 Mtftp4,\r
872 PktLen,\r
873 Packet,\r
874 (UINT32 *) &OptCnt,\r
875 &TableOfOptions\r
876 );\r
877 if (EFI_ERROR (Status)) {\r
878 goto Error;\r
879 }\r
880\r
881 Option = TableOfOptions;\r
882 while (OptCnt != 0) {\r
883 if (AsciiStrnCmp ((CHAR8 *)Option->OptionStr, "tsize", 5) == 0) {\r
884 *FileSize = AsciiStrDecimalToUintn ((CHAR8 *)Option->ValueStr);\r
885 break;\r
886 }\r
887 OptCnt--;\r
888 Option++;\r
889 }\r
890 FreePool (TableOfOptions);\r
891\r
892 if (OptCnt == 0) {\r
893 Status = EFI_UNSUPPORTED;\r
894 }\r
895\r
896Error :\r
897\r
898 return Status;\r
899}\r
900\r
901/**\r
902 Worker function that download the data of a file from a TFTP server given\r
903 the path of the file and its size.\r
904\r
905 @param[in] Mtftp4 MTFTP4 protocol interface\r
906 @param[in] FilePath Path of the file, Unicode encoded\r
907 @param[in] AsciiFilePath Path of the file, ASCII encoded\r
908 @param[in] FileSize Size of the file in number of bytes\r
2be45bfe 909 @param[in] BlockSize Value of the TFTP blksize option\r
a7ab1c31 910 @param[in] WindowSize Value of the TFTP window size option\r
68074260
RC
911 @param[out] Data Address where to store the address of the buffer\r
912 where the data of the file were downloaded in\r
913 case of success.\r
914\r
915 @retval EFI_SUCCESS The file was downloaded.\r
916 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
917 @retval Others The downloading of the file from the server failed\r
918 (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes).\r
919\r
920**/\r
921STATIC\r
922EFI_STATUS\r
923DownloadFile (\r
924 IN EFI_MTFTP4_PROTOCOL *Mtftp4,\r
925 IN CONST CHAR16 *FilePath,\r
926 IN CONST CHAR8 *AsciiFilePath,\r
927 IN UINTN FileSize,\r
2be45bfe 928 IN UINT16 BlockSize,\r
5c6fdb5e 929 IN UINT16 WindowSize,\r
68074260
RC
930 OUT VOID **Data\r
931 )\r
932{\r
933 EFI_STATUS Status;\r
934 EFI_PHYSICAL_ADDRESS PagesAddress;\r
935 VOID *Buffer;\r
936 DOWNLOAD_CONTEXT *TftpContext;\r
937 EFI_MTFTP4_TOKEN Mtftp4Token;\r
5c6fdb5e
JW
938 UINT8 BlksizeBuf[10];\r
939 UINT8 WindowsizeBuf[10];\r
68074260 940\r
61d3f100
JW
941 ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN));\r
942\r
68074260
RC
943 // Downloaded file can be large. BS.AllocatePages() is more faster\r
944 // than AllocatePool() and avoid fragmentation.\r
945 // The downloaded file could be an EFI application. Marking the\r
946 // allocated page as EfiBootServicesCode would allow to execute a\r
947 // potential downloaded EFI application.\r
948 Status = gBS->AllocatePages (\r
949 AllocateAnyPages,\r
950 EfiBootServicesCode,\r
951 EFI_SIZE_TO_PAGES (FileSize),\r
952 &PagesAddress\r
953 );\r
954 if (EFI_ERROR (Status)) {\r
955 return Status;\r
956 }\r
957\r
958 Buffer = (VOID*)(UINTN)PagesAddress;\r
959 TftpContext = AllocatePool (sizeof (DOWNLOAD_CONTEXT));\r
960 if (TftpContext == NULL) {\r
961 Status = EFI_OUT_OF_RESOURCES;\r
962 goto Error;\r
963 }\r
964 TftpContext->FileSize = FileSize;\r
965 TftpContext->DownloadedNbOfBytes = 0;\r
966 TftpContext->LastReportedNbOfBytes = 0;\r
967\r
68074260
RC
968 Mtftp4Token.Filename = (UINT8*)AsciiFilePath;\r
969 Mtftp4Token.BufferSize = FileSize;\r
970 Mtftp4Token.Buffer = Buffer;\r
971 Mtftp4Token.CheckPacket = CheckPacket;\r
972 Mtftp4Token.Context = (VOID*)TftpContext;\r
5c6fdb5e
JW
973 Mtftp4Token.OptionCount = 0;\r
974 Mtftp4Token.OptionList = AllocatePool (sizeof (EFI_MTFTP4_OPTION) * 2);\r
975 if (Mtftp4Token.OptionList == NULL) {\r
976 Status = EFI_OUT_OF_RESOURCES;\r
977 goto Error;\r
978 }\r
979\r
2be45bfe 980 if (BlockSize != MTFTP_DEFAULT_BLKSIZE) {\r
5c6fdb5e
JW
981 Mtftp4Token.OptionList[Mtftp4Token.OptionCount].OptionStr = (UINT8 *) "blksize";\r
982 AsciiSPrint ((CHAR8 *) BlksizeBuf, sizeof (BlksizeBuf), "%d", BlockSize);\r
983 Mtftp4Token.OptionList[Mtftp4Token.OptionCount].ValueStr = BlksizeBuf;\r
984 Mtftp4Token.OptionCount ++;\r
985 }\r
2be45bfe 986\r
5c6fdb5e
JW
987 if (WindowSize != MTFTP_DEFAULT_WINDOWSIZE) {\r
988 Mtftp4Token.OptionList[Mtftp4Token.OptionCount].OptionStr = (UINT8 *) "windowsize";\r
989 AsciiSPrint ((CHAR8 *) WindowsizeBuf, sizeof (WindowsizeBuf), "%d", WindowSize);\r
990 Mtftp4Token.OptionList[Mtftp4Token.OptionCount].ValueStr = WindowsizeBuf;\r
991 Mtftp4Token.OptionCount ++;\r
2be45bfe 992 }\r
68074260
RC
993\r
994 ShellPrintHiiEx (\r
995 -1, -1, NULL, STRING_TOKEN (STR_TFTP_DOWNLOADING),\r
09610023 996 mTftpHiiHandle, FilePath\r
68074260
RC
997 );\r
998\r
999 Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token);\r
1000 ShellPrintHiiEx (\r
1001 -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF),\r
09610023 1002 mTftpHiiHandle\r
68074260
RC
1003 );\r
1004\r
1005Error :\r
1006\r
5c6fdb5e 1007 if (TftpContext != NULL) {\r
68074260
RC
1008 FreePool (TftpContext);\r
1009 }\r
1010\r
5c6fdb5e
JW
1011 if (Mtftp4Token.OptionList != NULL) {\r
1012 FreePool (Mtftp4Token.OptionList);\r
1013 }\r
1014\r
68074260
RC
1015 if (EFI_ERROR (Status)) {\r
1016 gBS->FreePages (PagesAddress, EFI_SIZE_TO_PAGES (FileSize));\r
1017 return Status;\r
1018 }\r
1019\r
1020 *Data = Buffer;\r
1021\r
1022 return EFI_SUCCESS;\r
1023}\r
1024\r
1025/**\r
1026 Update the progress of a file download\r
1027 This procedure is called each time a new TFTP packet is received.\r
1028\r
1029 @param[in] This MTFTP4 protocol interface\r
1030 @param[in] Token Parameters for the download of the file\r
1031 @param[in] PacketLen Length of the packet\r
1032 @param[in] Packet Address of the packet\r
1033\r
1034 @retval EFI_SUCCESS All packets are accepted.\r
1035\r
1036**/\r
1037STATIC\r
1038EFI_STATUS\r
7367e66f 1039EFIAPI\r
68074260
RC
1040CheckPacket (\r
1041 IN EFI_MTFTP4_PROTOCOL *This,\r
1042 IN EFI_MTFTP4_TOKEN *Token,\r
1043 IN UINT16 PacketLen,\r
1044 IN EFI_MTFTP4_PACKET *Packet\r
1045 )\r
1046{\r
1047 DOWNLOAD_CONTEXT *Context;\r
1048 CHAR16 Progress[TFTP_PROGRESS_MESSAGE_SIZE];\r
6add86ab 1049 UINTN NbOfKb;\r
68074260 1050 UINTN Index;\r
310b053a
JC
1051 UINTN LastStep;\r
1052 UINTN Step;\r
da6b8feb 1053 EFI_STATUS Status;\r
68074260
RC
1054\r
1055 if ((NTOHS (Packet->OpCode)) != EFI_MTFTP4_OPCODE_DATA) {\r
1056 return EFI_SUCCESS;\r
1057 }\r
1058\r
1059 Context = (DOWNLOAD_CONTEXT*)Token->Context;\r
1060 if (Context->DownloadedNbOfBytes == 0) {\r
1061 ShellPrintEx (-1, -1, L"%s 0 Kb", mTftpProgressFrame);\r
1062 }\r
1063\r
1064 //\r
1065 // The data in the packet are prepended with two UINT16 :\r
1066 // . OpCode = EFI_MTFTP4_OPCODE_DATA\r
1067 // . Block = the number of this block of data\r
1068 //\r
1069 Context->DownloadedNbOfBytes += PacketLen - sizeof (Packet->OpCode)\r
1070 - sizeof (Packet->Data.Block);\r
1071 NbOfKb = Context->DownloadedNbOfBytes / 1024;\r
1072\r
1073 Progress[0] = L'\0';\r
6add86ab
JC
1074 LastStep = (Context->LastReportedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;\r
1075 Step = (Context->DownloadedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;\r
1076\r
68074260
RC
1077 if (Step <= LastStep) {\r
1078 return EFI_SUCCESS;\r
1079 }\r
1080\r
1081 ShellPrintEx (-1, -1, L"%s", mTftpProgressDelete);\r
1082\r
da6b8feb
QS
1083 Status = StrCpyS (Progress, TFTP_PROGRESS_MESSAGE_SIZE, mTftpProgressFrame);\r
1084 if (EFI_ERROR(Status)) {\r
1085 return Status;\r
1086 }\r
68074260
RC
1087 for (Index = 1; Index < Step; Index++) {\r
1088 Progress[Index] = L'=';\r
1089 }\r
1090 Progress[Step] = L'>';\r
1091\r
1092 UnicodeSPrint (\r
1093 Progress + (sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 1,\r
1094 sizeof (Progress) - sizeof (mTftpProgressFrame),\r
1095 L" %7d Kb",\r
1096 NbOfKb\r
1097 );\r
1098 Context->LastReportedNbOfBytes = Context->DownloadedNbOfBytes;\r
1099\r
1100 ShellPrintEx (-1, -1, L"%s", Progress);\r
1101\r
1102 return EFI_SUCCESS;\r
1103}\r
09610023
RN
1104\r
1105/**\r
1106 Retrive HII package list from ImageHandle and publish to HII database.\r
1107\r
1108 @param ImageHandle The image handle of the process.\r
1109\r
1110 @return HII handle.\r
1111**/\r
1112EFI_HANDLE\r
1113InitializeHiiPackage (\r
1114 EFI_HANDLE ImageHandle\r
1115 )\r
1116{\r
1117 EFI_STATUS Status;\r
1118 EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
1119 EFI_HANDLE HiiHandle;\r
1120\r
1121 //\r
1122 // Retrieve HII package list from ImageHandle\r
1123 //\r
1124 Status = gBS->OpenProtocol (\r
1125 ImageHandle,\r
1126 &gEfiHiiPackageListProtocolGuid,\r
1127 (VOID **)&PackageList,\r
1128 ImageHandle,\r
1129 NULL,\r
1130 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1131 );\r
1132 ASSERT_EFI_ERROR (Status);\r
1133 if (EFI_ERROR (Status)) {\r
1134 return NULL;\r
1135 }\r
1136\r
1137 //\r
1138 // Publish HII package list to HII Database.\r
1139 //\r
1140 Status = gHiiDatabase->NewPackageList (\r
1141 gHiiDatabase,\r
1142 PackageList,\r
1143 NULL,\r
1144 &HiiHandle\r
1145 );\r
1146 ASSERT_EFI_ERROR (Status);\r
1147 if (EFI_ERROR (Status)) {\r
1148 return NULL;\r
1149 }\r
1150 return HiiHandle;\r
1151}\r