]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
ShellPkg/Dp: Add null pointer check
[mirror_edk2.git] / ShellPkg / Library / UefiShellNetwork1CommandsLib / Ping.c
index 10d38d80227c942a8caf0470ace2410b6f133d27..bec9535a8b436338c91e94290fde58a900e43804 100644 (file)
@@ -1,7 +1,9 @@
 /** @file\r
   The implementation for Ping shell command.\r
 \r
 /** @file\r
   The implementation for Ping shell command.\r
 \r
-  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
+  Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -17,6 +19,7 @@
 \r
 #define PING_IP4_COPY_ADDRESS(Dest, Src) (CopyMem ((Dest), (Src), sizeof (EFI_IPv4_ADDRESS)))\r
 \r
 \r
 #define PING_IP4_COPY_ADDRESS(Dest, Src) (CopyMem ((Dest), (Src), sizeof (EFI_IPv4_ADDRESS)))\r
 \r
+UINT64          mCurrentTick = 0;\r
 \r
 //\r
 // Function templates to match the IPv4 and IPv6 commands that we use.\r
 \r
 //\r
 // Function templates to match the IPv4 and IPv6 commands that we use.\r
@@ -83,7 +86,7 @@ typedef struct _ICMPX_ECHO_REQUEST_REPLY {
   UINT16                      Checksum;\r
   UINT16                      Identifier;\r
   UINT16                      SequenceNum;\r
   UINT16                      Checksum;\r
   UINT16                      Identifier;\r
   UINT16                      SequenceNum;\r
-  UINT64                      TimeStamp;\r
+  UINT32                      TimeStamp;\r
   UINT8                       Data[1];\r
 } ICMPX_ECHO_REQUEST_REPLY;\r
 #pragma pack()\r
   UINT8                       Data[1];\r
 } ICMPX_ECHO_REQUEST_REPLY;\r
 #pragma pack()\r
@@ -91,7 +94,7 @@ typedef struct _ICMPX_ECHO_REQUEST_REPLY {
 typedef struct _PING_ICMP_TX_INFO {\r
   LIST_ENTRY                Link;\r
   UINT16                    SequenceNum;\r
 typedef struct _PING_ICMP_TX_INFO {\r
   LIST_ENTRY                Link;\r
   UINT16                    SequenceNum;\r
-  UINT64                    TimeStamp;\r
+  UINT32                    TimeStamp;\r
   PING_IPX_COMPLETION_TOKEN *Token;\r
 } PING_ICMPX_TX_INFO;\r
 \r
   PING_IPX_COMPLETION_TOKEN *Token;\r
 } PING_ICMPX_TX_INFO;\r
 \r
@@ -106,6 +109,7 @@ typedef struct _PING_ICMP_TX_INFO {
 #define DEFAULT_BUFFER_SIZE   16\r
 #define ICMP_V4_ECHO_REQUEST  0x8\r
 #define ICMP_V4_ECHO_REPLY    0x0\r
 #define DEFAULT_BUFFER_SIZE   16\r
 #define ICMP_V4_ECHO_REQUEST  0x8\r
 #define ICMP_V4_ECHO_REPLY    0x0\r
+#define STALL_1_MILLI_SECOND  1000\r
 \r
 #define PING_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('P', 'i', 'n', 'g')\r
 typedef struct _PING_PRIVATE_DATA {\r
 \r
 #define PING_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('P', 'i', 'n', 'g')\r
 typedef struct _PING_PRIVATE_DATA {\r
@@ -114,6 +118,10 @@ typedef struct _PING_PRIVATE_DATA {
   EFI_HANDLE                  IpChildHandle;\r
   EFI_EVENT                   Timer;\r
 \r
   EFI_HANDLE                  IpChildHandle;\r
   EFI_EVENT                   Timer;\r
 \r
+  UINT32                      TimerPeriod;\r
+  UINT32                      RttTimerTick;   \r
+  EFI_EVENT                   RttTimer;\r
+\r
   EFI_STATUS                  Status;\r
   LIST_ENTRY                  TxList;\r
   UINT16                      RxCount;\r
   EFI_STATUS                  Status;\r
   LIST_ENTRY                  TxList;\r
   UINT16                      RxCount;\r
@@ -132,6 +140,7 @@ typedef struct _PING_PRIVATE_DATA {
   UINT8                       SrcAddress[MAX(sizeof(EFI_IPv6_ADDRESS)        , sizeof(EFI_IPv4_ADDRESS)          )];\r
   UINT8                       DstAddress[MAX(sizeof(EFI_IPv6_ADDRESS)        , sizeof(EFI_IPv4_ADDRESS)          )];\r
   PING_IPX_COMPLETION_TOKEN   RxToken;\r
   UINT8                       SrcAddress[MAX(sizeof(EFI_IPv6_ADDRESS)        , sizeof(EFI_IPv4_ADDRESS)          )];\r
   UINT8                       DstAddress[MAX(sizeof(EFI_IPv6_ADDRESS)        , sizeof(EFI_IPv4_ADDRESS)          )];\r
   PING_IPX_COMPLETION_TOKEN   RxToken;\r
+  UINT16                      FailedCount;\r
 } PING_PRIVATE_DATA;\r
 \r
 /**\r
 } PING_PRIVATE_DATA;\r
 \r
 /**\r
@@ -144,7 +153,6 @@ typedef struct _PING_PRIVATE_DATA {
                        ones complement sum of 16 bit words\r
 **/\r
 UINT16\r
                        ones complement sum of 16 bit words\r
 **/\r
 UINT16\r
-EFIAPI\r
 NetChecksum (\r
   IN UINT8   *Buffer,\r
   IN UINT32  Length\r
 NetChecksum (\r
   IN UINT8   *Buffer,\r
   IN UINT32  Length\r
@@ -195,6 +203,10 @@ STATIC CONST SHELL_PARAM_ITEM    PingParamList[] = {
     L"-n",\r
     TypeValue\r
   },\r
     L"-n",\r
     TypeValue\r
   },\r
+  {\r
+    L"-s",\r
+    TypeValue\r
+  },\r
   {\r
     L"-_s",\r
     TypeValue\r
   {\r
     L"-_s",\r
     TypeValue\r
@@ -214,92 +226,185 @@ STATIC CONST SHELL_PARAM_ITEM    PingParamList[] = {
 //\r
 STATIC CONST CHAR16      *mDstString;\r
 STATIC CONST CHAR16      *mSrcString;\r
 //\r
 STATIC CONST CHAR16      *mDstString;\r
 STATIC CONST CHAR16      *mSrcString;\r
-STATIC UINT64            mFrequency = 0;\r
-EFI_CPU_ARCH_PROTOCOL    *gCpu = NULL;\r
 \r
 \r
-UINT64\r
+/**\r
+  RTT timer tick routine.\r
+\r
+  @param[in]    Event    A EFI_EVENT type event.\r
+  @param[in]    Context  The pointer to Context.\r
+\r
+**/\r
+VOID\r
 EFIAPI\r
 EFIAPI\r
-ReadTime (\r
+RttTimerTickRoutine (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+  UINT32     *RttTimerTick;\r
+\r
+  RttTimerTick = (UINT32*) Context;\r
+  (*RttTimerTick)++;\r
+}\r
+\r
+/**\r
+  Get the timer period of the system.\r
+\r
+  This function tries to get the system timer period by creating\r
+  an 1ms period timer.\r
+\r
+  @return     System timer period in MS, or 0 if operation failed.\r
+\r
+**/\r
+UINT32\r
+GetTimerPeriod(\r
   VOID\r
   )\r
 {\r
   VOID\r
   )\r
 {\r
-  static UINT64          CurrentTick = 0;\r
-  UINT64                 TimerPeriod;\r
-  EFI_STATUS             Status;\r
+  EFI_STATUS                 Status;\r
+  UINT32                     RttTimerTick;\r
+  EFI_EVENT                  TimerEvent;\r
+  UINT32                     StallCounter;\r
+  EFI_TPL                    OldTpl;\r
 \r
 \r
-  ASSERT (gCpu != NULL);\r
+  RttTimerTick = 0;\r
+  StallCounter   = 0;\r
 \r
 \r
-  Status = gCpu->GetTimerValue (gCpu, 0, &CurrentTick, &TimerPeriod);\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  RttTimerTickRoutine,\r
+                  &RttTimerTick,\r
+                  &TimerEvent\r
+                  );\r
   if (EFI_ERROR (Status)) {\r
   if (EFI_ERROR (Status)) {\r
-    //\r
-    // The WinntGetTimerValue will return EFI_UNSUPPORTED. Set the\r
-    // TimerPeriod by ourselves.\r
-    //\r
-    CurrentTick += 1000000;\r
+    return 0;\r
   }\r
   }\r
-  \r
-  return CurrentTick;\r
-}\r
 \r
 \r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+  Status = gBS->SetTimer (\r
+                  TimerEvent,\r
+                  TimerPeriodic,\r
+                  TICKS_PER_MS\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->CloseEvent (TimerEvent);\r
+    return 0;\r
+  }\r
+\r
+  while (RttTimerTick < 10) {\r
+    gBS->Stall (STALL_1_MILLI_SECOND);\r
+    ++StallCounter;\r
+  }\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  gBS->SetTimer (TimerEvent, TimerCancel, 0);\r
+  gBS->CloseEvent (TimerEvent);\r
+\r
+  return StallCounter / RttTimerTick;\r
+}\r
 \r
 /**\r
 \r
 /**\r
-  Get and caculate the frequency in tick/ms.\r
-  The result is saved in the globle variable mFrequency\r
+  Initialize the timer event for RTT (round trip time).\r
+\r
+  @param[in]    Private    The pointer to PING_PRIVATE_DATA.\r
 \r
 \r
-  @retval EFI_SUCCESS    Caculated the frequency successfully.\r
-  @retval Others         Failed to caculate the frequency.\r
+  @retval EFI_SUCCESS      RTT timer is started.\r
+  @retval Others           Failed to start the RTT timer.\r
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
-GetFrequency (\r
-  VOID\r
+PingInitRttTimer (\r
+  PING_PRIVATE_DATA      *Private\r
   )\r
 {\r
   )\r
 {\r
-  EFI_STATUS               Status;\r
-  UINT64                   CurrentTick;\r
-  UINT64                   TimerPeriod;\r
+  EFI_STATUS                 Status;\r
+\r
+  Private->TimerPeriod = GetTimerPeriod ();\r
+  if (Private->TimerPeriod == 0) {\r
+    return EFI_ABORTED;\r
+  }\r
+  \r
+  Private->RttTimerTick = 0;\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  RttTimerTickRoutine,\r
+                  &Private->RttTimerTick,\r
+                  &Private->RttTimer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
 \r
-  Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &gCpu);\r
+  Status = gBS->SetTimer (\r
+                  Private->RttTimer,\r
+                  TimerPeriodic,\r
+                  TICKS_PER_MS\r
+                  );\r
   if (EFI_ERROR (Status)) {\r
   if (EFI_ERROR (Status)) {\r
+    gBS->CloseEvent (Private->RttTimer);\r
     return Status;\r
   }\r
 \r
     return Status;\r
   }\r
 \r
-  Status = gCpu->GetTimerValue (gCpu, 0, &CurrentTick, &TimerPeriod);\r
+  return EFI_SUCCESS;\r
+}\r
 \r
 \r
-  if (EFI_ERROR (Status)) {\r
-    TimerPeriod = DEFAULT_TIMER_PERIOD;\r
+/**\r
+  Free RTT timer event resource.\r
+\r
+  @param[in]    Private    The pointer to PING_PRIVATE_DATA.\r
+\r
+**/\r
+VOID\r
+PingFreeRttTimer (\r
+  PING_PRIVATE_DATA      *Private\r
+  )\r
+{\r
+  if (Private->RttTimer != NULL) {\r
+    gBS->SetTimer (Private->RttTimer, TimerCancel, 0);\r
+    gBS->CloseEvent (Private->RttTimer);\r
   }\r
   }\r
+}\r
 \r
 \r
-  //\r
-  // The timer period is in femtosecond (1 femtosecond is 1e-15 second).\r
-  // So 1e+12 is divided by timer period to produce the freq in tick/ms.\r
-  //\r
-  mFrequency = DivU64x64Remainder (1000000000000ULL, TimerPeriod, NULL);\r
+/**\r
+  Read the current time.\r
+  \r
+  @param[in]    Private    The pointer to PING_PRIVATE_DATA.\r
 \r
 \r
-  return EFI_SUCCESS;\r
+  @retval the current tick value.\r
+**/\r
+UINT32\r
+ReadTime (\r
+  PING_PRIVATE_DATA      *Private\r
+  )\r
+{\r
+  return Private->RttTimerTick;\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  Caculate a duration in ms.\r
+  Calculate a duration in ms.\r
 \r
 \r
-  @param[in]  Begin     The start point of time.\r
-  @param[in]  End       The end point of time.\r
+  @param[in]    Private   The pointer to PING_PRIVATE_DATA.\r
+  @param[in]    Begin     The start point of time.\r
+  @param[in]    End       The end point of time.\r
 \r
   @return               The duration in ms.\r
   @retval 0             The parameters were not valid.\r
 **/\r
 \r
   @return               The duration in ms.\r
   @retval 0             The parameters were not valid.\r
 **/\r
-UINT64\r
-EFIAPI\r
+UINT32\r
 CalculateTick (\r
 CalculateTick (\r
-  IN UINT64    Begin,\r
-  IN UINT64    End\r
+  PING_PRIVATE_DATA      *Private,\r
+  IN UINT32              Begin,\r
+  IN UINT32              End\r
   )\r
 {\r
   )\r
 {\r
-  if (End <= Begin) {\r
+  if (End < Begin) {\r
     return (0);\r
   }\r
     return (0);\r
   }\r
-  return DivU64x64Remainder (End - Begin, mFrequency, NULL);\r
+\r
+  return (End - Begin) * Private->TimerPeriod;\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -309,7 +414,6 @@ CalculateTick (
   @param[in]    IpChoice  Whether the token is IPv4 or IPv6\r
 **/\r
 VOID\r
   @param[in]    IpChoice  Whether the token is IPv4 or IPv6\r
 **/\r
 VOID\r
-EFIAPI\r
 PingDestroyTxInfo (\r
   IN PING_ICMPX_TX_INFO    *TxInfo,\r
   IN UINT32                IpChoice\r
 PingDestroyTxInfo (\r
   IN PING_ICMPX_TX_INFO    *TxInfo,\r
   IN UINT32                IpChoice\r
@@ -381,7 +485,6 @@ PingDestroyTxInfo (
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 Ping6MatchEchoReply (\r
   IN PING_PRIVATE_DATA           *Private,\r
   IN ICMPX_ECHO_REQUEST_REPLY    *Packet\r
 Ping6MatchEchoReply (\r
   IN PING_PRIVATE_DATA           *Private,\r
   IN ICMPX_ECHO_REQUEST_REPLY    *Packet\r
@@ -442,8 +545,7 @@ Ping6OnEchoReplyReceived (
   PING_PRIVATE_DATA           *Private;\r
   ICMPX_ECHO_REQUEST_REPLY    *Reply;\r
   UINT32                      PayLoad;\r
   PING_PRIVATE_DATA           *Private;\r
   ICMPX_ECHO_REQUEST_REPLY    *Reply;\r
   UINT32                      PayLoad;\r
-  UINT64                      Rtt;\r
-  CHAR8                       Near;\r
+  UINT32                      Rtt;\r
 \r
   Private = (PING_PRIVATE_DATA *) Context;\r
 \r
 \r
   Private = (PING_PRIVATE_DATA *) Context;\r
 \r
@@ -496,12 +598,7 @@ Ping6OnEchoReplyReceived (
   //\r
   // Display statistics on this icmp6 echo reply packet.\r
   //\r
   //\r
   // Display statistics on this icmp6 echo reply packet.\r
   //\r
-  Rtt  = CalculateTick (Reply->TimeStamp, ReadTime ());\r
-  if (Rtt != 0) {\r
-    Near = (CHAR8) '=';\r
-  } else {\r
-    Near = (CHAR8) '<';\r
-  }\r
+  Rtt  = CalculateTick (Private, Reply->TimeStamp, ReadTime (Private));\r
 \r
   Private->RttSum += Rtt;\r
   Private->RttMin  = Private->RttMin > Rtt ? Rtt : Private->RttMin;\r
 \r
   Private->RttSum += Rtt;\r
   Private->RttMin  = Private->RttMin > Rtt ? Rtt : Private->RttMin;\r
@@ -517,8 +614,8 @@ Ping6OnEchoReplyReceived (
     mDstString,\r
     Reply->SequenceNum,\r
     Private->IpChoice == PING_IP_CHOICE_IP6?((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->HopLimit:0,\r
     mDstString,\r
     Reply->SequenceNum,\r
     Private->IpChoice == PING_IP_CHOICE_IP6?((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->HopLimit:0,\r
-    Near,\r
-    Rtt\r
+    Rtt,\r
+    Rtt + Private->TimerPeriod\r
     );\r
 \r
 ON_EXIT:\r
     );\r
 \r
 ON_EXIT:\r
@@ -532,6 +629,7 @@ ON_EXIT:
     Status = Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken);\r
 \r
     if (EFI_ERROR (Status)) {\r
     Status = Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken);\r
 \r
     if (EFI_ERROR (Status)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_RECEIVE), gShellNetwork1HiiHandle, Status);\r
       Private->Status = EFI_ABORTED;\r
     }\r
   } else {\r
       Private->Status = EFI_ABORTED;\r
     }\r
   } else {\r
@@ -557,10 +655,9 @@ ON_EXIT:
 \r
 **/\r
 PING_IPX_COMPLETION_TOKEN *\r
 \r
 **/\r
 PING_IPX_COMPLETION_TOKEN *\r
-EFIAPI\r
 PingGenerateToken (\r
   IN PING_PRIVATE_DATA    *Private,\r
 PingGenerateToken (\r
   IN PING_PRIVATE_DATA    *Private,\r
-  IN UINT64                TimeStamp,\r
+  IN UINT32                TimeStamp,\r
   IN UINT16                SequenceNum\r
   )\r
 {\r
   IN UINT16                SequenceNum\r
   )\r
 {\r
@@ -592,7 +689,7 @@ PingGenerateToken (
   //\r
   Request->Type        = (UINT8)(Private->IpChoice==PING_IP_CHOICE_IP6?ICMP_V6_ECHO_REQUEST:ICMP_V4_ECHO_REQUEST);\r
   Request->Code        = 0;\r
   //\r
   Request->Type        = (UINT8)(Private->IpChoice==PING_IP_CHOICE_IP6?ICMP_V6_ECHO_REQUEST:ICMP_V4_ECHO_REQUEST);\r
   Request->Code        = 0;\r
-  Request->SequenceNum = SequenceNum;\r
+  Request->SequenceNum = SequenceNum; \r
   Request->Identifier  = 0;\r
   Request->Checksum    = 0;\r
 \r
   Request->Identifier  = 0;\r
   Request->Checksum    = 0;\r
 \r
@@ -600,6 +697,7 @@ PingGenerateToken (
   // Assembly token for transmit.\r
   //\r
   if (Private->IpChoice==PING_IP_CHOICE_IP6) {\r
   // Assembly token for transmit.\r
   //\r
   if (Private->IpChoice==PING_IP_CHOICE_IP6) {\r
+    Request->TimeStamp   = TimeStamp;\r
     ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrsLength                   = 0;\r
     ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrs                         = NULL;\r
     ((EFI_IP6_TRANSMIT_DATA*)TxData)->OverrideData                    = 0;\r
     ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrsLength                   = 0;\r
     ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrs                         = NULL;\r
     ((EFI_IP6_TRANSMIT_DATA*)TxData)->OverrideData                    = 0;\r
@@ -659,7 +757,6 @@ PingGenerateToken (
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 PingSendEchoRequest (\r
   IN PING_PRIVATE_DATA    *Private\r
   )\r
 PingSendEchoRequest (\r
   IN PING_PRIVATE_DATA    *Private\r
   )\r
@@ -673,7 +770,7 @@ PingSendEchoRequest (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  TxInfo->TimeStamp   = ReadTime ();\r
+  TxInfo->TimeStamp   = ReadTime (Private);\r
   TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1);\r
   TxInfo->Token       = PingGenerateToken (\r
                           Private,\r
   TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1);\r
   TxInfo->Token       = PingGenerateToken (\r
                           Private,\r
@@ -710,7 +807,6 @@ PingSendEchoRequest (
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 Ping6ReceiveEchoReply (\r
   IN PING_PRIVATE_DATA    *Private\r
   )\r
 Ping6ReceiveEchoReply (\r
   IN PING_PRIVATE_DATA    *Private\r
   )\r
@@ -733,7 +829,11 @@ Ping6ReceiveEchoReply (
 \r
   Private->RxToken.Status = EFI_NOT_READY;\r
 \r
 \r
   Private->RxToken.Status = EFI_NOT_READY;\r
 \r
-  return (Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken));\r
+  Status = Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken);\r
+  if (EFI_ERROR (Status)) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_RECEIVE), gShellNetwork1HiiHandle, Status);\r
+  }\r
+  return Status;\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -780,7 +880,7 @@ Ping6OnTimerRoutine (
   //\r
   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {\r
     TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link);\r
   //\r
   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {\r
     TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link);\r
-    Time   = CalculateTick (TxInfo->TimeStamp, ReadTime ());\r
+    Time   = CalculateTick (Private, TxInfo->TimeStamp, ReadTime (Private));\r
 \r
     //\r
     // Remove the timeout echo request from txlist.\r
 \r
     //\r
     // Remove the timeout echo request from txlist.\r
@@ -798,10 +898,8 @@ Ping6OnTimerRoutine (
       RemoveEntryList (&TxInfo->Link);\r
       PingDestroyTxInfo (TxInfo, Private->IpChoice);\r
 \r
       RemoveEntryList (&TxInfo->Link);\r
       PingDestroyTxInfo (TxInfo, Private->IpChoice);\r
 \r
-      //\r
-      // We dont need to wait for this some other time...\r
-      //\r
       Private->RxCount++;\r
       Private->RxCount++;\r
+      Private->FailedCount++;\r
 \r
       if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) {\r
         //\r
 \r
       if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) {\r
         //\r
@@ -824,7 +922,6 @@ Ping6OnTimerRoutine (
   @retval FALSE     It is not.\r
 **/\r
 BOOLEAN\r
   @retval FALSE     It is not.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 PingNetIp4IsLinkLocalAddr (\r
   IN CONST EFI_IPv4_ADDRESS *Address\r
   )\r
 PingNetIp4IsLinkLocalAddr (\r
   IN CONST EFI_IPv4_ADDRESS *Address\r
   )\r
@@ -841,7 +938,6 @@ PingNetIp4IsLinkLocalAddr (
   @retval FALSE     It is not.\r
 **/\r
 BOOLEAN\r
   @retval FALSE     It is not.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 PingNetIp4IsUnspecifiedAddr (\r
   IN CONST EFI_IPv4_ADDRESS *Address\r
   )\r
 PingNetIp4IsUnspecifiedAddr (\r
   IN CONST EFI_IPv4_ADDRESS *Address\r
   )\r
@@ -861,7 +957,6 @@ PingNetIp4IsUnspecifiedAddr (
   @retval EFI_NOT_FOUND            The source address is not found.\r
 **/\r
 EFI_STATUS\r
   @retval EFI_NOT_FOUND            The source address is not found.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 PingCreateIpInstance (\r
   IN  PING_PRIVATE_DATA    *Private\r
   )\r
 PingCreateIpInstance (\r
   IN  PING_PRIVATE_DATA    *Private\r
   )\r
@@ -870,6 +965,8 @@ PingCreateIpInstance (
   UINTN                            HandleIndex;\r
   UINTN                            HandleNum;\r
   EFI_HANDLE                       *HandleBuffer;\r
   UINTN                            HandleIndex;\r
   UINTN                            HandleNum;\r
   EFI_HANDLE                       *HandleBuffer;\r
+  BOOLEAN                          UnspecifiedSrc;\r
+  EFI_STATUS                       MediaStatus;\r
   EFI_SERVICE_BINDING_PROTOCOL     *EfiSb;\r
   VOID                             *IpXCfg;\r
   EFI_IP6_CONFIG_DATA              Ip6Config;\r
   EFI_SERVICE_BINDING_PROTOCOL     *EfiSb;\r
   VOID                             *IpXCfg;\r
   EFI_IP6_CONFIG_DATA              Ip6Config;\r
@@ -880,6 +977,8 @@ PingCreateIpInstance (
   UINTN                            AddrIndex;\r
 \r
   HandleBuffer      = NULL;\r
   UINTN                            AddrIndex;\r
 \r
   HandleBuffer      = NULL;\r
+  UnspecifiedSrc    = FALSE;\r
+  MediaStatus       = EFI_SUCCESS;\r
   EfiSb             = NULL;\r
   IpXInterfaceInfo  = NULL;\r
   IfInfoSize        = 0;\r
   EfiSb             = NULL;\r
   IpXInterfaceInfo  = NULL;\r
   IfInfoSize        = 0;\r
@@ -897,37 +996,54 @@ PingCreateIpInstance (
   if (EFI_ERROR (Status) || (HandleNum == 0) || (HandleBuffer == NULL)) {\r
     return EFI_ABORTED;\r
   }\r
   if (EFI_ERROR (Status) || (HandleNum == 0) || (HandleBuffer == NULL)) {\r
     return EFI_ABORTED;\r
   }\r
+\r
+  if (Private->IpChoice == PING_IP_CHOICE_IP6 ? NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress) : \\r
+      PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress)) {\r
+    //\r
+    // SrcAddress is unspecified. So, both connected and configured interface will be automatic selected. \r
+    //\r
+    UnspecifiedSrc = TRUE;\r
+  }\r
+  \r
   //\r
   //\r
-  // Source address is required when pinging a link-local address on multi-\r
-  // interfaces host.\r
+  // Source address is required when pinging a link-local address.\r
   //\r
   if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
   //\r
   if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
-    if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS*)&Private->DstAddress) &&\r
-        NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress) &&\r
-        (HandleNum > 1)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, mSrcString);\r
+    if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle);\r
       Status = EFI_INVALID_PARAMETER;\r
       goto ON_ERROR;\r
     }\r
   } else {\r
     ASSERT(Private->IpChoice == PING_IP_CHOICE_IP4);\r
       Status = EFI_INVALID_PARAMETER;\r
       goto ON_ERROR;\r
     }\r
   } else {\r
     ASSERT(Private->IpChoice == PING_IP_CHOICE_IP4);\r
-    if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS*)&Private->DstAddress) &&\r
-        PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress) &&\r
-        (HandleNum > 1)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, mSrcString);\r
+    if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle); \r
       Status = EFI_INVALID_PARAMETER;\r
       goto ON_ERROR;\r
     }\r
   }\r
       Status = EFI_INVALID_PARAMETER;\r
       goto ON_ERROR;\r
     }\r
   }\r
+  \r
   //\r
   // For each ip6 protocol, check interface addresses list.\r
   //\r
   for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {\r
   //\r
   // For each ip6 protocol, check interface addresses list.\r
   //\r
   for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {\r
-\r
     EfiSb             = NULL;\r
     IpXInterfaceInfo  = NULL;\r
     IfInfoSize        = 0;\r
 \r
     EfiSb             = NULL;\r
     IpXInterfaceInfo  = NULL;\r
     IfInfoSize        = 0;\r
 \r
+    if (UnspecifiedSrc) {\r
+      //\r
+      // Check media.\r
+      //\r
+      NetLibDetectMediaWaitTimeout (HandleBuffer[HandleIndex], 0, &MediaStatus);\r
+      if (MediaStatus != EFI_SUCCESS) {\r
+        //\r
+        // Skip this one.\r
+        //\r
+        continue;\r
+      }\r
+    }\r
+\r
     Status = gBS->HandleProtocol (\r
                     HandleBuffer[HandleIndex],\r
                     Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,\r
     Status = gBS->HandleProtocol (\r
                     HandleBuffer[HandleIndex],\r
                     Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,\r
@@ -937,114 +1053,122 @@ PingCreateIpInstance (
       goto ON_ERROR;\r
     }\r
 \r
       goto ON_ERROR;\r
     }\r
 \r
-    if (Private->IpChoice == PING_IP_CHOICE_IP6?NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress):PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress)) {\r
-      //\r
-      // No need to match interface address.\r
-      //\r
-      break;\r
-    } else {\r
-      //\r
-      // Ip6config protocol and ip6 service binding protocol are installed\r
-      // on the same handle.\r
-      //\r
-      Status = gBS->HandleProtocol (\r
-                      HandleBuffer[HandleIndex],\r
-                      Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ConfigProtocolGuid:&gEfiIp4ConfigProtocolGuid,\r
-                      (VOID **) &IpXCfg\r
-                      );\r
+    //\r
+    // Ip6config protocol and ip6 service binding protocol are installed\r
+    // on the same handle.\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    HandleBuffer[HandleIndex],\r
+                    Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ConfigProtocolGuid:&gEfiIp4Config2ProtocolGuid,\r
+                    (VOID **) &IpXCfg\r
+                    );\r
 \r
 \r
-      if (EFI_ERROR (Status)) {\r
-        goto ON_ERROR;\r
-      }\r
-      //\r
-      // Get the interface information size.\r
-      //\r
-      if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
-        Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
-                           IpXCfg,\r
-                           Ip6ConfigDataTypeInterfaceInfo,\r
-                           &IfInfoSize,\r
-                           NULL\r
-                           );\r
-      } else {\r
-        Status = ((EFI_IP4_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
-                           IpXCfg,\r
-                           &IfInfoSize,\r
-                           NULL\r
-                           );\r
-      }\r
-      \r
-      //\r
-      // Skip the ones not in current use.\r
-      //\r
-      if (Status == EFI_NOT_STARTED) {\r
-        continue;\r
-      }\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Get the interface information size.\r
+    //\r
+    if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
+      Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
+                         IpXCfg,\r
+                         Ip6ConfigDataTypeInterfaceInfo,\r
+                         &IfInfoSize,\r
+                         NULL\r
+                         );\r
+    } else {\r
+      Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (\r
+                         IpXCfg,\r
+                         Ip4Config2DataTypeInterfaceInfo,\r
+                         &IfInfoSize,\r
+                         NULL\r
+                         );\r
+    }\r
+    \r
+    //\r
+    // Skip the ones not in current use.\r
+    //\r
+    if (Status == EFI_NOT_STARTED) {\r
+      continue;\r
+    }\r
 \r
 \r
-      if (Status != EFI_BUFFER_TOO_SMALL) {\r
-        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);\r
-        goto ON_ERROR;\r
-      }\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
 \r
 \r
-      IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);\r
+    IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);\r
 \r
 \r
-      if (IpXInterfaceInfo == NULL) {\r
-        Status = EFI_OUT_OF_RESOURCES;\r
-        goto ON_ERROR;\r
-      }\r
-      //\r
-      // Get the interface info.\r
-      //\r
-      if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
-        Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
-                           IpXCfg,\r
-                           Ip6ConfigDataTypeInterfaceInfo,\r
-                           &IfInfoSize,\r
-                           IpXInterfaceInfo\r
-                           );\r
-      } else {\r
-        Status = ((EFI_IP4_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
-                           IpXCfg,\r
-                           &IfInfoSize,\r
-                           IpXInterfaceInfo\r
-                           );\r
-      }\r
+    if (IpXInterfaceInfo == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Get the interface info.\r
+    //\r
+    if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
+      Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
+                         IpXCfg,\r
+                         Ip6ConfigDataTypeInterfaceInfo,\r
+                         &IfInfoSize,\r
+                         IpXInterfaceInfo\r
+                         );\r
+    } else {\r
+      Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (\r
+                         IpXCfg,\r
+                         Ip4Config2DataTypeInterfaceInfo,\r
+                         &IfInfoSize,\r
+                         IpXInterfaceInfo\r
+                         );\r
+    }\r
 \r
 \r
-      if (EFI_ERROR (Status)) {\r
-        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);\r
-        goto ON_ERROR;\r
-      }\r
-      //\r
-      // Check whether the source address is one of the interface addresses.\r
-      //\r
-      if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
-        for (AddrIndex = 0; AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount; AddrIndex++) {\r
+    if (EFI_ERROR (Status)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Check whether the source address is one of the interface addresses.\r
+    //\r
+    if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
+      for (AddrIndex = 0; AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount; AddrIndex++) {\r
+        Addr = &(((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfo[AddrIndex].Address);\r
 \r
 \r
-          Addr = &(((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfo[AddrIndex].Address);\r
-          if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {\r
+        if (UnspecifiedSrc) {\r
+          if (!NetIp6IsUnspecifiedAddr (Addr) && !NetIp6IsLinkLocalAddr (Addr)) {\r
             //\r
             //\r
-            // Match a certain interface address.\r
+            // Select the interface automatically.\r
             //\r
             //\r
+            CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress));\r
             break;\r
           }\r
             break;\r
           }\r
-        }\r
-\r
-        if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) {\r
+        } else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {\r
           //\r
           //\r
-          // Found a nic handle with right interface address.\r
+          // Match a certain interface address.\r
           //\r
           break;\r
         }\r
           //\r
           break;\r
         }\r
-      } else {\r
+      }\r
+\r
+      if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) {\r
         //\r
         //\r
-        // IP4 address check\r
+        // Found a nic handle with right interface address.\r
         //\r
         //\r
-        if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_IPCONFIG_DATA*)IpXInterfaceInfo)->StationAddress)) {\r
+        break;\r
+      }\r
+    } else {\r
+      if (UnspecifiedSrc) {\r
+        if (!PingNetIp4IsUnspecifiedAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress) && \r
+            !PingNetIp4IsLinkLocalAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {\r
           //\r
           //\r
-          // Match a certain interface address.\r
+          // Select the interface automatically.\r
           //\r
           break;\r
         }\r
           //\r
           break;\r
         }\r
+      } else if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {\r
+        //\r
+        // Match a certain interface address.\r
+        //\r
+        break;\r
       }\r
     }\r
 \r
       }\r
     }\r
 \r
@@ -1056,7 +1180,7 @@ PingCreateIpInstance (
   //\r
 \r
   if (HandleIndex == HandleNum) {\r
   //\r
 \r
   if (HandleIndex == HandleNum) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, mSrcString);\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIGD_NIC_NF), gShellNetwork1HiiHandle, L"ping");  \r
     Status = EFI_NOT_FOUND;\r
     goto ON_ERROR;\r
   }\r
     Status = EFI_NOT_FOUND;\r
     goto ON_ERROR;\r
   }\r
@@ -1131,11 +1255,6 @@ PingCreateIpInstance (
     //\r
     // Configure the ip4 instance for icmp4 packet exchange.\r
     //\r
     //\r
     // Configure the ip4 instance for icmp4 packet exchange.\r
     //\r
-//    PING_IP4_COPY_ADDRESS (&Ip4Config.StationAddress,     &Private->SrcAddress);\r
-//    Ip4Config.SubnetMask.Addr[0] = 0xFF;\r
-//    Ip4Config.SubnetMask.Addr[1] = 0xFF;\r
-//    Ip4Config.SubnetMask.Addr[2] = 0xFF;\r
-//    Ip4Config.SubnetMask.Addr[3] = 0x00;\r
     Ip4Config.DefaultProtocol   = 1;\r
     Ip4Config.AcceptAnyProtocol = FALSE;\r
     Ip4Config.AcceptBroadcast   = FALSE;\r
     Ip4Config.DefaultProtocol   = 1;\r
     Ip4Config.AcceptAnyProtocol = FALSE;\r
     Ip4Config.AcceptBroadcast   = FALSE;\r
@@ -1185,14 +1304,13 @@ ON_ERROR:
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  Destory the IP instance.\r
+  Destroy the IP instance.\r
 \r
   @param[in]    Private    The pointer of PING_PRIVATE_DATA.\r
 \r
 **/\r
 VOID\r
 \r
   @param[in]    Private    The pointer of PING_PRIVATE_DATA.\r
 \r
 **/\r
 VOID\r
-EFIAPI\r
-Ping6DestoryIp6Instance (\r
+Ping6DestroyIp6Instance (\r
   IN PING_PRIVATE_DATA    *Private\r
   )\r
 {\r
   IN PING_PRIVATE_DATA    *Private\r
   )\r
 {\r
@@ -1217,6 +1335,7 @@ Ping6DestoryIp6Instance (
   }\r
 }\r
 \r
   }\r
 }\r
 \r
+\r
 /**\r
   The Ping Process.\r
 \r
 /**\r
   The Ping Process.\r
 \r
@@ -1230,7 +1349,6 @@ Ping6DestoryIp6Instance (
   @retval others         The ping processed unsuccessfully.\r
 **/\r
 SHELL_STATUS\r
   @retval others         The ping processed unsuccessfully.\r
 **/\r
 SHELL_STATUS\r
-EFIAPI\r
 ShellPing (\r
   IN UINT32              SendNumber,\r
   IN UINT32              BufferSize,\r
 ShellPing (\r
   IN UINT32              SendNumber,\r
   IN UINT32              BufferSize,\r
@@ -1302,6 +1420,16 @@ ShellPing (
     ShellStatus = SHELL_ACCESS_DENIED;\r
     goto ON_EXIT;\r
   }\r
     ShellStatus = SHELL_ACCESS_DENIED;\r
     goto ON_EXIT;\r
   }\r
+\r
+  //\r
+  // Start a timer to calculate the RTT.\r
+  //\r
+  Status = PingInitRttTimer (Private);\r
+  if (EFI_ERROR (Status)) {\r
+    ShellStatus = SHELL_ACCESS_DENIED;\r
+    goto ON_EXIT;\r
+  }\r
+  \r
   //\r
   // Create a ipv6 token to send the first icmp6 echo request packet.\r
   //\r
   //\r
   // Create a ipv6 token to send the first icmp6 echo request packet.\r
   //\r
@@ -1316,7 +1444,7 @@ ShellPing (
     } else if (Status == RETURN_NO_MAPPING) {\r
       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOROUTE_FOUND), gShellNetwork1HiiHandle, mDstString, mSrcString);\r
     } else {\r
     } else if (Status == RETURN_NO_MAPPING) {\r
       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOROUTE_FOUND), gShellNetwork1HiiHandle, mDstString, mSrcString);\r
     } else {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NETWORK_ERROR), gShellNetwork1HiiHandle, Status);\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NETWORK_ERROR), gShellNetwork1HiiHandle, L"ping", Status);  \r
     }\r
 \r
     goto ON_EXIT;\r
     }\r
 \r
     goto ON_EXIT;\r
@@ -1362,13 +1490,13 @@ ON_STAT:
       STRING_TOKEN (STR_PING_STAT),\r
       gShellNetwork1HiiHandle,\r
       Private->TxCount,\r
       STRING_TOKEN (STR_PING_STAT),\r
       gShellNetwork1HiiHandle,\r
       Private->TxCount,\r
-      Private->RxCount,\r
-      (100 * (Private->TxCount - Private->RxCount)) / Private->TxCount,\r
+      (Private->RxCount - Private->FailedCount),\r
+      (100 - ((100 * (Private->RxCount - Private->FailedCount)) / Private->TxCount)),\r
       Private->RttSum\r
       );\r
   }\r
 \r
       Private->RttSum\r
       );\r
   }\r
 \r
-  if (Private->RxCount != 0) {\r
+  if (Private->RxCount > Private->FailedCount) {\r
     ShellPrintHiiEx (\r
       -1,\r
       -1,\r
     ShellPrintHiiEx (\r
       -1,\r
       -1,\r
@@ -1376,8 +1504,11 @@ ON_STAT:
       STRING_TOKEN (STR_PING_RTT),\r
       gShellNetwork1HiiHandle,\r
       Private->RttMin,\r
       STRING_TOKEN (STR_PING_RTT),\r
       gShellNetwork1HiiHandle,\r
       Private->RttMin,\r
+      Private->RttMin + Private->TimerPeriod,\r
       Private->RttMax,\r
       Private->RttMax,\r
-      DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL)\r
+      Private->RttMax + Private->TimerPeriod,\r
+      DivU64x64Remainder (Private->RttSum, (Private->RxCount - Private->FailedCount), NULL),\r
+      DivU64x64Remainder (Private->RttSum, (Private->RxCount - Private->FailedCount), NULL) + Private->TimerPeriod\r
       );\r
   }\r
 \r
       );\r
   }\r
 \r
@@ -1396,6 +1527,8 @@ ON_EXIT:
       PingDestroyTxInfo (TxInfo, Private->IpChoice);\r
     }\r
 \r
       PingDestroyTxInfo (TxInfo, Private->IpChoice);\r
     }\r
 \r
+    PingFreeRttTimer (Private);\r
+\r
     if (Private->Timer != NULL) {\r
       gBS->CloseEvent (Private->Timer);\r
     }\r
     if (Private->Timer != NULL) {\r
       gBS->CloseEvent (Private->Timer);\r
     }\r
@@ -1409,7 +1542,7 @@ ON_EXIT:
     }\r
 \r
     if (Private->IpChildHandle != NULL) {\r
     }\r
 \r
     if (Private->IpChildHandle != NULL) {\r
-      Ping6DestoryIp6Instance (Private);\r
+      Ping6DestroyIp6Instance (Private);\r
     }\r
 \r
     FreePool (Private);\r
     }\r
 \r
     FreePool (Private);\r
@@ -1423,6 +1556,10 @@ ON_EXIT:
 \r
   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
 \r
   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
+\r
+  @retval SHELL_SUCCESS  The ping processed successfullly.\r
+  @retval others         The ping processed unsuccessfully.\r
+  \r
 **/\r
 SHELL_STATUS\r
 EFIAPI\r
 **/\r
 SHELL_STATUS\r
 EFIAPI\r
@@ -1441,6 +1578,7 @@ ShellCommandRunPing (
   CONST CHAR16        *ValueStr;\r
   UINTN               NonOptionCount;\r
   UINT32              IpChoice;\r
   CONST CHAR16        *ValueStr;\r
   UINTN               NonOptionCount;\r
   UINT32              IpChoice;\r
+  CHAR16              *ProblemParam;\r
 \r
   //\r
   // we use IPv6 buffers to hold items... \r
 \r
   //\r
   // we use IPv6 buffers to hold items... \r
@@ -1452,10 +1590,11 @@ ShellCommandRunPing (
   IpChoice = PING_IP_CHOICE_IP4;\r
 \r
   ShellStatus = SHELL_SUCCESS;\r
   IpChoice = PING_IP_CHOICE_IP4;\r
 \r
   ShellStatus = SHELL_SUCCESS;\r
+  ProblemParam = NULL;\r
 \r
 \r
-  Status = ShellCommandLineParseEx (PingParamList, &ParamPackage, NULL, TRUE, FALSE);\r
+  Status = ShellCommandLineParseEx (PingParamList, &ParamPackage, &ProblemParam, TRUE, FALSE);\r
   if (EFI_ERROR(Status)) {\r
   if (EFI_ERROR(Status)) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle);\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ProblemParam);\r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
@@ -1465,7 +1604,7 @@ ShellCommandRunPing (
   }\r
 \r
   //\r
   }\r
 \r
   //\r
-  // Parse the paramter of count number.\r
+  // Parse the parameter of count number.\r
   //\r
   ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n");\r
   if (ValueStr != NULL) {\r
   //\r
   ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n");\r
   if (ValueStr != NULL) {\r
@@ -1475,7 +1614,7 @@ ShellCommandRunPing (
     // ShellStrToUintn will return 0 when input is 0 or an invalid input string.\r
     //\r
     if ((SendNumber == 0) || (SendNumber > MAX_SEND_NUMBER)) {\r
     // ShellStrToUintn will return 0 when input is 0 or an invalid input string.\r
     //\r
     if ((SendNumber == 0) || (SendNumber > MAX_SEND_NUMBER)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);  \r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
@@ -1483,7 +1622,7 @@ ShellCommandRunPing (
     SendNumber = DEFAULT_SEND_COUNT;\r
   }\r
   //\r
     SendNumber = DEFAULT_SEND_COUNT;\r
   }\r
   //\r
-  // Parse the paramter of buffer size.\r
+  // Parse the parameter of buffer size.\r
   //\r
   ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");\r
   if (ValueStr != NULL) {\r
   //\r
   ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");\r
   if (ValueStr != NULL) {\r
@@ -1493,7 +1632,7 @@ ShellCommandRunPing (
     // ShellStrToUintn will return 0 when input is 0 or an invalid input string.\r
     //\r
     if ((BufferSize < 16) || (BufferSize > MAX_BUFFER_SIZE)) {\r
     // ShellStrToUintn will return 0 when input is 0 or an invalid input string.\r
     //\r
     if ((BufferSize < 16) || (BufferSize > MAX_BUFFER_SIZE)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);  \r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
@@ -1505,9 +1644,13 @@ ShellCommandRunPing (
   ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS));\r
 \r
   //\r
   ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS));\r
 \r
   //\r
-  // Parse the paramter of source ip address.\r
+  // Parse the parameter of source ip address.\r
   //\r
   //\r
-  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-_s");\r
+  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");\r
+  if (ValueStr == NULL) {\r
+    ValueStr = ShellCommandLineGetValue (ParamPackage, L"-_s");\r
+  }\r
+  \r
   if (ValueStr != NULL) {\r
     mSrcString = ValueStr;\r
     if (IpChoice == PING_IP_CHOICE_IP6) {\r
   if (ValueStr != NULL) {\r
     mSrcString = ValueStr;\r
     if (IpChoice == PING_IP_CHOICE_IP6) {\r
@@ -1516,22 +1659,22 @@ ShellCommandRunPing (
       Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&SrcAddress);\r
     }\r
     if (EFI_ERROR (Status)) {\r
       Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&SrcAddress);\r
     }\r
     if (EFI_ERROR (Status)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);  \r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
   }\r
   //\r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
   }\r
   //\r
-  // Parse the paramter of destination ip address.\r
+  // Parse the parameter of destination ip address.\r
   //\r
   NonOptionCount = ShellCommandLineGetCount(ParamPackage);\r
   if (NonOptionCount < 2) {\r
   //\r
   NonOptionCount = ShellCommandLineGetCount(ParamPackage);\r
   if (NonOptionCount < 2) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle);\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle, L"ping");  \r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
   if (NonOptionCount > 2) {\r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
   if (NonOptionCount > 2) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellNetwork1HiiHandle);\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellNetwork1HiiHandle, L"ping");  \r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
@@ -1544,19 +1687,12 @@ ShellCommandRunPing (
       Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&DstAddress);\r
     }\r
     if (EFI_ERROR (Status)) {\r
       Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&DstAddress);\r
     }\r
     if (EFI_ERROR (Status)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);  \r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
   }\r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
   }\r
-  //\r
-  // Get frequency to calculate the time from ticks.\r
-  //\r
-  Status = GetFrequency ();\r
 \r
 \r
-  if (EFI_ERROR(Status)) {\r
-    goto ON_EXIT;\r
-  }\r
   //\r
   // Enter into ping process.\r
   //\r
   //\r
   // Enter into ping process.\r
   //\r