]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/Application/Ping6/Ping6.c
NetworkPkg: Remove ping6 and ifconfig shell application.
[mirror_edk2.git] / NetworkPkg / Application / Ping6 / Ping6.c
diff --git a/NetworkPkg/Application/Ping6/Ping6.c b/NetworkPkg/Application/Ping6/Ping6.c
deleted file mode 100644 (file)
index 66daac2..0000000
+++ /dev/null
@@ -1,1200 +0,0 @@
-/** @file\r
-  The implementation for Ping6 application.\r
-\r
-  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<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
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php.\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include <Library/ShellLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiHiiServicesLib.h>\r
-#include <Library/HiiLib.h>\r
-#include <Library/NetLib.h>\r
-\r
-#include <Protocol/Cpu.h>\r
-#include <Protocol/ServiceBinding.h>\r
-#include <Protocol/Ip6.h>\r
-#include <Protocol/Ip6Config.h>\r
-\r
-#include "Ping6.h"\r
-\r
-//\r
-// String token ID of Ping6 command help message text.\r
-//\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStringPing6HelpToken = STRING_TOKEN (STR_PING6_HELP);\r
-\r
-SHELL_PARAM_ITEM    Ping6ParamList[] = {\r
-  {\r
-    L"-l",\r
-    TypeValue\r
-  },\r
-  {\r
-    L"-n",\r
-    TypeValue\r
-  },\r
-  {\r
-    L"-s",\r
-    TypeValue\r
-  },\r
-  {\r
-    NULL,\r
-    TypeMax\r
-  },\r
-};\r
-\r
-//\r
-// Global Variables in Ping6 application.\r
-//\r
-EFI_HII_HANDLE    mHiiHandle;\r
-CONST CHAR16      *mIp6DstString;\r
-CONST CHAR16      *mIp6SrcString;\r
-UINT64            mFrequency = 0;\r
-/**\r
-  Get and calculate the frequency in tick/ms.\r
-  The result is saved in the globle variable mFrequency\r
-\r
-  @retval EFI_SUCCESS    Calculated the frequency successfully.\r
-  @retval Others         Failed to calculate the frequency.\r
-\r
-**/\r
-EFI_STATUS\r
-Ping6GetFrequency (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS               Status;\r
-  EFI_CPU_ARCH_PROTOCOL    *Cpu;\r
-  UINT64                   CurrentTick;\r
-  UINT64                   TimerPeriod;\r
-\r
-  Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Cpu);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = Cpu->GetTimerValue (Cpu, 0, &CurrentTick, &TimerPeriod);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // For NT32 Simulator only. 358049 is a similar value to keep timer granularity.\r
-    // Set the timer period by ourselves.\r
-    //\r
-    TimerPeriod = (UINT64) NTTIMERPERIOD;\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
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Get and calculate the duration in ms.\r
-\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
-\r
-**/\r
-UINT64\r
-Ping6CalculateTick (\r
-  IN UINT64    Begin,\r
-  IN UINT64    End\r
-  )\r
-{\r
-  ASSERT (End > Begin);\r
-  return DivU64x64Remainder (End - Begin, mFrequency, NULL);\r
-}\r
-\r
-/**\r
-  Destroy IPING6_ICMP6_TX_INFO, and recollect the memory.\r
-\r
-  @param[in]    TxInfo    The pointer to PING6_ICMP6_TX_INFO.\r
-\r
-**/\r
-VOID\r
-Ping6DestroyTxInfo (\r
-  IN PING6_ICMP6_TX_INFO    *TxInfo\r
-  )\r
-{\r
-  EFI_IP6_TRANSMIT_DATA    *TxData;\r
-  EFI_IP6_FRAGMENT_DATA    *FragData;\r
-  UINTN                    Index;\r
-\r
-  ASSERT (TxInfo != NULL);\r
-\r
-  if (TxInfo->Token != NULL) {\r
-\r
-    if (TxInfo->Token->Event != NULL) {\r
-      gBS->CloseEvent (TxInfo->Token->Event);\r
-    }\r
-\r
-    TxData = TxInfo->Token->Packet.TxData;\r
-    if (TxData != NULL) {\r
-\r
-      if (TxData->OverrideData != NULL) {\r
-        FreePool (TxData->OverrideData);\r
-      }\r
-\r
-      if (TxData->ExtHdrs != NULL) {\r
-        FreePool (TxData->ExtHdrs);\r
-      }\r
-\r
-      for (Index = 0; Index < TxData->FragmentCount; Index++) {\r
-        FragData = TxData->FragmentTable[Index].FragmentBuffer;\r
-        if (FragData != NULL) {\r
-          FreePool (FragData);\r
-        }\r
-      }\r
-    }\r
-\r
-    FreePool (TxInfo->Token);\r
-  }\r
-\r
-  FreePool (TxInfo);\r
-}\r
-\r
-/**\r
-  Match the request, and reply with SequenceNum/TimeStamp.\r
-\r
-  @param[in]    Private    The pointer to PING6_PRIVATE_DATA.\r
-  @param[in]    Packet     The pointer to ICMP6_ECHO_REQUEST_REPLY.\r
-\r
-  @retval EFI_SUCCESS      The match is successful.\r
-  @retval EFI_NOT_FOUND    The reply can't be matched with any request.\r
-\r
-**/\r
-EFI_STATUS\r
-Ping6MatchEchoReply (\r
-  IN PING6_PRIVATE_DATA          *Private,\r
-  IN ICMP6_ECHO_REQUEST_REPLY    *Packet\r
-  )\r
-{\r
-  PING6_ICMP6_TX_INFO    *TxInfo;\r
-  LIST_ENTRY             *Entry;\r
-  LIST_ENTRY             *NextEntry;\r
-\r
-  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {\r
-    TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link);\r
-\r
-    if ((TxInfo->SequenceNum == Packet->SequenceNum) && (TxInfo->TimeStamp == Packet->TimeStamp)) {\r
-      Private->RxCount++;\r
-      RemoveEntryList (&TxInfo->Link);\r
-      Ping6DestroyTxInfo (TxInfo);\r
-      return EFI_SUCCESS;\r
-    }\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
-  The original intention is to send a request.\r
-  Currently, the application retransmits an icmp6 echo request packet\r
-  per second in sendnumber times that is specified by the user.\r
-  Because nothing can be done here, all things move to the timer rountine.\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
-Ping6OnEchoRequestSent (\r
-  IN EFI_EVENT    Event,\r
-  IN VOID         *Context\r
-  )\r
-{\r
-}\r
-\r
-/**\r
-  receive reply, match and print reply infomation.\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
-Ping6OnEchoReplyReceived (\r
-  IN EFI_EVENT    Event,\r
-  IN VOID         *Context\r
-  )\r
-{\r
-  EFI_STATUS                  Status;\r
-  PING6_PRIVATE_DATA          *Private;\r
-  EFI_IP6_COMPLETION_TOKEN    *RxToken;\r
-  EFI_IP6_RECEIVE_DATA        *RxData;\r
-  ICMP6_ECHO_REQUEST_REPLY    *Reply;\r
-  UINT32                      PayLoad;\r
-  UINT64                      Rtt;\r
-  CHAR8                       Near;\r
-\r
-  Private = (PING6_PRIVATE_DATA *) Context;\r
-\r
-  if (Private->Status == EFI_ABORTED) {\r
-    return;\r
-  }\r
-\r
-  RxToken = &Private->RxToken;\r
-  RxData  = RxToken->Packet.RxData;\r
-  Reply   = RxData->FragmentTable[0].FragmentBuffer;\r
-  PayLoad = RxData->DataLength;\r
-\r
-  if (RxData->Header->NextHeader != IP6_ICMP) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  if (!IP6_IS_MULTICAST (&Private->DstAddress) && \r
-      !EFI_IP6_EQUAL (&RxData->Header->SourceAddress, &Private->DstAddress)) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  if ((Reply->Type != ICMP_V6_ECHO_REPLY) || (Reply->Code != 0)) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  if (PayLoad != Private->BufferSize) {\r
-    goto ON_EXIT;\r
-  }\r
-  //\r
-  // Check whether the reply matches the sent request before.\r
-  //\r
-  Status = Ping6MatchEchoReply (Private, Reply);\r
-  if (EFI_ERROR(Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-  //\r
-  // Display statistics on this icmp6 echo reply packet.\r
-  //\r
-  Rtt  = Ping6CalculateTick (Reply->TimeStamp, ReadTime ());\r
-  if (Rtt != 0) {\r
-    Near = (CHAR8) '=';\r
-  } else {\r
-    Near = (CHAR8) '<';\r
-  }\r
-\r
-  Private->RttSum += Rtt;\r
-  Private->RttMin  = Private->RttMin > Rtt ? Rtt : Private->RttMin;\r
-  Private->RttMax  = Private->RttMax < Rtt ? Rtt : Private->RttMax;\r
-\r
-  ShellPrintHiiEx (\r
-    -1,\r
-    -1,\r
-    NULL,\r
-    STRING_TOKEN (STR_PING6_REPLY_INFO),\r
-    mHiiHandle,\r
-    PayLoad,\r
-    mIp6DstString,\r
-    Reply->SequenceNum,\r
-    RxData->Header->HopLimit,\r
-    Near,\r
-    Rtt\r
-    );\r
-\r
-ON_EXIT:\r
-\r
-  if (Private->RxCount < Private->SendNum) {\r
-    //\r
-    // Continue to receive icmp6 echo reply packets.\r
-    //\r
-    RxToken->Status = EFI_ABORTED;\r
-\r
-    Status = Private->Ip6->Receive (Private->Ip6, RxToken);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      Private->Status = EFI_ABORTED;\r
-    }\r
-  } else {\r
-    //\r
-    // All reply have already been received from the dest host.\r
-    //\r
-    Private->Status = EFI_SUCCESS;\r
-  }\r
-  //\r
-  // Singal to recycle the each rxdata here, not at the end of process.\r
-  //\r
-  gBS->SignalEvent (RxData->RecycleSignal);\r
-}\r
-\r
-/**\r
-  Initial EFI_IP6_COMPLETION_TOKEN.\r
-\r
-  @param[in]    Private        The pointer of PING6_PRIVATE_DATA.\r
-  @param[in]    TimeStamp      The TimeStamp of request.\r
-  @param[in]    SequenceNum    The SequenceNum of request.\r
-\r
-  @return The pointer of EFI_IP6_COMPLETION_TOKEN.\r
-\r
-**/\r
-EFI_IP6_COMPLETION_TOKEN *\r
-Ping6GenerateToken (\r
-  IN PING6_PRIVATE_DATA    *Private,\r
-  IN UINT64                TimeStamp,\r
-  IN UINT16                SequenceNum\r
-  )\r
-{\r
-  EFI_STATUS                  Status;\r
-  EFI_IP6_COMPLETION_TOKEN    *Token;\r
-  EFI_IP6_TRANSMIT_DATA       *TxData;\r
-  ICMP6_ECHO_REQUEST_REPLY    *Request;\r
-\r
-  Request = AllocateZeroPool (Private->BufferSize);\r
-\r
-  if (Request == NULL) {\r
-    return NULL;\r
-  }\r
-  //\r
-  // Assembly icmp6 echo request packet.\r
-  //\r
-  Request->Type        = ICMP_V6_ECHO_REQUEST;\r
-  Request->Code        = 0;\r
-  Request->SequenceNum = SequenceNum;\r
-  Request->TimeStamp   = TimeStamp;\r
-  Request->Identifier  = 0;\r
-  //\r
-  // Leave check sum to ip6 layer, since it has no idea of source address\r
-  // selection.\r
-  //\r
-  Request->Checksum    = 0;\r
-\r
-  TxData = AllocateZeroPool (sizeof (EFI_IP6_TRANSMIT_DATA));\r
-\r
-  if (TxData == NULL) {\r
-    FreePool (Request);\r
-    return NULL;\r
-  }\r
-  //\r
-  // Assembly ipv6 token for transmit.\r
-  //\r
-  TxData->OverrideData       = 0;\r
-  TxData->ExtHdrsLength      = 0;\r
-  TxData->ExtHdrs            = NULL;\r
-  TxData->DataLength         = Private->BufferSize;\r
-  TxData->FragmentCount      = 1;\r
-  TxData->FragmentTable[0].FragmentBuffer = (VOID *) Request;\r
-  TxData->FragmentTable[0].FragmentLength = Private->BufferSize;\r
-\r
-  Token = AllocateZeroPool (sizeof (EFI_IP6_COMPLETION_TOKEN));\r
-\r
-  if (Token == NULL) {\r
-    FreePool (Request);\r
-    FreePool (TxData);\r
-    return NULL;\r
-  }\r
-\r
-  Token->Status         = EFI_ABORTED;\r
-  Token->Packet.TxData  = TxData;\r
-\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
-                  Ping6OnEchoRequestSent,\r
-                  Private,\r
-                  &Token->Event\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (Request);\r
-    FreePool (TxData);\r
-    FreePool (Token);\r
-    return NULL;\r
-  }\r
-\r
-  return Token;\r
-}\r
-\r
-/**\r
-  Transmit the EFI_IP6_COMPLETION_TOKEN.\r
-\r
-  @param[in]    Private    The pointer of PING6_PRIVATE_DATA.\r
-\r
-  @retval EFI_SUCCESS             Transmitted successfully.\r
-  @retval EFI_OUT_OF_RESOURCES    No memory is available on the platform.\r
-  @retval others                  Transmitted unsuccessfully.\r
-\r
-**/\r
-EFI_STATUS\r
-Ping6SendEchoRequest (\r
-  IN PING6_PRIVATE_DATA    *Private\r
-  )\r
-{\r
-  EFI_STATUS             Status;\r
-  PING6_ICMP6_TX_INFO    *TxInfo;\r
-\r
-  TxInfo = AllocateZeroPool (sizeof (PING6_ICMP6_TX_INFO));\r
-\r
-  if (TxInfo == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  TxInfo->TimeStamp   = ReadTime ();\r
-  TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1);\r
-\r
-  TxInfo->Token       = Ping6GenerateToken (\r
-                          Private,\r
-                          TxInfo->TimeStamp,\r
-                          TxInfo->SequenceNum\r
-                          );\r
-\r
-  if (TxInfo->Token == NULL) {\r
-    Ping6DestroyTxInfo (TxInfo);\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  Status = Private->Ip6->Transmit (Private->Ip6, TxInfo->Token);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    Ping6DestroyTxInfo (TxInfo);\r
-    return Status;\r
-  }\r
-\r
-  InsertTailList (&Private->TxList, &TxInfo->Link);\r
-  Private->TxCount++;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Place a completion token into the receive packet queue to receive the echo reply.\r
-\r
-  @param[in]    Private    The pointer of PING6_PRIVATE_DATA.\r
-\r
-  @retval EFI_SUCCESS      Put the token into the receive packet queue successfully.\r
-  @retval others           Put the token into the receive packet queue unsuccessfully.\r
-\r
-**/\r
-EFI_STATUS\r
-Ping6ReceiveEchoReply (\r
-  IN PING6_PRIVATE_DATA    *Private\r
-  )\r
-{\r
-  EFI_STATUS    Status;\r
-\r
-  ZeroMem (&Private->RxToken, sizeof (EFI_IP6_COMPLETION_TOKEN));\r
-\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
-                  Ping6OnEchoReplyReceived,\r
-                  Private,\r
-                  &Private->RxToken.Event\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Private->RxToken.Status = EFI_NOT_READY;\r
-\r
-  return Private->Ip6->Receive (Private->Ip6, &Private->RxToken);\r
-}\r
-\r
-/**\r
-  Remove the timeout request from the list.\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
-Ping6OnTimerRoutine (\r
-  IN EFI_EVENT    Event,\r
-  IN VOID         *Context\r
-  )\r
-{\r
-  EFI_STATUS             Status;\r
-  PING6_PRIVATE_DATA     *Private;\r
-  PING6_ICMP6_TX_INFO    *TxInfo;\r
-  LIST_ENTRY             *Entry;\r
-  LIST_ENTRY             *NextEntry;\r
-  UINT64                 Time;\r
-\r
-  Private = (PING6_PRIVATE_DATA *) Context;\r
-\r
-  //\r
-  // Retransmit icmp6 echo request packets per second in sendnumber times.\r
-  //\r
-  if (Private->TxCount < Private->SendNum) {\r
-\r
-    Status = Ping6SendEchoRequest (Private);\r
-    if (Private->TxCount != 0){\r
-      if (EFI_ERROR (Status)) {\r
-        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_SEND_REQUEST), mHiiHandle, Private->TxCount + 1);\r
-      }\r
-    }\r
-  }\r
-  //\r
-  // Check whether any icmp6 echo request in the list timeout.\r
-  //\r
-  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {\r
-    TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link);\r
-    Time   = Ping6CalculateTick (TxInfo->TimeStamp, ReadTime ());\r
-\r
-    //\r
-    // Remove the timeout echo request from txlist.\r
-    //\r
-    if (Time > PING6_DEFAULT_TIMEOUT) {\r
-\r
-      if (EFI_ERROR (TxInfo->Token->Status)) {\r
-        Private->Ip6->Cancel (Private->Ip6, TxInfo->Token);\r
-      }\r
-      //\r
-      // Remove the timeout icmp6 echo request from list.\r
-      //\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_TIMEOUT), mHiiHandle, TxInfo->SequenceNum);\r
-\r
-      RemoveEntryList (&TxInfo->Link);\r
-      Ping6DestroyTxInfo (TxInfo);\r
-\r
-      if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) {\r
-        //\r
-        // All the left icmp6 echo request in the list timeout.\r
-        //\r
-        Private->Status = EFI_TIMEOUT;\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
-  Create a valid IP6 instance.\r
-\r
-  @param[in]    Private    The pointer of PING6_PRIVATE_DATA.\r
-\r
-  @retval EFI_SUCCESS              Create a valid IP6 instance successfully.\r
-  @retval EFI_ABORTED              Locate handle with ip6 service binding protocol unsuccessfully.\r
-  @retval EFI_INVALID_PARAMETER    The source address is unspecified when the destination address is a link -ocal address.\r
-  @retval EFI_OUT_OF_RESOURCES     No memory is available on the platform.\r
-  @retval EFI_NOT_FOUND            The source address is not found.\r
-**/\r
-EFI_STATUS\r
-Ping6CreateIp6Instance (\r
-  IN  PING6_PRIVATE_DATA    *Private\r
-  )\r
-{\r
-  EFI_STATUS                       Status;\r
-  UINTN                            HandleIndex;\r
-  UINTN                            HandleNum;\r
-  EFI_HANDLE                       *HandleBuffer;\r
-  EFI_SERVICE_BINDING_PROTOCOL     *Ip6Sb;\r
-  EFI_IP6_CONFIG_PROTOCOL          *Ip6Cfg;\r
-  EFI_IP6_CONFIG_DATA              Ip6Config;\r
-  EFI_IP6_CONFIG_INTERFACE_INFO    *IfInfo;\r
-  UINTN                            IfInfoSize;\r
-  EFI_IPv6_ADDRESS                 *Addr;\r
-  UINTN                            AddrIndex;\r
-\r
-  HandleBuffer = NULL;\r
-  Ip6Sb        = NULL;\r
-  IfInfo       = NULL;\r
-  IfInfoSize   = 0;\r
-\r
-  //\r
-  // Locate all the handles with ip6 service binding protocol.\r
-  //\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiIp6ServiceBindingProtocolGuid,\r
-                  NULL,\r
-                  &HandleNum,\r
-                  &HandleBuffer\r
-                  );\r
-  if (EFI_ERROR (Status) || (HandleNum == 0)) {\r
-    return EFI_ABORTED;\r
-  }\r
-  //\r
-  // Source address is required when pinging a link-local address on multi-\r
-  // interfaces host.\r
-  //\r
-  if (NetIp6IsLinkLocalAddr (&Private->DstAddress) &&\r
-      NetIp6IsUnspecifiedAddr (&Private->SrcAddress) &&\r
-      (HandleNum > 1)) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SOURCE), mHiiHandle);\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto ON_ERROR;\r
-  }\r
-  //\r
-  // For each ip6 protocol, check interface addresses list.\r
-  //\r
-  for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {\r
-\r
-    Ip6Sb      = NULL;\r
-    IfInfo     = NULL;\r
-    IfInfoSize = 0;\r
-\r
-    Status = gBS->HandleProtocol (\r
-                    HandleBuffer[HandleIndex],\r
-                    &gEfiIp6ServiceBindingProtocolGuid,\r
-                    (VOID **) &Ip6Sb\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      goto ON_ERROR;\r
-    }\r
-\r
-    if (NetIp6IsUnspecifiedAddr (&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
-                      &gEfiIp6ConfigProtocolGuid,\r
-                      (VOID **) &Ip6Cfg\r
-                      );\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        goto ON_ERROR;\r
-      }\r
-      //\r
-      // Get the interface information size.\r
-      //\r
-      Status = Ip6Cfg->GetData (\r
-                         Ip6Cfg,\r
-                         Ip6ConfigDataTypeInterfaceInfo,\r
-                         &IfInfoSize,\r
-                         NULL\r
-                         );\r
-\r
-      if (Status != EFI_BUFFER_TOO_SMALL) {\r
-        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), mHiiHandle, Status);\r
-        goto ON_ERROR;\r
-      }\r
-\r
-      IfInfo = AllocateZeroPool (IfInfoSize);\r
-\r
-      if (IfInfo == NULL) {\r
-        Status = EFI_OUT_OF_RESOURCES;\r
-        goto ON_ERROR;\r
-      }\r
-      //\r
-      // Get the interface info.\r
-      //\r
-      Status = Ip6Cfg->GetData (\r
-                         Ip6Cfg,\r
-                         Ip6ConfigDataTypeInterfaceInfo,\r
-                         &IfInfoSize,\r
-                         IfInfo\r
-                         );\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), mHiiHandle, Status);\r
-        goto ON_ERROR;\r
-      }\r
-      //\r
-      // Check whether the source address is one of the interface addresses.\r
-      //\r
-      for (AddrIndex = 0; AddrIndex < IfInfo->AddressInfoCount; AddrIndex++) {\r
-\r
-        Addr = &(IfInfo->AddressInfo[AddrIndex].Address);\r
-        if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {\r
-          //\r
-          // Match a certain interface address.\r
-          //\r
-          break;\r
-        }\r
-      }\r
-\r
-      if (AddrIndex < IfInfo->AddressInfoCount) {\r
-        //\r
-        // Found a nic handle with right interface address.\r
-        //\r
-        break;\r
-      }\r
-    }\r
-\r
-    FreePool (IfInfo);\r
-    IfInfo = NULL;\r
-  }\r
-  //\r
-  // No exact interface address matched.\r
-  //\r
-\r
-  if (HandleIndex == HandleNum) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_SOURCE_NOT_FOUND), mHiiHandle, mIp6SrcString);\r
-    Status = EFI_NOT_FOUND;\r
-    goto ON_ERROR;\r
-  }\r
-\r
-  Private->NicHandle = HandleBuffer[HandleIndex];\r
-\r
-  ASSERT (Ip6Sb != NULL);\r
-  Status = Ip6Sb->CreateChild (Ip6Sb, &Private->Ip6ChildHandle);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
-\r
-  Status = gBS->OpenProtocol (\r
-                  Private->Ip6ChildHandle,\r
-                  &gEfiIp6ProtocolGuid,\r
-                  (VOID **) &Private->Ip6,\r
-                  Private->ImageHandle,\r
-                  Private->Ip6ChildHandle,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
-\r
-  ZeroMem (&Ip6Config, sizeof (EFI_IP6_CONFIG_DATA));\r
-\r
-  //\r
-  // Configure the ip6 instance for icmp6 packet exchange.\r
-  //\r
-  Ip6Config.DefaultProtocol   = 58;\r
-  Ip6Config.AcceptAnyProtocol = FALSE;\r
-  Ip6Config.AcceptIcmpErrors  = TRUE;\r
-  Ip6Config.AcceptPromiscuous = FALSE;\r
-  Ip6Config.TrafficClass      = 0;\r
-  Ip6Config.HopLimit          = 128;\r
-  Ip6Config.FlowLabel         = 0;\r
-  Ip6Config.ReceiveTimeout    = 0;\r
-  Ip6Config.TransmitTimeout   = 0;\r
-\r
-  IP6_COPY_ADDRESS (&Ip6Config.StationAddress, &Private->SrcAddress);\r
-\r
-  IP6_COPY_ADDRESS (&Ip6Config.DestinationAddress, &Private->DstAddress);\r
-\r
-  Status = Private->Ip6->Configure (Private->Ip6, &Ip6Config);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6_CONFIG), mHiiHandle, Status);\r
-    goto ON_ERROR;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-\r
-ON_ERROR:\r
-  if (HandleBuffer != NULL) {\r
-    FreePool (HandleBuffer);\r
-  }\r
-\r
-  if (IfInfo != NULL) {\r
-    FreePool (IfInfo);\r
-  }\r
-\r
-  if ((Ip6Sb != NULL) && (Private->Ip6ChildHandle != NULL)) {\r
-    Ip6Sb->DestroyChild (Ip6Sb, Private->Ip6ChildHandle);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Destroy the IP6 instance.\r
-\r
-  @param[in]    Private    The pointer of PING6_PRIVATE_DATA.\r
-\r
-**/\r
-VOID\r
-Ping6DestroyIp6Instance (\r
-  IN PING6_PRIVATE_DATA    *Private\r
-  )\r
-{\r
-  EFI_STATUS                      Status;\r
-  EFI_SERVICE_BINDING_PROTOCOL    *Ip6Sb;\r
-\r
-  gBS->CloseProtocol (\r
-         Private->Ip6ChildHandle,\r
-         &gEfiIp6ProtocolGuid,\r
-         Private->ImageHandle,\r
-         Private->Ip6ChildHandle\r
-         );\r
-\r
-  Status = gBS->HandleProtocol (\r
-                  Private->NicHandle,\r
-                  &gEfiIp6ServiceBindingProtocolGuid,\r
-                  (VOID **) &Ip6Sb\r
-                  );\r
-\r
-  if (!EFI_ERROR(Status)) {\r
-    Ip6Sb->DestroyChild (Ip6Sb, Private->Ip6ChildHandle);\r
-  }\r
-}\r
-\r
-/**\r
-  The Ping6 Process.\r
-\r
-  @param[in]   ImageHandle    The firmware allocated handle for the UEFI image.\r
-  @param[in]   SendNumber     The send request count.\r
-  @param[in]   BufferSize     The send buffer size.\r
-  @param[in]   SrcAddress     The source IPv6 address.\r
-  @param[in]   DstAddress     The destination IPv6 address.\r
-\r
-  @retval EFI_SUCCESS    The ping6 processed successfullly.\r
-  @retval others         The ping6 processed unsuccessfully.\r
-\r
-**/\r
-EFI_STATUS\r
-Ping6 (\r
-  IN EFI_HANDLE          ImageHandle,\r
-  IN UINT32              SendNumber,\r
-  IN UINT32              BufferSize,\r
-  IN EFI_IPv6_ADDRESS    *SrcAddress,\r
-  IN EFI_IPv6_ADDRESS    *DstAddress\r
-  )\r
-{\r
-  EFI_STATUS             Status;\r
-  EFI_INPUT_KEY          Key;\r
-  PING6_PRIVATE_DATA     *Private;\r
-  PING6_ICMP6_TX_INFO    *TxInfo;\r
-  LIST_ENTRY             *Entry;\r
-  LIST_ENTRY             *NextEntry;\r
-\r
-  Private = AllocateZeroPool (sizeof (PING6_PRIVATE_DATA));\r
-\r
-  ASSERT (Private != NULL);\r
-\r
-  Private->ImageHandle = ImageHandle;\r
-  Private->SendNum     = SendNumber;\r
-  Private->BufferSize  = BufferSize;\r
-  Private->RttMin      = ~((UINT64 )(0x0));\r
-  Private->Status      = EFI_NOT_READY;\r
-\r
-  InitializeListHead (&Private->TxList);\r
-\r
-  IP6_COPY_ADDRESS (&Private->SrcAddress, SrcAddress);\r
-  IP6_COPY_ADDRESS (&Private->DstAddress, DstAddress);\r
-\r
-  //\r
-  // Open and configure a ip6 instance for ping6.\r
-  //\r
-  Status = Ping6CreateIp6Instance (Private);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-  //\r
-  // Print the command line itself.\r
-  //\r
-  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_START), mHiiHandle, mIp6DstString, Private->BufferSize);\r
-  //\r
-  // Create a ipv6 token to receive the first icmp6 echo reply packet.\r
-  //\r
-  Status = Ping6ReceiveEchoReply (Private);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-  //\r
-  // Create and start timer to send icmp6 echo request packet per second.\r
-  //\r
-  Status = gBS->CreateEvent (\r
-                  EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
-                  Ping6OnTimerRoutine,\r
-                  Private,\r
-                  &Private->Timer\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-  //\r
-  // Create a ipv6 token to send the first icmp6 echo request packet.\r
-  //\r
-  Status = Ping6SendEchoRequest (Private);\r
-  //\r
-  // EFI_NOT_READY for IPsec is enable and IKE is not established.\r
-  //\r
-  if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {\r
-    if(Status == EFI_NOT_FOUND) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_NOSOURCE_INDOMAIN), mHiiHandle, mIp6DstString);\r
-    }\r
-\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Status = gBS->SetTimer (\r
-                  Private->Timer,\r
-                  TimerPeriodic,\r
-                  PING6_ONE_SECOND\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-  //\r
-  // Control the ping6 process by two factors:\r
-  // 1. Hot key\r
-  // 2. Private->Status\r
-  //   2.1. success means all icmp6 echo request packets get reply packets.\r
-  //   2.2. timeout means the last icmp6 echo reply request timeout to get reply.\r
-  //   2.3. noready means ping6 process is on-the-go.\r
-  //\r
-  while (Private->Status == EFI_NOT_READY) {\r
-    Private->Ip6->Poll (Private->Ip6);\r
-\r
-    //\r
-    // Terminate the ping6 process by 'esc' or 'ctl-c'.\r
-    //\r
-    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
-\r
-    if (!EFI_ERROR(Status)) {\r
-      if ((Key.UnicodeChar == 0x1b) || (Key.UnicodeChar == 0x03) ||\r
-         ((Key.UnicodeChar == 0) && (Key.ScanCode == SCAN_ESC))) {\r
-        goto ON_STAT;\r
-      }\r
-    }\r
-  }\r
-\r
-ON_STAT:\r
-  //\r
-  // Display the statistics in all.\r
-  //\r
-  gBS->SetTimer (Private->Timer, TimerCancel, 0);\r
-\r
-  if (Private->TxCount != 0) {\r
-    ShellPrintHiiEx (\r
-      -1,\r
-      -1,\r
-      NULL,\r
-      STRING_TOKEN (STR_PING6_STAT),\r
-      mHiiHandle,\r
-      Private->TxCount,\r
-      Private->RxCount,\r
-      (100 * (Private->TxCount - Private->RxCount)) / Private->TxCount,\r
-      Private->RttSum\r
-      );\r
-  }\r
-\r
-  if (Private->RxCount != 0) {\r
-    ShellPrintHiiEx (\r
-      -1,\r
-      -1,\r
-      NULL,\r
-      STRING_TOKEN (STR_PING6_RTT),\r
-      mHiiHandle,\r
-      Private->RttMin,\r
-      Private->RttMax,\r
-      DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL)\r
-      );\r
-  }\r
-\r
-ON_EXIT:\r
-\r
-  if (Private != NULL) {\r
-    Private->Status = EFI_ABORTED;\r
-\r
-    NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {\r
-      TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link);\r
-\r
-      Status = Private->Ip6->Cancel (Private->Ip6, TxInfo->Token);\r
-\r
-      RemoveEntryList (&TxInfo->Link);\r
-      Ping6DestroyTxInfo (TxInfo);\r
-    }\r
-\r
-    if (Private->Timer != NULL) {\r
-      gBS->CloseEvent (Private->Timer);\r
-    }\r
-\r
-    if (Private->Ip6 != NULL) {\r
-      Status = Private->Ip6->Cancel (Private->Ip6, &Private->RxToken);\r
-    }\r
-\r
-    if (Private->RxToken.Event != NULL) {\r
-      gBS->CloseEvent (Private->RxToken.Event);\r
-    }\r
-\r
-    if (Private->Ip6ChildHandle != NULL) {\r
-      Ping6DestroyIp6Instance (Private);\r
-    }\r
-\r
-    FreePool (Private);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  This is the declaration of an EFI image entry point. This entry point is\r
-  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including\r
-  both device drivers and bus drivers.\r
-\r
-  The entry point for the Ping6 application that parses the command line input and calls the Ping6 process.\r
-\r
-  @param[in] ImageHandle    The firmware allocated handle for the UEFI image.\r
-  @param[in] SystemTable    A pointer to the EFI System Table.\r
-\r
-  @retval EFI_SUCCESS               The operation completed successfully.\r
-  @retval EFI_INVALID_PARAMETETR    Input parameters combination is invalid.\r
-  @retval Others                    Some errors occur.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InitializePing6 (\r
-  IN  EFI_HANDLE          ImageHandle,\r
-  IN  EFI_SYSTEM_TABLE    *SystemTable\r
-  )\r
-{\r
-  EFI_STATUS          Status;\r
-  EFI_IPv6_ADDRESS    DstAddress;\r
-  EFI_IPv6_ADDRESS    SrcAddress;\r
-  UINT64              BufferSize;\r
-  UINTN               SendNumber;\r
-  LIST_ENTRY          *ParamPackage;\r
-  CONST CHAR16        *ValueStr;\r
-  CONST CHAR16        *ValueStrPtr;\r
-  UINTN               NonOptionCount;\r
-  EFI_HII_PACKAGE_LIST_HEADER     *PackageList;\r
-\r
-  //\r
-  // Retrieve HII package list from ImageHandle\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  ImageHandle,\r
-                  &gEfiHiiPackageListProtocolGuid,\r
-                  (VOID **) &PackageList,\r
-                  ImageHandle,\r
-                  NULL,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Publish HII package list to HII Database.\r
-  //\r
-  Status = gHiiDatabase->NewPackageList (\r
-                          gHiiDatabase,\r
-                          PackageList,\r
-                          NULL,\r
-                          &mHiiHandle\r
-                          );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  \r
-  ASSERT (mHiiHandle != NULL);\r
-\r
-  Status = ShellCommandLineParseEx (Ping6ParamList, &ParamPackage, NULL, TRUE, FALSE);\r
-  if (EFI_ERROR(Status)) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_INPUT), mHiiHandle);\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  SendNumber = 10;\r
-  BufferSize = 16;\r
-\r
-  //\r
-  // Parse the parameter of count number.\r
-  //\r
-  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n");\r
-  ValueStrPtr = ValueStr;\r
-  if (ValueStr != NULL) {\r
-    SendNumber = ShellStrToUintn (ValueStrPtr);\r
-\r
-    //\r
-    // ShellStrToUintn will return 0 when input is 0 or an invalid input string.\r
-    //\r
-    if ((SendNumber == 0) || (SendNumber > PING6_MAX_SEND_NUMBER)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SEND_NUMBER), mHiiHandle, ValueStr);\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
-  //\r
-  // Parse the parameter of buffer size.\r
-  //\r
-  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");\r
-  ValueStrPtr = ValueStr;\r
-  if (ValueStr != NULL) {\r
-    BufferSize = ShellStrToUintn (ValueStrPtr);\r
-\r
-    //\r
-    // ShellStrToUintn will return 0 when input is 0 or an invalid input string.\r
-    //\r
-    if ((BufferSize < 16) || (BufferSize > PING6_MAX_BUFFER_SIZE)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_BUFFER_SIZE), mHiiHandle, ValueStr);\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
-\r
-  ZeroMem (&SrcAddress, sizeof (EFI_IPv6_ADDRESS));\r
-  ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS));\r
-\r
-  //\r
-  // Parse the parameter of source ip address.\r
-  //\r
-  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");\r
-  ValueStrPtr = ValueStr;\r
-  if (ValueStr != NULL) {\r
-    mIp6SrcString = ValueStr;\r
-    Status = NetLibStrToIp6 (ValueStrPtr, &SrcAddress);\r
-    if (EFI_ERROR (Status)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_IP), mHiiHandle, ValueStr);\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
-  //\r
-  // Parse the parameter of destination ip address.\r
-  //\r
-  NonOptionCount = ShellCommandLineGetCount(ParamPackage);\r
-  ValueStr = ShellCommandLineGetRawValue (ParamPackage, (UINT32)(NonOptionCount-1));\r
-  if (NonOptionCount != 2) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_INPUT), mHiiHandle);\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto ON_EXIT;\r
-  }\r
-  ValueStrPtr = ValueStr;\r
-  if (ValueStr != NULL) {\r
-    mIp6DstString = ValueStr;\r
-    Status = NetLibStrToIp6 (ValueStrPtr, &DstAddress);\r
-    if (EFI_ERROR (Status)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_IP), mHiiHandle, ValueStr);\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
-  //\r
-  // Get frequency to calculate the time from ticks.\r
-  //\r
-  Status = Ping6GetFrequency ();\r
-\r
-  if (EFI_ERROR(Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-  //\r
-  // Enter into ping6 process.\r
-  //\r
-  Status = Ping6 (\r
-             ImageHandle,\r
-             (UINT32)SendNumber,\r
-             (UINT32)BufferSize,\r
-             &SrcAddress,\r
-             &DstAddress\r
-             );\r
-\r
-ON_EXIT:\r
-  ShellCommandLineFreeVarList (ParamPackage);\r
-  HiiRemovePackages (mHiiHandle);\r
-  return Status;\r
-}\r