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