2 The implementation for Ping shell command.
4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "UefiShellNetwork1CommandsLib.h"
18 #define PING_IP4_COPY_ADDRESS(Dest, Src) (CopyMem ((Dest), (Src), sizeof (EFI_IPv4_ADDRESS)))
22 // Function templates to match the IPv4 and IPv6 commands that we use.
26 (EFIAPI
*PING_IPX_POLL
)(
32 (EFIAPI
*PING_IPX_TRANSMIT
)(
39 (EFIAPI
*PING_IPX_RECEIVE
)(
46 (EFIAPI
*PING_IPX_CANCEL
)(
48 IN VOID
*Token OPTIONAL
52 /// A set of pointers to either IPv6 or IPv4 functions.
53 /// Unknown which one to the ping command.
56 PING_IPX_TRANSMIT Transmit
;
57 PING_IPX_RECEIVE Receive
;
58 PING_IPX_CANCEL Cancel
;
69 // PING_IPX_COMPLETION_TOKEN
70 // structures are used for both transmit and receive operations.
71 // This version is IP-unaware.
77 } PING_IPX_COMPLETION_TOKEN
;
80 typedef struct _ICMPX_ECHO_REQUEST_REPLY
{
88 } ICMPX_ECHO_REQUEST_REPLY
;
91 typedef struct _PING_ICMP_TX_INFO
{
95 PING_IPX_COMPLETION_TOKEN
*Token
;
98 #define DEFAULT_TIMEOUT 5000
99 #define MAX_SEND_NUMBER 10000
100 #define MAX_BUFFER_SIZE 32768
101 #define DEFAULT_TIMER_PERIOD 358049
102 #define ONE_SECOND 10000000
103 #define PING_IP_CHOICE_IP4 1
104 #define PING_IP_CHOICE_IP6 2
105 #define DEFAULT_SEND_COUNT 10
106 #define DEFAULT_BUFFER_SIZE 16
107 #define ICMP_V4_ECHO_REQUEST 0x8
108 #define ICMP_V4_ECHO_REPLY 0x0
110 #define PING_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'i', 'n', 'g')
111 typedef struct _PING_PRIVATE_DATA
{
113 EFI_HANDLE NicHandle
;
114 EFI_HANDLE IpChildHandle
;
130 PING_IPX_PROTOCOL ProtocolPointers
;
132 UINT8 SrcAddress
[MAX(sizeof(EFI_IPv6_ADDRESS
) , sizeof(EFI_IPv4_ADDRESS
) )];
133 UINT8 DstAddress
[MAX(sizeof(EFI_IPv6_ADDRESS
) , sizeof(EFI_IPv4_ADDRESS
) )];
134 PING_IPX_COMPLETION_TOKEN RxToken
;
138 Calculate the internet checksum (see RFC 1071).
140 @param[in] Packet Buffer which contains the data to be checksummed.
141 @param[in] Length Length to be checksummed.
143 @retval Checksum Returns the 16 bit ones complement of
144 ones complement sum of 16 bit words
157 Packet
= (UINT16
*) Buffer
;
160 Odd
= (UINT8
) (Length
& 1);
162 while ((Length
--) != 0) {
167 Sum
+= *(UINT8
*) Packet
;
170 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
173 // in case above carried
181 Reads and returns the current value of register.
182 In IA64, the register is the Interval Timer Vector (ITV).
183 In X86(IA32/X64), the register is the Time Stamp Counter (TSC)
185 @return The current value of the register.
194 STATIC CONST SHELL_PARAM_ITEM PingParamList
[] = {
218 // Global Variables in Ping command.
220 STATIC CONST CHAR16
*mDstString
;
221 STATIC CONST CHAR16
*mSrcString
;
222 STATIC UINT64 mFrequency
= 0;
225 Get and caculate the frequency in tick/ms.
226 The result is saved in the globle variable mFrequency
228 @retval EFI_SUCCESS Caculated the frequency successfully.
229 @retval Others Failed to caculate the frequency.
239 EFI_CPU_ARCH_PROTOCOL
*Cpu
;
243 Status
= gBS
->LocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**) &Cpu
);
245 if (EFI_ERROR (Status
)) {
249 Status
= Cpu
->GetTimerValue (Cpu
, 0, &CurrentTick
, &TimerPeriod
);
251 if (EFI_ERROR (Status
)) {
252 TimerPeriod
= DEFAULT_TIMER_PERIOD
;
256 // The timer period is in femtosecond (1 femtosecond is 1e-15 second).
257 // So 1e+12 is divided by timer period to produce the freq in tick/ms.
259 mFrequency
= DivU64x64Remainder (1000000000000ULL, TimerPeriod
, NULL
);
265 Caculate a duration in ms.
267 @param[in] Begin The start point of time.
268 @param[in] End The end point of time.
270 @return The duration in ms.
271 @retval 0 The parameters were not valid.
283 return DivU64x64Remainder (End
- Begin
, mFrequency
, NULL
);
287 Destroy PING_ICMPX_TX_INFO, and recollect the memory.
289 @param[in] TxInfo The pointer to PING_ICMPX_TX_INFO.
290 @param[in] IpChoice Whether the token is IPv4 or IPv6
295 IN PING_ICMPX_TX_INFO
*TxInfo
,
299 EFI_IP6_TRANSMIT_DATA
*Ip6TxData
;
300 EFI_IP4_TRANSMIT_DATA
*Ip4TxData
;
301 EFI_IP6_FRAGMENT_DATA
*FragData
;
304 if (TxInfo
== NULL
) {
308 if (TxInfo
->Token
!= NULL
) {
310 if (TxInfo
->Token
->Event
!= NULL
) {
311 gBS
->CloseEvent (TxInfo
->Token
->Event
);
314 if (TxInfo
->Token
->Packet
.TxData
!= NULL
) {
315 if (IpChoice
== PING_IP_CHOICE_IP6
) {
316 Ip6TxData
= TxInfo
->Token
->Packet
.TxData
;
318 if (Ip6TxData
->OverrideData
!= NULL
) {
319 FreePool (Ip6TxData
->OverrideData
);
322 if (Ip6TxData
->ExtHdrs
!= NULL
) {
323 FreePool (Ip6TxData
->ExtHdrs
);
326 for (Index
= 0; Index
< Ip6TxData
->FragmentCount
; Index
++) {
327 FragData
= Ip6TxData
->FragmentTable
[Index
].FragmentBuffer
;
328 if (FragData
!= NULL
) {
333 Ip4TxData
= TxInfo
->Token
->Packet
.TxData
;
335 if (Ip4TxData
->OverrideData
!= NULL
) {
336 FreePool (Ip4TxData
->OverrideData
);
339 for (Index
= 0; Index
< Ip4TxData
->FragmentCount
; Index
++) {
340 FragData
= Ip4TxData
->FragmentTable
[Index
].FragmentBuffer
;
341 if (FragData
!= NULL
) {
348 FreePool (TxInfo
->Token
);
355 Match the request, and reply with SequenceNum/TimeStamp.
357 @param[in] Private The pointer to PING_PRIVATE_DATA.
358 @param[in] Packet The pointer to ICMPX_ECHO_REQUEST_REPLY.
360 @retval EFI_SUCCESS The match is successful.
361 @retval EFI_NOT_FOUND The reply can't be matched with any request.
366 Ping6MatchEchoReply (
367 IN PING_PRIVATE_DATA
*Private
,
368 IN ICMPX_ECHO_REQUEST_REPLY
*Packet
371 PING_ICMPX_TX_INFO
*TxInfo
;
373 LIST_ENTRY
*NextEntry
;
375 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &Private
->TxList
) {
376 TxInfo
= BASE_CR (Entry
, PING_ICMPX_TX_INFO
, Link
);
378 if ((TxInfo
->SequenceNum
== Packet
->SequenceNum
) && (TxInfo
->TimeStamp
== Packet
->TimeStamp
)) {
380 RemoveEntryList (&TxInfo
->Link
);
381 PingDestroyTxInfo (TxInfo
, Private
->IpChoice
);
386 return EFI_NOT_FOUND
;
390 The original intention is to send a request.
391 Currently, the application retransmits an icmp6 echo request packet
392 per second in sendnumber times that is specified by the user.
393 Because nothing can be done here, all things move to the timer rountine.
395 @param[in] Event A EFI_EVENT type event.
396 @param[in] Context The pointer to Context.
401 Ping6OnEchoRequestSent (
409 receive reply, match and print reply infomation.
411 @param[in] Event A EFI_EVENT type event.
412 @param[in] Context The pointer to context.
417 Ping6OnEchoReplyReceived (
423 PING_PRIVATE_DATA
*Private
;
424 ICMPX_ECHO_REQUEST_REPLY
*Reply
;
429 Private
= (PING_PRIVATE_DATA
*) Context
;
431 if (Private
== NULL
|| Private
->Status
== EFI_ABORTED
|| Private
->Signature
!= PING_PRIVATE_DATA_SIGNATURE
) {
435 if (Private
->RxToken
.Packet
.RxData
== NULL
) {
439 if (Private
->IpChoice
== PING_IP_CHOICE_IP6
) {
440 Reply
= ((EFI_IP6_RECEIVE_DATA
*)Private
->RxToken
.Packet
.RxData
)->FragmentTable
[0].FragmentBuffer
;
441 PayLoad
= ((EFI_IP6_RECEIVE_DATA
*)Private
->RxToken
.Packet
.RxData
)->DataLength
;
442 if (((EFI_IP6_RECEIVE_DATA
*)Private
->RxToken
.Packet
.RxData
)->Header
->NextHeader
!= IP6_ICMP
) {
445 if (!IP6_IS_MULTICAST ((EFI_IPv6_ADDRESS
*)&Private
->DstAddress
) &&
446 !EFI_IP6_EQUAL (&((EFI_IP6_RECEIVE_DATA
*)Private
->RxToken
.Packet
.RxData
)->Header
->SourceAddress
, (EFI_IPv6_ADDRESS
*)&Private
->DstAddress
)) {
450 if ((Reply
->Type
!= ICMP_V6_ECHO_REPLY
) || (Reply
->Code
!= 0)) {
454 Reply
= ((EFI_IP4_RECEIVE_DATA
*)Private
->RxToken
.Packet
.RxData
)->FragmentTable
[0].FragmentBuffer
;
455 PayLoad
= ((EFI_IP4_RECEIVE_DATA
*)Private
->RxToken
.Packet
.RxData
)->DataLength
;
456 if (!IP4_IS_MULTICAST (EFI_IP4(*(EFI_IPv4_ADDRESS
*)Private
->DstAddress
)) &&
457 !EFI_IP4_EQUAL (&((EFI_IP4_RECEIVE_DATA
*)Private
->RxToken
.Packet
.RxData
)->Header
->SourceAddress
, (EFI_IPv4_ADDRESS
*)&Private
->DstAddress
)) {
461 if ((Reply
->Type
!= ICMP_V4_ECHO_REPLY
) || (Reply
->Code
!= 0)) {
467 if (PayLoad
!= Private
->BufferSize
) {
471 // Check whether the reply matches the sent request before.
473 Status
= Ping6MatchEchoReply (Private
, Reply
);
474 if (EFI_ERROR(Status
)) {
478 // Display statistics on this icmp6 echo reply packet.
480 Rtt
= CalculateTick (Reply
->TimeStamp
, ReadTime ());
487 Private
->RttSum
+= Rtt
;
488 Private
->RttMin
= Private
->RttMin
> Rtt
? Rtt
: Private
->RttMin
;
489 Private
->RttMax
= Private
->RttMax
< Rtt
? Rtt
: Private
->RttMax
;
495 STRING_TOKEN (STR_PING_REPLY_INFO
),
496 gShellNetwork1HiiHandle
,
500 Private
->IpChoice
== PING_IP_CHOICE_IP6
?((EFI_IP6_RECEIVE_DATA
*)Private
->RxToken
.Packet
.RxData
)->Header
->HopLimit
:0,
507 if (Private
->RxCount
< Private
->SendNum
) {
509 // Continue to receive icmp echo reply packets.
511 Private
->RxToken
.Status
= EFI_ABORTED
;
513 Status
= Private
->ProtocolPointers
.Receive (Private
->IpProtocol
, &Private
->RxToken
);
515 if (EFI_ERROR (Status
)) {
516 Private
->Status
= EFI_ABORTED
;
520 // All reply have already been received from the dest host.
522 Private
->Status
= EFI_SUCCESS
;
525 // Singal to recycle the each rxdata here, not at the end of process.
527 gBS
->SignalEvent (Private
->IpChoice
== PING_IP_CHOICE_IP6
?((EFI_IP6_RECEIVE_DATA
*)Private
->RxToken
.Packet
.RxData
)->RecycleSignal
:((EFI_IP4_RECEIVE_DATA
*)Private
->RxToken
.Packet
.RxData
)->RecycleSignal
);
531 Create a PING_IPX_COMPLETION_TOKEN.
533 @param[in] Private The pointer of PING_PRIVATE_DATA.
534 @param[in] TimeStamp The TimeStamp of request.
535 @param[in] SequenceNum The SequenceNum of request.
537 @return The pointer of PING_IPX_COMPLETION_TOKEN.
540 PING_IPX_COMPLETION_TOKEN
*
543 IN PING_PRIVATE_DATA
*Private
,
545 IN UINT16 SequenceNum
549 PING_IPX_COMPLETION_TOKEN
*Token
;
551 ICMPX_ECHO_REQUEST_REPLY
*Request
;
555 Request
= AllocateZeroPool (Private
->BufferSize
);
556 if (Request
== NULL
) {
559 TxData
= AllocateZeroPool (Private
->IpChoice
==PING_IP_CHOICE_IP6
?sizeof (EFI_IP6_TRANSMIT_DATA
):sizeof (EFI_IP4_TRANSMIT_DATA
));
560 if (TxData
== NULL
) {
564 Token
= AllocateZeroPool (sizeof (PING_IPX_COMPLETION_TOKEN
));
572 // Assembly echo request packet.
574 Request
->Type
= (UINT8
)(Private
->IpChoice
==PING_IP_CHOICE_IP6
?ICMP_V6_ECHO_REQUEST
:ICMP_V4_ECHO_REQUEST
);
576 Request
->SequenceNum
= SequenceNum
;
577 Request
->Identifier
= 0;
578 Request
->Checksum
= 0;
581 // Assembly token for transmit.
583 if (Private
->IpChoice
==PING_IP_CHOICE_IP6
) {
584 ((EFI_IP6_TRANSMIT_DATA
*)TxData
)->ExtHdrsLength
= 0;
585 ((EFI_IP6_TRANSMIT_DATA
*)TxData
)->ExtHdrs
= NULL
;
586 ((EFI_IP6_TRANSMIT_DATA
*)TxData
)->OverrideData
= 0;
587 ((EFI_IP6_TRANSMIT_DATA
*)TxData
)->DataLength
= Private
->BufferSize
;
588 ((EFI_IP6_TRANSMIT_DATA
*)TxData
)->FragmentCount
= 1;
589 ((EFI_IP6_TRANSMIT_DATA
*)TxData
)->FragmentTable
[0].FragmentBuffer
= (VOID
*) Request
;
590 ((EFI_IP6_TRANSMIT_DATA
*)TxData
)->FragmentTable
[0].FragmentLength
= Private
->BufferSize
;
592 ((EFI_IP4_TRANSMIT_DATA
*)TxData
)->OptionsLength
= 0;
593 ((EFI_IP4_TRANSMIT_DATA
*)TxData
)->OptionsBuffer
= NULL
;
594 ((EFI_IP4_TRANSMIT_DATA
*)TxData
)->OverrideData
= 0;
595 ((EFI_IP4_TRANSMIT_DATA
*)TxData
)->TotalDataLength
= Private
->BufferSize
;
596 ((EFI_IP4_TRANSMIT_DATA
*)TxData
)->FragmentCount
= 1;
597 ((EFI_IP4_TRANSMIT_DATA
*)TxData
)->FragmentTable
[0].FragmentBuffer
= (VOID
*) Request
;
598 ((EFI_IP4_TRANSMIT_DATA
*)TxData
)->FragmentTable
[0].FragmentLength
= Private
->BufferSize
;
599 ((EFI_IP4_TRANSMIT_DATA
*)TxData
)->DestinationAddress
.Addr
[0] = Private
->DstAddress
[0];
600 ((EFI_IP4_TRANSMIT_DATA
*)TxData
)->DestinationAddress
.Addr
[1] = Private
->DstAddress
[1];
601 ((EFI_IP4_TRANSMIT_DATA
*)TxData
)->DestinationAddress
.Addr
[2] = Private
->DstAddress
[2];
602 ((EFI_IP4_TRANSMIT_DATA
*)TxData
)->DestinationAddress
.Addr
[3] = Private
->DstAddress
[3];
604 HeadSum
= NetChecksum ((UINT8
*) Request
, Private
->BufferSize
);
605 Request
->TimeStamp
= TimeStamp
;
606 TempChecksum
= NetChecksum ((UINT8
*) &Request
->TimeStamp
, sizeof (UINT64
));
607 Request
->Checksum
= (UINT16
)(~NetAddChecksum (HeadSum
, TempChecksum
));
611 Token
->Status
= EFI_ABORTED
;
612 Token
->Packet
.TxData
= TxData
;
614 Status
= gBS
->CreateEvent (
617 Ping6OnEchoRequestSent
,
622 if (EFI_ERROR (Status
)) {
633 Transmit the PING_IPX_COMPLETION_TOKEN.
635 @param[in] Private The pointer of PING_PRIVATE_DATA.
637 @retval EFI_SUCCESS Transmitted successfully.
638 @retval EFI_OUT_OF_RESOURCES No memory is available on the platform.
639 @retval others Transmitted unsuccessfully.
644 PingSendEchoRequest (
645 IN PING_PRIVATE_DATA
*Private
649 PING_ICMPX_TX_INFO
*TxInfo
;
651 TxInfo
= AllocateZeroPool (sizeof (PING_ICMPX_TX_INFO
));
653 if (TxInfo
== NULL
) {
654 return EFI_OUT_OF_RESOURCES
;
657 TxInfo
->TimeStamp
= ReadTime ();
658 TxInfo
->SequenceNum
= (UINT16
) (Private
->TxCount
+ 1);
659 TxInfo
->Token
= PingGenerateToken (
665 if (TxInfo
->Token
== NULL
) {
666 PingDestroyTxInfo (TxInfo
, Private
->IpChoice
);
667 return EFI_OUT_OF_RESOURCES
;
670 ASSERT(Private
->ProtocolPointers
.Transmit
!= NULL
);
671 Status
= Private
->ProtocolPointers
.Transmit (Private
->IpProtocol
, TxInfo
->Token
);
673 if (EFI_ERROR (Status
)) {
674 PingDestroyTxInfo (TxInfo
, Private
->IpChoice
);
678 InsertTailList (&Private
->TxList
, &TxInfo
->Link
);
685 Place a completion token into the receive packet queue to receive the echo reply.
687 @param[in] Private The pointer of PING_PRIVATE_DATA.
689 @retval EFI_SUCCESS Put the token into the receive packet queue successfully.
690 @retval others Put the token into the receive packet queue unsuccessfully.
695 Ping6ReceiveEchoReply (
696 IN PING_PRIVATE_DATA
*Private
701 ZeroMem (&Private
->RxToken
, sizeof (PING_IPX_COMPLETION_TOKEN
));
703 Status
= gBS
->CreateEvent (
706 Ping6OnEchoReplyReceived
,
708 &Private
->RxToken
.Event
711 if (EFI_ERROR (Status
)) {
715 Private
->RxToken
.Status
= EFI_NOT_READY
;
717 return (Private
->ProtocolPointers
.Receive (Private
->IpProtocol
, &Private
->RxToken
));
721 Remove the timeout request from the list.
723 @param[in] Event A EFI_EVENT type event.
724 @param[in] Context The pointer to Context.
729 Ping6OnTimerRoutine (
735 PING_PRIVATE_DATA
*Private
;
736 PING_ICMPX_TX_INFO
*TxInfo
;
738 LIST_ENTRY
*NextEntry
;
741 Private
= (PING_PRIVATE_DATA
*) Context
;
742 if (Private
->Signature
!= PING_PRIVATE_DATA_SIGNATURE
) {
743 Private
->Status
= EFI_NOT_FOUND
;
748 // Retransmit icmp6 echo request packets per second in sendnumber times.
750 if (Private
->TxCount
< Private
->SendNum
) {
752 Status
= PingSendEchoRequest (Private
);
753 if (Private
->TxCount
!= 0){
754 if (EFI_ERROR (Status
)) {
755 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_PING_SEND_REQUEST
), gShellNetwork1HiiHandle
, Private
->TxCount
+ 1);
760 // Check whether any icmp6 echo request in the list timeout.
762 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &Private
->TxList
) {
763 TxInfo
= BASE_CR (Entry
, PING_ICMPX_TX_INFO
, Link
);
764 Time
= CalculateTick (TxInfo
->TimeStamp
, ReadTime ());
767 // Remove the timeout echo request from txlist.
769 if (Time
> DEFAULT_TIMEOUT
) {
771 if (EFI_ERROR (TxInfo
->Token
->Status
)) {
772 Private
->ProtocolPointers
.Cancel (Private
->IpProtocol
, TxInfo
->Token
);
775 // Remove the timeout icmp6 echo request from list.
777 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_PING_TIMEOUT
), gShellNetwork1HiiHandle
, TxInfo
->SequenceNum
);
779 RemoveEntryList (&TxInfo
->Link
);
780 PingDestroyTxInfo (TxInfo
, Private
->IpChoice
);
783 // We dont need to wait for this some other time...
787 if (IsListEmpty (&Private
->TxList
) && (Private
->TxCount
== Private
->SendNum
)) {
789 // All the left icmp6 echo request in the list timeout.
791 Private
->Status
= EFI_TIMEOUT
;
798 Determine if a IP4 address is Link Local.
800 169.254.1.0 through 169.254.254.255 is link local.
802 @param[in] Address The address to test.
805 @retval FALSE It is not.
809 PingNetIp4IsLinkLocalAddr (
810 IN CONST EFI_IPv4_ADDRESS
*Address
813 return ((BOOLEAN
)(Address
->Addr
[0] == 169 && Address
->Addr
[1] == 254 && Address
->Addr
[2] >= 1 && Address
->Addr
[2] <= 254));
817 Determine if a IP4 address is unspecified.
819 @param[in] Address The address to test.
822 @retval FALSE It is not.
826 PingNetIp4IsUnspecifiedAddr (
827 IN CONST EFI_IPv4_ADDRESS
*Address
830 return ((BOOLEAN
)((ReadUnaligned32 ((UINT32
*)&Address
->Addr
[0])) == 0x00000000));
834 Create a valid IP instance.
836 @param[in] Private The pointer of PING_PRIVATE_DATA.
838 @retval EFI_SUCCESS Create a valid IPx instance successfully.
839 @retval EFI_ABORTED Locate handle with ipx service binding protocol unsuccessfully.
840 @retval EFI_INVALID_PARAMETER The source address is unspecified when the destination address is a link-local address.
841 @retval EFI_OUT_OF_RESOURCES No memory is available on the platform.
842 @retval EFI_NOT_FOUND The source address is not found.
846 PingCreateIpInstance (
847 IN PING_PRIVATE_DATA
*Private
853 EFI_HANDLE
*HandleBuffer
;
854 EFI_SERVICE_BINDING_PROTOCOL
*EfiSb
;
856 EFI_IP6_CONFIG_DATA Ip6Config
;
857 EFI_IP4_CONFIG_DATA Ip4Config
;
858 VOID
*IpXInterfaceInfo
;
860 EFI_IPv6_ADDRESS
*Addr
;
865 IpXInterfaceInfo
= NULL
;
869 // Locate all the handles with ip6 service binding protocol.
871 Status
= gBS
->LocateHandleBuffer (
873 Private
->IpChoice
== PING_IP_CHOICE_IP6
?&gEfiIp6ServiceBindingProtocolGuid
:&gEfiIp4ServiceBindingProtocolGuid
,
878 if (EFI_ERROR (Status
) || (HandleNum
== 0) || (HandleBuffer
== NULL
)) {
882 // Source address is required when pinging a link-local address on multi-
885 if (Private
->IpChoice
== PING_IP_CHOICE_IP6
) {
886 if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS
*)&Private
->DstAddress
) &&
887 NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS
*)&Private
->SrcAddress
) &&
889 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellNetwork1HiiHandle
, mSrcString
);
890 Status
= EFI_INVALID_PARAMETER
;
894 ASSERT(Private
->IpChoice
== PING_IP_CHOICE_IP4
);
895 if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS
*)&Private
->DstAddress
) &&
896 PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS
*)&Private
->SrcAddress
) &&
898 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellNetwork1HiiHandle
, mSrcString
);
899 Status
= EFI_INVALID_PARAMETER
;
904 // For each ip6 protocol, check interface addresses list.
906 for (HandleIndex
= 0; HandleIndex
< HandleNum
; HandleIndex
++) {
909 IpXInterfaceInfo
= NULL
;
912 Status
= gBS
->HandleProtocol (
913 HandleBuffer
[HandleIndex
],
914 Private
->IpChoice
== PING_IP_CHOICE_IP6
?&gEfiIp6ServiceBindingProtocolGuid
:&gEfiIp4ServiceBindingProtocolGuid
,
917 if (EFI_ERROR (Status
)) {
921 if (Private
->IpChoice
== PING_IP_CHOICE_IP6
?NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS
*)&Private
->SrcAddress
):PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS
*)&Private
->SrcAddress
)) {
923 // No need to match interface address.
928 // Ip6config protocol and ip6 service binding protocol are installed
929 // on the same handle.
931 Status
= gBS
->HandleProtocol (
932 HandleBuffer
[HandleIndex
],
933 Private
->IpChoice
== PING_IP_CHOICE_IP6
?&gEfiIp6ConfigProtocolGuid
:&gEfiIp4ConfigProtocolGuid
,
937 if (EFI_ERROR (Status
)) {
941 // Get the interface information size.
943 if (Private
->IpChoice
== PING_IP_CHOICE_IP6
) {
944 Status
= ((EFI_IP6_CONFIG_PROTOCOL
*)IpXCfg
)->GetData (
946 Ip6ConfigDataTypeInterfaceInfo
,
951 Status
= ((EFI_IP4_CONFIG_PROTOCOL
*)IpXCfg
)->GetData (
959 // Skip the ones not in current use.
961 if (Status
== EFI_NOT_STARTED
) {
965 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
966 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_PING_GETDATA
), gShellNetwork1HiiHandle
, Status
);
970 IpXInterfaceInfo
= AllocateZeroPool (IfInfoSize
);
972 if (IpXInterfaceInfo
== NULL
) {
973 Status
= EFI_OUT_OF_RESOURCES
;
977 // Get the interface info.
979 if (Private
->IpChoice
== PING_IP_CHOICE_IP6
) {
980 Status
= ((EFI_IP6_CONFIG_PROTOCOL
*)IpXCfg
)->GetData (
982 Ip6ConfigDataTypeInterfaceInfo
,
987 Status
= ((EFI_IP4_CONFIG_PROTOCOL
*)IpXCfg
)->GetData (
994 if (EFI_ERROR (Status
)) {
995 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_PING_GETDATA
), gShellNetwork1HiiHandle
, Status
);
999 // Check whether the source address is one of the interface addresses.
1001 if (Private
->IpChoice
== PING_IP_CHOICE_IP6
) {
1002 for (AddrIndex
= 0; AddrIndex
< ((EFI_IP6_CONFIG_INTERFACE_INFO
*)IpXInterfaceInfo
)->AddressInfoCount
; AddrIndex
++) {
1004 Addr
= &(((EFI_IP6_CONFIG_INTERFACE_INFO
*)IpXInterfaceInfo
)->AddressInfo
[AddrIndex
].Address
);
1005 if (EFI_IP6_EQUAL (&Private
->SrcAddress
, Addr
)) {
1007 // Match a certain interface address.
1013 if (AddrIndex
< ((EFI_IP6_CONFIG_INTERFACE_INFO
*)IpXInterfaceInfo
)->AddressInfoCount
) {
1015 // Found a nic handle with right interface address.
1021 // IP4 address check
1023 if (EFI_IP4_EQUAL (&Private
->SrcAddress
, &((EFI_IP4_IPCONFIG_DATA
*)IpXInterfaceInfo
)->StationAddress
)) {
1025 // Match a certain interface address.
1032 FreePool (IpXInterfaceInfo
);
1033 IpXInterfaceInfo
= NULL
;
1036 // No exact interface address matched.
1039 if (HandleIndex
== HandleNum
) {
1040 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellNetwork1HiiHandle
, mSrcString
);
1041 Status
= EFI_NOT_FOUND
;
1045 Private
->NicHandle
= HandleBuffer
[HandleIndex
];
1047 ASSERT (EfiSb
!= NULL
);
1048 Status
= EfiSb
->CreateChild (EfiSb
, &Private
->IpChildHandle
);
1050 if (EFI_ERROR (Status
)) {
1053 if (Private
->IpChoice
== PING_IP_CHOICE_IP6
) {
1054 Status
= gBS
->OpenProtocol (
1055 Private
->IpChildHandle
,
1056 &gEfiIp6ProtocolGuid
,
1057 &Private
->IpProtocol
,
1059 Private
->IpChildHandle
,
1060 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1062 if (EFI_ERROR (Status
)) {
1067 ZeroMem (&Ip6Config
, sizeof (EFI_IP6_CONFIG_DATA
));
1070 // Configure the ip6 instance for icmp6 packet exchange.
1072 Ip6Config
.DefaultProtocol
= 58;
1073 Ip6Config
.AcceptAnyProtocol
= FALSE
;
1074 Ip6Config
.AcceptIcmpErrors
= TRUE
;
1075 Ip6Config
.AcceptPromiscuous
= FALSE
;
1076 Ip6Config
.TrafficClass
= 0;
1077 Ip6Config
.HopLimit
= 128;
1078 Ip6Config
.FlowLabel
= 0;
1079 Ip6Config
.ReceiveTimeout
= 0;
1080 Ip6Config
.TransmitTimeout
= 0;
1082 IP6_COPY_ADDRESS (&Ip6Config
.StationAddress
, &Private
->SrcAddress
);
1083 IP6_COPY_ADDRESS (&Ip6Config
.DestinationAddress
, &Private
->DstAddress
);
1085 Status
= ((EFI_IP6_PROTOCOL
*)(Private
->IpProtocol
))->Configure (Private
->IpProtocol
, &Ip6Config
);
1087 if (EFI_ERROR (Status
)) {
1088 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_PING_CONFIG
), gShellNetwork1HiiHandle
, Status
);
1092 Private
->ProtocolPointers
.Transmit
= (PING_IPX_TRANSMIT
)((EFI_IP6_PROTOCOL
*)Private
->IpProtocol
)->Transmit
;
1093 Private
->ProtocolPointers
.Receive
= (PING_IPX_RECEIVE
)((EFI_IP6_PROTOCOL
*)Private
->IpProtocol
)->Receive
;
1094 Private
->ProtocolPointers
.Cancel
= (PING_IPX_CANCEL
)((EFI_IP6_PROTOCOL
*)Private
->IpProtocol
)->Cancel
;
1095 Private
->ProtocolPointers
.Poll
= (PING_IPX_POLL
)((EFI_IP6_PROTOCOL
*)Private
->IpProtocol
)->Poll
;
1097 Status
= gBS
->OpenProtocol (
1098 Private
->IpChildHandle
,
1099 &gEfiIp4ProtocolGuid
,
1100 &Private
->IpProtocol
,
1102 Private
->IpChildHandle
,
1103 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1105 if (EFI_ERROR (Status
)) {
1110 ZeroMem (&Ip4Config
, sizeof (EFI_IP4_CONFIG_DATA
));
1113 // Configure the ip4 instance for icmp4 packet exchange.
1115 // PING_IP4_COPY_ADDRESS (&Ip4Config.StationAddress, &Private->SrcAddress);
1116 // Ip4Config.SubnetMask.Addr[0] = 0xFF;
1117 // Ip4Config.SubnetMask.Addr[1] = 0xFF;
1118 // Ip4Config.SubnetMask.Addr[2] = 0xFF;
1119 // Ip4Config.SubnetMask.Addr[3] = 0x00;
1120 Ip4Config
.DefaultProtocol
= 1;
1121 Ip4Config
.AcceptAnyProtocol
= FALSE
;
1122 Ip4Config
.AcceptBroadcast
= FALSE
;
1123 Ip4Config
.AcceptIcmpErrors
= TRUE
;
1124 Ip4Config
.AcceptPromiscuous
= FALSE
;
1125 Ip4Config
.DoNotFragment
= FALSE
;
1126 Ip4Config
.RawData
= FALSE
;
1127 Ip4Config
.ReceiveTimeout
= 0;
1128 Ip4Config
.TransmitTimeout
= 0;
1129 Ip4Config
.UseDefaultAddress
= TRUE
;
1130 Ip4Config
.TimeToLive
= 128;
1131 Ip4Config
.TypeOfService
= 0;
1133 Status
= ((EFI_IP4_PROTOCOL
*)(Private
->IpProtocol
))->Configure (Private
->IpProtocol
, &Ip4Config
);
1135 if (EFI_ERROR (Status
)) {
1136 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_PING_CONFIG
), gShellNetwork1HiiHandle
, Status
);
1140 Private
->ProtocolPointers
.Transmit
= (PING_IPX_TRANSMIT
)((EFI_IP4_PROTOCOL
*)Private
->IpProtocol
)->Transmit
;
1141 Private
->ProtocolPointers
.Receive
= (PING_IPX_RECEIVE
)((EFI_IP4_PROTOCOL
*)Private
->IpProtocol
)->Receive
;
1142 Private
->ProtocolPointers
.Cancel
= (PING_IPX_CANCEL
)((EFI_IP4_PROTOCOL
*)Private
->IpProtocol
)->Cancel
;
1143 Private
->ProtocolPointers
.Poll
= (PING_IPX_POLL
)((EFI_IP4_PROTOCOL
*)Private
->IpProtocol
)->Poll
;
1146 if (HandleBuffer
!= NULL
) {
1147 FreePool (HandleBuffer
);
1153 if (HandleBuffer
!= NULL
) {
1154 FreePool (HandleBuffer
);
1157 if (IpXInterfaceInfo
!= NULL
) {
1158 FreePool (IpXInterfaceInfo
);
1161 if ((EfiSb
!= NULL
) && (Private
->IpChildHandle
!= NULL
)) {
1162 EfiSb
->DestroyChild (EfiSb
, Private
->IpChildHandle
);
1169 Destory the IP instance.
1171 @param[in] Private The pointer of PING_PRIVATE_DATA.
1176 Ping6DestoryIp6Instance (
1177 IN PING_PRIVATE_DATA
*Private
1181 EFI_SERVICE_BINDING_PROTOCOL
*IpSb
;
1183 gBS
->CloseProtocol (
1184 Private
->IpChildHandle
,
1185 Private
->IpChoice
== PING_IP_CHOICE_IP6
?&gEfiIp6ProtocolGuid
:&gEfiIp4ProtocolGuid
,
1187 Private
->IpChildHandle
1190 Status
= gBS
->HandleProtocol (
1192 Private
->IpChoice
== PING_IP_CHOICE_IP6
?&gEfiIp6ServiceBindingProtocolGuid
:&gEfiIp4ServiceBindingProtocolGuid
,
1196 if (!EFI_ERROR(Status
)) {
1197 IpSb
->DestroyChild (IpSb
, Private
->IpChildHandle
);
1204 @param[in] SendNumber The send request count.
1205 @param[in] BufferSize The send buffer size.
1206 @param[in] SrcAddress The source address.
1207 @param[in] DstAddress The destination address.
1208 @param[in] IpChoice The choice between IPv4 and IPv6.
1210 @retval SHELL_SUCCESS The ping processed successfullly.
1211 @retval others The ping processed unsuccessfully.
1216 IN UINT32 SendNumber
,
1217 IN UINT32 BufferSize
,
1218 IN EFI_IPv6_ADDRESS
*SrcAddress
,
1219 IN EFI_IPv6_ADDRESS
*DstAddress
,
1224 PING_PRIVATE_DATA
*Private
;
1225 PING_ICMPX_TX_INFO
*TxInfo
;
1227 LIST_ENTRY
*NextEntry
;
1228 SHELL_STATUS ShellStatus
;
1230 ShellStatus
= SHELL_SUCCESS
;
1231 Private
= AllocateZeroPool (sizeof (PING_PRIVATE_DATA
));
1233 if (Private
== NULL
) {
1234 return (SHELL_OUT_OF_RESOURCES
);
1237 Private
->IpChoice
= IpChoice
;
1238 Private
->Signature
= PING_PRIVATE_DATA_SIGNATURE
;
1239 Private
->SendNum
= SendNumber
;
1240 Private
->BufferSize
= BufferSize
;
1241 Private
->RttMin
= ~((UINT64
)(0x0));
1242 Private
->Status
= EFI_NOT_READY
;
1244 CopyMem(&Private
->SrcAddress
, SrcAddress
, sizeof(Private
->SrcAddress
));
1245 CopyMem(&Private
->DstAddress
, DstAddress
, sizeof(Private
->DstAddress
));
1247 InitializeListHead (&Private
->TxList
);
1250 // Open and configure a ip instance for us.
1252 Status
= PingCreateIpInstance (Private
);
1254 if (EFI_ERROR (Status
)) {
1255 ShellStatus
= SHELL_ACCESS_DENIED
;
1259 // Print the command line itself.
1261 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_PING_START
), gShellNetwork1HiiHandle
, mDstString
, Private
->BufferSize
);
1263 // Create a ipv6 token to receive the first icmp6 echo reply packet.
1265 Status
= Ping6ReceiveEchoReply (Private
);
1267 if (EFI_ERROR (Status
)) {
1268 ShellStatus
= SHELL_ACCESS_DENIED
;
1272 // Create and start timer to send icmp6 echo request packet per second.
1274 Status
= gBS
->CreateEvent (
1275 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1277 Ping6OnTimerRoutine
,
1282 if (EFI_ERROR (Status
)) {
1283 ShellStatus
= SHELL_ACCESS_DENIED
;
1287 // Create a ipv6 token to send the first icmp6 echo request packet.
1289 Status
= PingSendEchoRequest (Private
);
1291 // EFI_NOT_READY for IPsec is enable and IKE is not established.
1293 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_READY
)) {
1294 ShellStatus
= SHELL_ACCESS_DENIED
;
1295 if(Status
== EFI_NOT_FOUND
) {
1296 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_PING_NOSOURCE_INDO
), gShellNetwork1HiiHandle
, mDstString
);
1297 } else if (Status
== RETURN_NO_MAPPING
) {
1298 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_PING_NOROUTE_FOUND
), gShellNetwork1HiiHandle
, mDstString
, mSrcString
);
1300 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_PING_NETWORK_ERROR
), gShellNetwork1HiiHandle
, Status
);
1306 Status
= gBS
->SetTimer (
1312 if (EFI_ERROR (Status
)) {
1313 ShellStatus
= SHELL_ACCESS_DENIED
;
1317 // Control the ping6 process by two factors:
1319 // 2. Private->Status
1320 // 2.1. success means all icmp6 echo request packets get reply packets.
1321 // 2.2. timeout means the last icmp6 echo reply request timeout to get reply.
1322 // 2.3. noready means ping6 process is on-the-go.
1324 while (Private
->Status
== EFI_NOT_READY
) {
1325 Status
= Private
->ProtocolPointers
.Poll (Private
->IpProtocol
);
1326 if (ShellGetExecutionBreakFlag()) {
1327 Private
->Status
= EFI_ABORTED
;
1334 // Display the statistics in all.
1336 gBS
->SetTimer (Private
->Timer
, TimerCancel
, 0);
1338 if (Private
->TxCount
!= 0) {
1343 STRING_TOKEN (STR_PING_STAT
),
1344 gShellNetwork1HiiHandle
,
1347 (100 * (Private
->TxCount
- Private
->RxCount
)) / Private
->TxCount
,
1352 if (Private
->RxCount
!= 0) {
1357 STRING_TOKEN (STR_PING_RTT
),
1358 gShellNetwork1HiiHandle
,
1361 DivU64x64Remainder (Private
->RttSum
, Private
->RxCount
, NULL
)
1367 if (Private
!= NULL
) {
1369 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &Private
->TxList
) {
1370 TxInfo
= BASE_CR (Entry
, PING_ICMPX_TX_INFO
, Link
);
1372 if (Private
->IpProtocol
!= NULL
&& Private
->ProtocolPointers
.Cancel
!= NULL
) {
1373 Status
= Private
->ProtocolPointers
.Cancel (Private
->IpProtocol
, TxInfo
->Token
);
1376 RemoveEntryList (&TxInfo
->Link
);
1377 PingDestroyTxInfo (TxInfo
, Private
->IpChoice
);
1380 if (Private
->Timer
!= NULL
) {
1381 gBS
->CloseEvent (Private
->Timer
);
1384 if (Private
->IpProtocol
!= NULL
&& Private
->ProtocolPointers
.Cancel
!= NULL
) {
1385 Status
= Private
->ProtocolPointers
.Cancel (Private
->IpProtocol
, &Private
->RxToken
);
1388 if (Private
->RxToken
.Event
!= NULL
) {
1389 gBS
->CloseEvent (Private
->RxToken
.Event
);
1392 if (Private
->IpChildHandle
!= NULL
) {
1393 Ping6DestoryIp6Instance (Private
);
1403 Function for 'ping' command.
1405 @param[in] ImageHandle Handle to the Image (NULL if Internal).
1406 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
1410 ShellCommandRunPing (
1411 IN EFI_HANDLE ImageHandle
,
1412 IN EFI_SYSTEM_TABLE
*SystemTable
1416 SHELL_STATUS ShellStatus
;
1417 EFI_IPv6_ADDRESS DstAddress
;
1418 EFI_IPv6_ADDRESS SrcAddress
;
1421 LIST_ENTRY
*ParamPackage
;
1422 CONST CHAR16
*ValueStr
;
1423 UINTN NonOptionCount
;
1427 // we use IPv6 buffers to hold items...
1428 // make sure this is enough space!
1430 ASSERT(sizeof(EFI_IPv4_ADDRESS
) <= sizeof(EFI_IPv6_ADDRESS
));
1431 ASSERT(sizeof(EFI_IP4_COMPLETION_TOKEN
) <= sizeof(EFI_IP6_COMPLETION_TOKEN
));
1433 IpChoice
= PING_IP_CHOICE_IP4
;
1435 ShellStatus
= SHELL_SUCCESS
;
1437 Status
= ShellCommandLineParseEx (PingParamList
, &ParamPackage
, NULL
, TRUE
, FALSE
);
1438 if (EFI_ERROR(Status
)) {
1439 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellNetwork1HiiHandle
);
1440 ShellStatus
= SHELL_INVALID_PARAMETER
;
1444 if (ShellCommandLineGetFlag (ParamPackage
, L
"-_ip6")) {
1445 IpChoice
= PING_IP_CHOICE_IP6
;
1449 // Parse the paramter of count number.
1451 ValueStr
= ShellCommandLineGetValue (ParamPackage
, L
"-n");
1452 if (ValueStr
!= NULL
) {
1453 SendNumber
= ShellStrToUintn (ValueStr
);
1456 // ShellStrToUintn will return 0 when input is 0 or an invalid input string.
1458 if ((SendNumber
== 0) || (SendNumber
> MAX_SEND_NUMBER
)) {
1459 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellNetwork1HiiHandle
, ValueStr
);
1460 ShellStatus
= SHELL_INVALID_PARAMETER
;
1464 SendNumber
= DEFAULT_SEND_COUNT
;
1467 // Parse the paramter of buffer size.
1469 ValueStr
= ShellCommandLineGetValue (ParamPackage
, L
"-l");
1470 if (ValueStr
!= NULL
) {
1471 BufferSize
= ShellStrToUintn (ValueStr
);
1474 // ShellStrToUintn will return 0 when input is 0 or an invalid input string.
1476 if ((BufferSize
< 16) || (BufferSize
> MAX_BUFFER_SIZE
)) {
1477 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellNetwork1HiiHandle
, ValueStr
);
1478 ShellStatus
= SHELL_INVALID_PARAMETER
;
1482 BufferSize
= DEFAULT_BUFFER_SIZE
;
1485 ZeroMem (&SrcAddress
, sizeof (EFI_IPv6_ADDRESS
));
1486 ZeroMem (&DstAddress
, sizeof (EFI_IPv6_ADDRESS
));
1489 // Parse the paramter of source ip address.
1491 ValueStr
= ShellCommandLineGetValue (ParamPackage
, L
"-_s");
1492 if (ValueStr
!= NULL
) {
1493 mSrcString
= ValueStr
;
1494 if (IpChoice
== PING_IP_CHOICE_IP6
) {
1495 Status
= NetLibStrToIp6 (ValueStr
, &SrcAddress
);
1497 Status
= NetLibStrToIp4 (ValueStr
, (EFI_IPv4_ADDRESS
*)&SrcAddress
);
1499 if (EFI_ERROR (Status
)) {
1500 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellNetwork1HiiHandle
, ValueStr
);
1501 ShellStatus
= SHELL_INVALID_PARAMETER
;
1506 // Parse the paramter of destination ip address.
1508 NonOptionCount
= ShellCommandLineGetCount(ParamPackage
);
1509 if (NonOptionCount
< 2) {
1510 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellNetwork1HiiHandle
);
1511 ShellStatus
= SHELL_INVALID_PARAMETER
;
1514 if (NonOptionCount
> 2) {
1515 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellNetwork1HiiHandle
);
1516 ShellStatus
= SHELL_INVALID_PARAMETER
;
1519 ValueStr
= ShellCommandLineGetRawValue (ParamPackage
, 1);
1520 if (ValueStr
!= NULL
) {
1521 mDstString
= ValueStr
;
1522 if (IpChoice
== PING_IP_CHOICE_IP6
) {
1523 Status
= NetLibStrToIp6 (ValueStr
, &DstAddress
);
1525 Status
= NetLibStrToIp4 (ValueStr
, (EFI_IPv4_ADDRESS
*)&DstAddress
);
1527 if (EFI_ERROR (Status
)) {
1528 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellNetwork1HiiHandle
, ValueStr
);
1529 ShellStatus
= SHELL_INVALID_PARAMETER
;
1534 // Get frequency to calculate the time from ticks.
1536 Status
= GetFrequency ();
1538 if (EFI_ERROR(Status
)) {
1542 // Enter into ping process.
1544 ShellStatus
= ShellPing (
1553 ShellCommandLineFreeVarList (ParamPackage
);