1a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/** @file
2a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  The implementation for Ping6 application.
3a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
45edac28e83eb477b7c509e688ad43739a30b0818Shumin Qiu  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
5a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
6a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  This program and the accompanying materials
7a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  are licensed and made available under the terms and conditions of the BSD License
8a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  which accompanies this distribution.  The full text of the license may be found at
9a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  http://opensource.org/licenses/bsd-license.php.
10a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
11a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
14a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
15a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
16a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include <Library/ShellLib.h>
17a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include <Library/BaseMemoryLib.h>
18a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include <Library/BaseLib.h>
19a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include <Library/MemoryAllocationLib.h>
20a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include <Library/DebugLib.h>
21a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include <Library/UefiBootServicesTableLib.h>
22a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include <Library/HiiLib.h>
23a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include <Library/NetLib.h>
24a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
25a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include <Protocol/Cpu.h>
26a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include <Protocol/ServiceBinding.h>
27a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include <Protocol/Ip6.h>
28a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include <Protocol/Ip6Config.h>
29a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
30a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian#include "Ping6.h"
31a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
32a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianSHELL_PARAM_ITEM    Ping6ParamList[] = {
33a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  {
34a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    L"-l",
35a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    TypeValue
36a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  },
37a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  {
38a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    L"-n",
39a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    TypeValue
40a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  },
41a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  {
42a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    L"-s",
43a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    TypeValue
44a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  },
45a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  {
46a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    L"-?",
47a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    TypeFlag
48a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  },
49a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  {
50a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    NULL,
51a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    TypeMax
52a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  },
53a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian};
54a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
55a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian//
56a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian// Global Variables in Ping6 application.
57a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian//
58a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFI_HII_HANDLE    mHiiHandle;
59a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianCONST CHAR16      *mIp6DstString;
60a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianCONST CHAR16      *mIp6SrcString;
61cda10fe42c95c187902a7d4e980a133e89e59da5tyeUINT64            mFrequency = 0;
62a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
635edac28e83eb477b7c509e688ad43739a30b0818Shumin Qiu  Get and calculate the frequency in tick/ms.
64a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  The result is saved in the globle variable mFrequency
65a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
665edac28e83eb477b7c509e688ad43739a30b0818Shumin Qiu  @retval EFI_SUCCESS    Calculated the frequency successfully.
675edac28e83eb477b7c509e688ad43739a30b0818Shumin Qiu  @retval Others         Failed to calculate the frequency.
68a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
69a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
70a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFI_STATUS
71a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianPing6GetFrequency (
72a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  VOID
73a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
74a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
75a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_STATUS               Status;
76a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_CPU_ARCH_PROTOCOL    *Cpu;
77a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  UINT64                   CurrentTick;
78cda10fe42c95c187902a7d4e980a133e89e59da5tye  UINT64                   TimerPeriod;
79a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
80a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Cpu);
81a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
82a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status)) {
83a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    return Status;
84a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
85a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
86cda10fe42c95c187902a7d4e980a133e89e59da5tye  Status = Cpu->GetTimerValue (Cpu, 0, &CurrentTick, &TimerPeriod);
87a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
88a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status)) {
89a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
90a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    // For NT32 Simulator only. 358049 is a similar value to keep timer granularity.
91a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    // Set the timer period by ourselves.
92a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
93cda10fe42c95c187902a7d4e980a133e89e59da5tye    TimerPeriod = (UINT64) NTTIMERPERIOD;
94a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
95a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
96a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // The timer period is in femtosecond (1 femtosecond is 1e-15 second).
97a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // So 1e+12 is divided by timer period to produce the freq in tick/ms.
98a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
99cda10fe42c95c187902a7d4e980a133e89e59da5tye  mFrequency = DivU64x64Remainder (1000000000000ULL, TimerPeriod, NULL);
100a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
101a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  return EFI_SUCCESS;
102a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
103a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
104a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
1055edac28e83eb477b7c509e688ad43739a30b0818Shumin Qiu  Get and calculate the duration in ms.
106a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
107a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]  Begin    The start point of time.
108a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]  End      The end point of time.
109a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
110a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @return The duration in ms.
111a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
112a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
113cda10fe42c95c187902a7d4e980a133e89e59da5tyeUINT64
114a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianPing6CalculateTick (
115a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN UINT64    Begin,
116a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN UINT64    End
117a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
118a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
119a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ASSERT (End > Begin);
120cda10fe42c95c187902a7d4e980a133e89e59da5tye  return DivU64x64Remainder (End - Begin, mFrequency, NULL);
121a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
122a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
123a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
124a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Destroy IPING6_ICMP6_TX_INFO, and recollect the memory.
125a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
126a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    TxInfo    The pointer to PING6_ICMP6_TX_INFO.
127a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
128a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
129a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianVOID
130a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianPing6DestroyTxInfo (
131a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN PING6_ICMP6_TX_INFO    *TxInfo
132a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
133a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
134a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_IP6_TRANSMIT_DATA    *TxData;
135a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_IP6_FRAGMENT_DATA    *FragData;
136a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  UINTN                    Index;
137a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
138a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ASSERT (TxInfo != NULL);
139a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
140a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (TxInfo->Token != NULL) {
141a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
142a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (TxInfo->Token->Event != NULL) {
143a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      gBS->CloseEvent (TxInfo->Token->Event);
144a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
145a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
146a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    TxData = TxInfo->Token->Packet.TxData;
147a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (TxData != NULL) {
148a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
149a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      if (TxData->OverrideData != NULL) {
150a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        FreePool (TxData->OverrideData);
151a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
152a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
153a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      if (TxData->ExtHdrs != NULL) {
154a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        FreePool (TxData->ExtHdrs);
155a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
156a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
157a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      for (Index = 0; Index < TxData->FragmentCount; Index++) {
158a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        FragData = TxData->FragmentTable[Index].FragmentBuffer;
159a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        if (FragData != NULL) {
160a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian          FreePool (FragData);
161a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        }
162a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
163a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
164a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
165a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    FreePool (TxInfo->Token);
166a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
167a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
168a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  FreePool (TxInfo);
169a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
170a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
171a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
172a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Match the request, and reply with SequenceNum/TimeStamp.
173a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
174a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Private    The pointer to PING6_PRIVATE_DATA.
175a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Packet     The pointer to ICMP6_ECHO_REQUEST_REPLY.
176a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
177a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_SUCCESS      The match is successful.
178a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_NOT_FOUND    The reply can't be matched with any request.
179a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
180a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
181a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFI_STATUS
182a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianPing6MatchEchoReply (
183a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN PING6_PRIVATE_DATA          *Private,
184a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN ICMP6_ECHO_REQUEST_REPLY    *Packet
185a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
186a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
187a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  PING6_ICMP6_TX_INFO    *TxInfo;
188a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  LIST_ENTRY             *Entry;
189a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  LIST_ENTRY             *NextEntry;
190a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
191a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
192a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link);
193a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
194a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if ((TxInfo->SequenceNum == Packet->SequenceNum) && (TxInfo->TimeStamp == Packet->TimeStamp)) {
195a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Private->RxCount++;
196a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      RemoveEntryList (&TxInfo->Link);
197a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Ping6DestroyTxInfo (TxInfo);
198a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      return EFI_SUCCESS;
199a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
200a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
201a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
202a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  return EFI_NOT_FOUND;
203a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
204a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
205a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
206a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  The original intention is to send a request.
207a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Currently, the application retransmits an icmp6 echo request packet
208a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  per second in sendnumber times that is specified by the user.
209a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Because nothing can be done here, all things move to the timer rountine.
210a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
211a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Event      A EFI_EVENT type event.
212a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Context    The pointer to Context.
213a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
214a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
215a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianVOID
216a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFIAPI
217a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianPing6OnEchoRequestSent (
218a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN EFI_EVENT    Event,
219a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN VOID         *Context
220a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
221a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
222a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
223a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
224a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
225a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  receive reply, match and print reply infomation.
226a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
227a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Event      A EFI_EVENT type event.
228a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Context    The pointer to context.
229a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
230a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
231a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianVOID
232a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFIAPI
233a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianPing6OnEchoReplyReceived (
234a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN EFI_EVENT    Event,
235a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN VOID         *Context
236a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
237a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
238a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_STATUS                  Status;
239a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  PING6_PRIVATE_DATA          *Private;
240a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_IP6_COMPLETION_TOKEN    *RxToken;
241a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_IP6_RECEIVE_DATA        *RxData;
242a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ICMP6_ECHO_REQUEST_REPLY    *Reply;
243a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  UINT32                      PayLoad;
244cda10fe42c95c187902a7d4e980a133e89e59da5tye  UINT64                      Rtt;
245a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  CHAR8                       Near;
246a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
247a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private = (PING6_PRIVATE_DATA *) Context;
248a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
249a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (Private->Status == EFI_ABORTED) {
250a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    return;
251a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
252a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
253a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  RxToken = &Private->RxToken;
254a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  RxData  = RxToken->Packet.RxData;
255a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Reply   = RxData->FragmentTable[0].FragmentBuffer;
256a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  PayLoad = RxData->DataLength;
257a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
258a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (RxData->Header->NextHeader != IP6_ICMP) {
259a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
260a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
261a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
262a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (!IP6_IS_MULTICAST (&Private->DstAddress) &&
263a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      !EFI_IP6_EQUAL (&RxData->Header->SourceAddress, &Private->DstAddress)) {
264a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
265a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
266a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
267a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if ((Reply->Type != ICMP_V6_ECHO_REPLY) || (Reply->Code != 0)) {
268a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
269a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
270a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
271a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (PayLoad != Private->BufferSize) {
272a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
273a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
274a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
275a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Check whether the reply matches the sent request before.
276a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
277a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = Ping6MatchEchoReply (Private, Reply);
278a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR(Status)) {
279a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
280a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
281a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
282a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Display statistics on this icmp6 echo reply packet.
283a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
284a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Rtt  = Ping6CalculateTick (Reply->TimeStamp, ReadTime ());
285a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (Rtt != 0) {
286a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Near = (CHAR8) '=';
287a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  } else {
288a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Near = (CHAR8) '<';
289a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
290a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
291a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private->RttSum += Rtt;
292a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private->RttMin  = Private->RttMin > Rtt ? Rtt : Private->RttMin;
293a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private->RttMax  = Private->RttMax < Rtt ? Rtt : Private->RttMax;
294a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
295a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ShellPrintHiiEx (
296a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    -1,
297a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    -1,
298a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    NULL,
299a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    STRING_TOKEN (STR_PING6_REPLY_INFO),
300a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    mHiiHandle,
301a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    PayLoad,
302a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    mIp6DstString,
303a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Reply->SequenceNum,
304a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    RxData->Header->HopLimit,
305a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Near,
306a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Rtt
307a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    );
308a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
309a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianON_EXIT:
310a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
311a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (Private->RxCount < Private->SendNum) {
312a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
313a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    // Continue to receive icmp6 echo reply packets.
314a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
315a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    RxToken->Status = EFI_ABORTED;
316a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
317a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Status = Private->Ip6->Receive (Private->Ip6, RxToken);
318a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
319a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (EFI_ERROR (Status)) {
320a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Private->Status = EFI_ABORTED;
321a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
322a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  } else {
323a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
324a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    // All reply have already been received from the dest host.
325a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
326a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Private->Status = EFI_SUCCESS;
327a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
328a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
329a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Singal to recycle the each rxdata here, not at the end of process.
330a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
331a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  gBS->SignalEvent (RxData->RecycleSignal);
332a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
333a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
334a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
335a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Initial EFI_IP6_COMPLETION_TOKEN.
336a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
337a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Private        The pointer of PING6_PRIVATE_DATA.
338a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    TimeStamp      The TimeStamp of request.
339a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    SequenceNum    The SequenceNum of request.
340a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
341a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @return The pointer of EFI_IP6_COMPLETION_TOKEN.
342a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
343a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
344a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFI_IP6_COMPLETION_TOKEN *
345a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianPing6GenerateToken (
346a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN PING6_PRIVATE_DATA    *Private,
347a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN UINT64                TimeStamp,
348a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN UINT16                SequenceNum
349a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
350a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
351a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_STATUS                  Status;
352a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_IP6_COMPLETION_TOKEN    *Token;
353a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_IP6_TRANSMIT_DATA       *TxData;
354a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ICMP6_ECHO_REQUEST_REPLY    *Request;
355a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
356a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Request = AllocateZeroPool (Private->BufferSize);
357a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
358a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (Request == NULL) {
359a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    return NULL;
360a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
361a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
362a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Assembly icmp6 echo request packet.
363a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
364a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Request->Type        = ICMP_V6_ECHO_REQUEST;
365a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Request->Code        = 0;
366a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Request->SequenceNum = SequenceNum;
367a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Request->TimeStamp   = TimeStamp;
368a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Request->Identifier  = 0;
369a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
370a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Leave check sum to ip6 layer, since it has no idea of source address
371a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // selection.
372a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
373a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Request->Checksum    = 0;
374a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
375a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  TxData = AllocateZeroPool (sizeof (EFI_IP6_TRANSMIT_DATA));
376a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
377a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (TxData == NULL) {
378a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    FreePool (Request);
379a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    return NULL;
380a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
381a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
382a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Assembly ipv6 token for transmit.
383a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
384a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  TxData->OverrideData       = 0;
385a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  TxData->ExtHdrsLength      = 0;
386a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  TxData->ExtHdrs            = NULL;
387a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  TxData->DataLength         = Private->BufferSize;
388a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  TxData->FragmentCount      = 1;
389a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  TxData->FragmentTable[0].FragmentBuffer = (VOID *) Request;
390a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  TxData->FragmentTable[0].FragmentLength = Private->BufferSize;
391a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
392a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Token = AllocateZeroPool (sizeof (EFI_IP6_COMPLETION_TOKEN));
393a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
394a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (Token == NULL) {
395a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    FreePool (Request);
396a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    FreePool (TxData);
397a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    return NULL;
398a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
399a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
400a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Token->Status         = EFI_ABORTED;
401a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Token->Packet.TxData  = TxData;
402a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
403a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = gBS->CreateEvent (
404a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  EVT_NOTIFY_SIGNAL,
405a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  TPL_CALLBACK,
406a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  Ping6OnEchoRequestSent,
407a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  Private,
408a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  &Token->Event
409a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  );
410a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
411a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status)) {
412a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    FreePool (Request);
413a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    FreePool (TxData);
414a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    FreePool (Token);
415a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    return NULL;
416a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
417a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
418a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  return Token;
419a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
420a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
421a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
422a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Transmit the EFI_IP6_COMPLETION_TOKEN.
423a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
424a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Private    The pointer of PING6_PRIVATE_DATA.
425a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
426a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_SUCCESS             Transmitted successfully.
427a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_OUT_OF_RESOURCES    No memory is available on the platform.
428a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval others                  Transmitted unsuccessfully.
429a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
430a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
431a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFI_STATUS
432a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianPing6SendEchoRequest (
433a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN PING6_PRIVATE_DATA    *Private
434a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
435a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
436a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_STATUS             Status;
437a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  PING6_ICMP6_TX_INFO    *TxInfo;
438a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
439a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  TxInfo = AllocateZeroPool (sizeof (PING6_ICMP6_TX_INFO));
440a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
441a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (TxInfo == NULL) {
442a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    return EFI_OUT_OF_RESOURCES;
443a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
444a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
445a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  TxInfo->TimeStamp   = ReadTime ();
446a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1);
447a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
448a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  TxInfo->Token       = Ping6GenerateToken (
449a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                          Private,
450a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                          TxInfo->TimeStamp,
451a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                          TxInfo->SequenceNum
452a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                          );
453a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
454a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (TxInfo->Token == NULL) {
455a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Ping6DestroyTxInfo (TxInfo);
456a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    return EFI_OUT_OF_RESOURCES;
457a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
458a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
459a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = Private->Ip6->Transmit (Private->Ip6, TxInfo->Token);
460a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
461a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status)) {
462a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Ping6DestroyTxInfo (TxInfo);
463a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    return Status;
464a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
465a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
466a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  InsertTailList (&Private->TxList, &TxInfo->Link);
467a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private->TxCount++;
468a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
469a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  return EFI_SUCCESS;
470a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
471a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
472a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
473a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Place a completion token into the receive packet queue to receive the echo reply.
474a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
475a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Private    The pointer of PING6_PRIVATE_DATA.
476a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
477a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_SUCCESS      Put the token into the receive packet queue successfully.
478a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval others           Put the token into the receive packet queue unsuccessfully.
479a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
480a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
481a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFI_STATUS
482a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianPing6ReceiveEchoReply (
483a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN PING6_PRIVATE_DATA    *Private
484a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
485a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
486a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_STATUS    Status;
487a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
488a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ZeroMem (&Private->RxToken, sizeof (EFI_IP6_COMPLETION_TOKEN));
489a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
490a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = gBS->CreateEvent (
491a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  EVT_NOTIFY_SIGNAL,
492a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  TPL_CALLBACK,
493a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  Ping6OnEchoReplyReceived,
494a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  Private,
495a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  &Private->RxToken.Event
496a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  );
497a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
498a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status)) {
499a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    return Status;
500a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
501a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
502a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private->RxToken.Status = EFI_NOT_READY;
503a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
504a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  return Private->Ip6->Receive (Private->Ip6, &Private->RxToken);
505a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
506a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
507a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
508a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Remove the timeout request from the list.
509a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
510a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Event    A EFI_EVENT type event.
511a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Context  The pointer to Context.
512a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
513a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
514a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianVOID
515a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFIAPI
516a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianPing6OnTimerRoutine (
517a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN EFI_EVENT    Event,
518a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN VOID         *Context
519a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
520a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
521a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_STATUS             Status;
522a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  PING6_PRIVATE_DATA     *Private;
523a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  PING6_ICMP6_TX_INFO    *TxInfo;
524a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  LIST_ENTRY             *Entry;
525a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  LIST_ENTRY             *NextEntry;
526cda10fe42c95c187902a7d4e980a133e89e59da5tye  UINT64                 Time;
527a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
528a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private = (PING6_PRIVATE_DATA *) Context;
529a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
530a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
531a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Retransmit icmp6 echo request packets per second in sendnumber times.
532a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
533a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (Private->TxCount < Private->SendNum) {
534a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
535a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Status = Ping6SendEchoRequest (Private);
536a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (Private->TxCount != 0){
537a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      if (EFI_ERROR (Status)) {
538a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_SEND_REQUEST), mHiiHandle, Private->TxCount + 1);
539a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
540a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
541a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
542a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
543a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Check whether any icmp6 echo request in the list timeout.
544a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
545a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
546a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link);
547a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Time   = Ping6CalculateTick (TxInfo->TimeStamp, ReadTime ());
548a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
549a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
550a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    // Remove the timeout echo request from txlist.
551a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
552a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (Time > PING6_DEFAULT_TIMEOUT) {
553a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
554a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      if (EFI_ERROR (TxInfo->Token->Status)) {
555a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        Private->Ip6->Cancel (Private->Ip6, TxInfo->Token);
556a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
557a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      //
558a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      // Remove the timeout icmp6 echo request from list.
559a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      //
560a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_TIMEOUT), mHiiHandle, TxInfo->SequenceNum);
561a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
562a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      RemoveEntryList (&TxInfo->Link);
563a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Ping6DestroyTxInfo (TxInfo);
564a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
565a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) {
566a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        //
567a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        // All the left icmp6 echo request in the list timeout.
568a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        //
569a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        Private->Status = EFI_TIMEOUT;
570a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
571a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
572a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
573a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
574a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
575a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
576a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Create a valid IP6 instance.
577a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
578a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Private    The pointer of PING6_PRIVATE_DATA.
579a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
580a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_SUCCESS              Create a valid IP6 instance successfully.
581a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_ABORTED              Locate handle with ip6 service binding protocol unsuccessfully.
582a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_INVALID_PARAMETER    The source address is unspecified when the destination address is a link -ocal address.
583a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_OUT_OF_RESOURCES     No memory is available on the platform.
584a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_NOT_FOUND            The source address is not found.
585a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
586a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFI_STATUS
587a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianPing6CreateIp6Instance (
588a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN  PING6_PRIVATE_DATA    *Private
589a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
590a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
591a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_STATUS                       Status;
592a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  UINTN                            HandleIndex;
593a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  UINTN                            HandleNum;
594a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_HANDLE                       *HandleBuffer;
595a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_SERVICE_BINDING_PROTOCOL     *Ip6Sb;
596a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_IP6_CONFIG_PROTOCOL          *Ip6Cfg;
597a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_IP6_CONFIG_DATA              Ip6Config;
598a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_IP6_CONFIG_INTERFACE_INFO    *IfInfo;
599a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  UINTN                            IfInfoSize;
600a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_IPv6_ADDRESS                 *Addr;
601a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  UINTN                            AddrIndex;
602a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
603a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  HandleBuffer = NULL;
604a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Ip6Sb        = NULL;
605a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IfInfo       = NULL;
606a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IfInfoSize   = 0;
607a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
608a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
609a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Locate all the handles with ip6 service binding protocol.
610a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
611a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = gBS->LocateHandleBuffer (
612a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  ByProtocol,
613a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  &gEfiIp6ServiceBindingProtocolGuid,
614a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  NULL,
615a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  &HandleNum,
616a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  &HandleBuffer
617a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  );
618a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status) || (HandleNum == 0)) {
619a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    return EFI_ABORTED;
620a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
621a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
622a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Source address is required when pinging a link-local address on multi-
623a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // interfaces host.
624a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
625a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (NetIp6IsLinkLocalAddr (&Private->DstAddress) &&
626a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      NetIp6IsUnspecifiedAddr (&Private->SrcAddress) &&
627a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      (HandleNum > 1)) {
628a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SOURCE), mHiiHandle);
629a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Status = EFI_INVALID_PARAMETER;
630a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_ERROR;
631a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
632a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
633a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // For each ip6 protocol, check interface addresses list.
634a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
635a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
636a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
637a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Ip6Sb      = NULL;
638a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    IfInfo     = NULL;
639a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    IfInfoSize = 0;
640a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
641a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Status = gBS->HandleProtocol (
642a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                    HandleBuffer[HandleIndex],
643a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                    &gEfiIp6ServiceBindingProtocolGuid,
644a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                    (VOID **) &Ip6Sb
645a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                    );
646a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (EFI_ERROR (Status)) {
647a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      goto ON_ERROR;
648a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
649a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
650a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (NetIp6IsUnspecifiedAddr (&Private->SrcAddress)) {
651a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      //
652a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      // No need to match interface address.
653a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      //
654a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      break;
655a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    } else {
656a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      //
657a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      // Ip6config protocol and ip6 service binding protocol are installed
658a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      // on the same handle.
659a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      //
660a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Status = gBS->HandleProtocol (
661a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                      HandleBuffer[HandleIndex],
662a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                      &gEfiIp6ConfigProtocolGuid,
663a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                      (VOID **) &Ip6Cfg
664a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                      );
665a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
666a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      if (EFI_ERROR (Status)) {
667a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        goto ON_ERROR;
668a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
669a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      //
670a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      // Get the interface information size.
671a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      //
672a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Status = Ip6Cfg->GetData (
673a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                         Ip6Cfg,
674a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                         Ip6ConfigDataTypeInterfaceInfo,
675a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                         &IfInfoSize,
676a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                         NULL
677a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                         );
678a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
679a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      if (Status != EFI_BUFFER_TOO_SMALL) {
680a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), mHiiHandle, Status);
681a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        goto ON_ERROR;
682a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
683a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
684a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      IfInfo = AllocateZeroPool (IfInfoSize);
685a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
686a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      if (IfInfo == NULL) {
687a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        Status = EFI_OUT_OF_RESOURCES;
688a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        goto ON_ERROR;
689a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
690a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      //
691a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      // Get the interface info.
692a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      //
693a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Status = Ip6Cfg->GetData (
694a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                         Ip6Cfg,
695a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                         Ip6ConfigDataTypeInterfaceInfo,
696a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                         &IfInfoSize,
697a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                         IfInfo
698a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                         );
699a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
700a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      if (EFI_ERROR (Status)) {
701a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), mHiiHandle, Status);
702a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        goto ON_ERROR;
703a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
704a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      //
705a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      // Check whether the source address is one of the interface addresses.
706a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      //
707a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      for (AddrIndex = 0; AddrIndex < IfInfo->AddressInfoCount; AddrIndex++) {
708a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
709a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        Addr = &(IfInfo->AddressInfo[AddrIndex].Address);
710a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {
711a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian          //
712a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian          // Match a certain interface address.
713a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian          //
714a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian          break;
715a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        }
716a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
717a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
718a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      if (AddrIndex < IfInfo->AddressInfoCount) {
719a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        //
720a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        // Found a nic handle with right interface address.
721a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        //
722a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        break;
723a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
724a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
725a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
726a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    FreePool (IfInfo);
727a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    IfInfo = NULL;
728a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
729a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
730a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // No exact interface address matched.
731a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
732a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
733a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (HandleIndex == HandleNum) {
734a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_SOURCE_NOT_FOUND), mHiiHandle, mIp6SrcString);
735a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Status = EFI_NOT_FOUND;
736a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_ERROR;
737a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
738a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
739a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private->NicHandle = HandleBuffer[HandleIndex];
740a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
741a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ASSERT (Ip6Sb != NULL);
742a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = Ip6Sb->CreateChild (Ip6Sb, &Private->Ip6ChildHandle);
743a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
744a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status)) {
745a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_ERROR;
746a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
747a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
748a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = gBS->OpenProtocol (
749a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  Private->Ip6ChildHandle,
750a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  &gEfiIp6ProtocolGuid,
751a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  (VOID **) &Private->Ip6,
752a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  Private->ImageHandle,
753a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  Private->Ip6ChildHandle,
754a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
755a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  );
756a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status)) {
757a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_ERROR;
758a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
759a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
760a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ZeroMem (&Ip6Config, sizeof (EFI_IP6_CONFIG_DATA));
761a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
762a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
763a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Configure the ip6 instance for icmp6 packet exchange.
764a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
765a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Ip6Config.DefaultProtocol   = 58;
766a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Ip6Config.AcceptAnyProtocol = FALSE;
767a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Ip6Config.AcceptIcmpErrors  = TRUE;
768a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Ip6Config.AcceptPromiscuous = FALSE;
769a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Ip6Config.TrafficClass      = 0;
770a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Ip6Config.HopLimit          = 128;
771a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Ip6Config.FlowLabel         = 0;
772a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Ip6Config.ReceiveTimeout    = 0;
773a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Ip6Config.TransmitTimeout   = 0;
774a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
775a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IP6_COPY_ADDRESS (&Ip6Config.StationAddress, &Private->SrcAddress);
776a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
777a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IP6_COPY_ADDRESS (&Ip6Config.DestinationAddress, &Private->DstAddress);
778a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
779a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = Private->Ip6->Configure (Private->Ip6, &Ip6Config);
780a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
781a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status)) {
782a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6_CONFIG), mHiiHandle, Status);
783a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_ERROR;
784a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
785a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
786a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  return EFI_SUCCESS;
787a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
788a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianON_ERROR:
789a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (HandleBuffer != NULL) {
790a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    FreePool (HandleBuffer);
791a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
792a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
793a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (IfInfo != NULL) {
794a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    FreePool (IfInfo);
795a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
796a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
797a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if ((Ip6Sb != NULL) && (Private->Ip6ChildHandle != NULL)) {
798a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Ip6Sb->DestroyChild (Ip6Sb, Private->Ip6ChildHandle);
799a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
800a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
801a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  return Status;
802a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
803a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
804a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
80575dce340624dba5e4a79b2e5b2dbe943bae0d0e9sfu  Destroy the IP6 instance.
806a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
807a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]    Private    The pointer of PING6_PRIVATE_DATA.
808a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
809a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
810a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianVOID
81175dce340624dba5e4a79b2e5b2dbe943bae0d0e9sfuPing6DestroyIp6Instance (
812a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN PING6_PRIVATE_DATA    *Private
813a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
814a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
815a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_STATUS                      Status;
816a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_SERVICE_BINDING_PROTOCOL    *Ip6Sb;
817a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
818a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  gBS->CloseProtocol (
819a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian         Private->Ip6ChildHandle,
820a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian         &gEfiIp6ProtocolGuid,
821a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian         Private->ImageHandle,
822a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian         Private->Ip6ChildHandle
823a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian         );
824a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
825a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = gBS->HandleProtocol (
826a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  Private->NicHandle,
827a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  &gEfiIp6ServiceBindingProtocolGuid,
828a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  (VOID **) &Ip6Sb
829a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  );
830a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
831a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (!EFI_ERROR(Status)) {
832a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Ip6Sb->DestroyChild (Ip6Sb, Private->Ip6ChildHandle);
833a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
834a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
835a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
836a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
837a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  The Ping6 Process.
838a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
839a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]   ImageHandle    The firmware allocated handle for the UEFI image.
840a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]   SendNumber     The send request count.
841a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]   BufferSize     The send buffer size.
842a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]   SrcAddress     The source IPv6 address.
843a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in]   DstAddress     The destination IPv6 address.
844a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
845a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_SUCCESS    The ping6 processed successfullly.
846a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval others         The ping6 processed unsuccessfully.
847a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
848a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
849a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFI_STATUS
850a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianPing6 (
851a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN EFI_HANDLE          ImageHandle,
852a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN UINT32              SendNumber,
853a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN UINT32              BufferSize,
854a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN EFI_IPv6_ADDRESS    *SrcAddress,
855a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN EFI_IPv6_ADDRESS    *DstAddress
856a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
857a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
858a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_STATUS             Status;
859a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_INPUT_KEY          Key;
860a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  PING6_PRIVATE_DATA     *Private;
861a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  PING6_ICMP6_TX_INFO    *TxInfo;
862a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  LIST_ENTRY             *Entry;
863a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  LIST_ENTRY             *NextEntry;
864a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
865a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private = AllocateZeroPool (sizeof (PING6_PRIVATE_DATA));
866a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
867a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ASSERT (Private != NULL);
868a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
869a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private->ImageHandle = ImageHandle;
870a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private->SendNum     = SendNumber;
871a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private->BufferSize  = BufferSize;
872cda10fe42c95c187902a7d4e980a133e89e59da5tye  Private->RttMin      = ~((UINT64 )(0x0));
873a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Private->Status      = EFI_NOT_READY;
874a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
875a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  InitializeListHead (&Private->TxList);
876a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
877a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IP6_COPY_ADDRESS (&Private->SrcAddress, SrcAddress);
878a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IP6_COPY_ADDRESS (&Private->DstAddress, DstAddress);
879a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
880a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
881a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Open and configure a ip6 instance for ping6.
882a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
883a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = Ping6CreateIp6Instance (Private);
884a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
885a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status)) {
886a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
887a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
888a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
889a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Print the command line itself.
890a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
891a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_START), mHiiHandle, mIp6DstString, Private->BufferSize);
892a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
893a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Create a ipv6 token to receive the first icmp6 echo reply packet.
894a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
895a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = Ping6ReceiveEchoReply (Private);
896a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
897a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status)) {
898a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
899a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
900a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
901a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Create and start timer to send icmp6 echo request packet per second.
902a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
903a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = gBS->CreateEvent (
904a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
905a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  TPL_CALLBACK,
906a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  Ping6OnTimerRoutine,
907a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  Private,
908a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  &Private->Timer
909a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  );
910a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
911a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status)) {
912a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
913a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
914a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
915a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Create a ipv6 token to send the first icmp6 echo request packet.
916a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
917a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = Ping6SendEchoRequest (Private);
918a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
919a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // EFI_NOT_READY for IPsec is enable and IKE is not established.
920a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
921a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
922a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if(Status == EFI_NOT_FOUND) {
923a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_NOSOURCE_INDOMAIN), mHiiHandle, mIp6DstString);
924a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
925a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
926a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
927a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
928a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
929a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = gBS->SetTimer (
930a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  Private->Timer,
931a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  TimerPeriodic,
932a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  PING6_ONE_SECOND
933a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian                  );
934a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
935a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR (Status)) {
936a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
937a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
938a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
939a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Control the ping6 process by two factors:
940a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // 1. Hot key
941a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // 2. Private->Status
942a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //   2.1. success means all icmp6 echo request packets get reply packets.
943a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //   2.2. timeout means the last icmp6 echo reply request timeout to get reply.
944a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //   2.3. noready means ping6 process is on-the-go.
945a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
946a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  while (Private->Status == EFI_NOT_READY) {
947a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Private->Ip6->Poll (Private->Ip6);
948a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
949a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
950a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    // Terminate the ping6 process by 'esc' or 'ctl-c'.
951a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
952a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
953a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
954a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (!EFI_ERROR(Status)) {
955a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      if ((Key.UnicodeChar == 0x1b) || (Key.UnicodeChar == 0x03) ||
956a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian         ((Key.UnicodeChar == 0) && (Key.ScanCode == SCAN_ESC))) {
957a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian        goto ON_STAT;
958a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      }
959a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
960a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
961a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
962a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianON_STAT:
963a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
964a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Display the statistics in all.
965a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
966a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  gBS->SetTimer (Private->Timer, TimerCancel, 0);
967a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
968a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (Private->TxCount != 0) {
969a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    ShellPrintHiiEx (
970a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      -1,
971a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      -1,
972a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      NULL,
973a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      STRING_TOKEN (STR_PING6_STAT),
974a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      mHiiHandle,
975a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Private->TxCount,
976a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Private->RxCount,
977a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      (100 * (Private->TxCount - Private->RxCount)) / Private->TxCount,
978a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Private->RttSum
979a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      );
980a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
981a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
982a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (Private->RxCount != 0) {
983a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    ShellPrintHiiEx (
984a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      -1,
985a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      -1,
986a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      NULL,
987a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      STRING_TOKEN (STR_PING6_RTT),
988a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      mHiiHandle,
989a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Private->RttMin,
990a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Private->RttMax,
991cda10fe42c95c187902a7d4e980a133e89e59da5tye      DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL)
992a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      );
993a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
994a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
995a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianON_EXIT:
996a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
997a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (Private != NULL) {
998a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Private->Status = EFI_ABORTED;
999a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1000a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
1001a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link);
1002a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1003a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Status = Private->Ip6->Cancel (Private->Ip6, TxInfo->Token);
1004a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1005a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      RemoveEntryList (&TxInfo->Link);
1006a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Ping6DestroyTxInfo (TxInfo);
1007a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
1008a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1009a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (Private->Timer != NULL) {
1010a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      gBS->CloseEvent (Private->Timer);
1011a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
1012a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1013a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (Private->Ip6 != NULL) {
1014a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Status = Private->Ip6->Cancel (Private->Ip6, &Private->RxToken);
1015a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
1016a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1017a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (Private->RxToken.Event != NULL) {
1018a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      gBS->CloseEvent (Private->RxToken.Event);
1019a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
1020a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1021a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (Private->Ip6ChildHandle != NULL) {
102275dce340624dba5e4a79b2e5b2dbe943bae0d0e9sfu      Ping6DestroyIp6Instance (Private);
1023a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
1024a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1025a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    FreePool (Private);
1026a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
1027a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1028a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  return Status;
1029a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
1030a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1031a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian/**
1032a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  This is the declaration of an EFI image entry point. This entry point is
1033a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
1034a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  both device drivers and bus drivers.
1035a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1036a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  The entry point for the Ping6 application that parses the command line input and calls the Ping6 process.
1037a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1038a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in] ImageHandle    The firmware allocated handle for the UEFI image.
1039a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @param[in] SystemTable    A pointer to the EFI System Table.
1040a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1041a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_SUCCESS               The operation completed successfully.
1042a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval EFI_INVALID_PARAMETETR    Input parameters combination is invalid.
1043a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  @retval Others                    Some errors occur.
1044a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1045a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian**/
1046a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFI_STATUS
1047a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianEFIAPI
1048a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianInitializePing6 (
1049a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN  EFI_HANDLE          ImageHandle,
1050a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  IN  EFI_SYSTEM_TABLE    *SystemTable
1051a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  )
1052a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian{
1053a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_STATUS          Status;
1054a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_IPv6_ADDRESS    DstAddress;
1055a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  EFI_IPv6_ADDRESS    SrcAddress;
1056a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  UINT64              BufferSize;
1057a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  UINTN               SendNumber;
1058a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  LIST_ENTRY          *ParamPackage;
1059a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  CONST CHAR16        *ValueStr;
1060a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  CONST CHAR16        *ValueStrPtr;
1061a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  UINTN               NonOptionCount;
1062a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1063a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1064a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Register our string package with HII and return the handle to it.
1065a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1066a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, Ping6Strings, NULL);
1067a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ASSERT (mHiiHandle != NULL);
1068a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1069a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = ShellCommandLineParseEx (Ping6ParamList, &ParamPackage, NULL, TRUE, FALSE);
1070a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR(Status)) {
1071a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_INPUT), mHiiHandle);
1072a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
1073a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
1074a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1075a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (ShellCommandLineGetFlag (ParamPackage, L"-?")) {
1076a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_HELP), mHiiHandle);
1077a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
1078a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
1079a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1080a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  SendNumber = 10;
1081a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  BufferSize = 16;
1082a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1083a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1084a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Parse the paramter of count number.
1085a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1086a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n");
1087a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ValueStrPtr = ValueStr;
1088a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (ValueStr != NULL) {
1089a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    SendNumber = ShellStrToUintn (ValueStrPtr);
1090a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1091a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
1092a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    // ShellStrToUintn will return 0 when input is 0 or an invalid input string.
1093a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
1094a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if ((SendNumber == 0) || (SendNumber > PING6_MAX_SEND_NUMBER)) {
1095a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SEND_NUMBER), mHiiHandle, ValueStr);
1096a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Status = EFI_INVALID_PARAMETER;
1097a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      goto ON_EXIT;
1098a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
1099a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
1100a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1101a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Parse the paramter of buffer size.
1102a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1103a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
1104a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ValueStrPtr = ValueStr;
1105a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (ValueStr != NULL) {
1106a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    BufferSize = ShellStrToUintn (ValueStrPtr);
1107a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1108a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
1109a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    // ShellStrToUintn will return 0 when input is 0 or an invalid input string.
1110a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    //
1111a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if ((BufferSize < 16) || (BufferSize > PING6_MAX_BUFFER_SIZE)) {
1112a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_BUFFER_SIZE), mHiiHandle, ValueStr);
1113a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Status = EFI_INVALID_PARAMETER;
1114a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      goto ON_EXIT;
1115a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
1116a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
1117a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1118a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ZeroMem (&SrcAddress, sizeof (EFI_IPv6_ADDRESS));
1119a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS));
1120a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1121a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1122a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Parse the paramter of source ip address.
1123a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1124a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
1125a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ValueStrPtr = ValueStr;
1126a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (ValueStr != NULL) {
1127a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    mIp6SrcString = ValueStr;
1128a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Status = NetLibStrToIp6 (ValueStrPtr, &SrcAddress);
1129a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (EFI_ERROR (Status)) {
1130a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_IP), mHiiHandle, ValueStr);
1131a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Status = EFI_INVALID_PARAMETER;
1132a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      goto ON_EXIT;
1133a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
1134a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
1135a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1136a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Parse the paramter of destination ip address.
1137a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1138780847d1287b1d70555570a4cdbcfa5da65d53b1xdu  NonOptionCount = ShellCommandLineGetCount(ParamPackage);
1139a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ValueStr = ShellCommandLineGetRawValue (ParamPackage, (UINT32)(NonOptionCount-1));
1140a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (NonOptionCount != 2) {
1141a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_INPUT), mHiiHandle);
1142a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Status = EFI_INVALID_PARAMETER;
1143a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
1144a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
1145a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ValueStrPtr = ValueStr;
1146a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (ValueStr != NULL) {
1147a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    mIp6DstString = ValueStr;
1148a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    Status = NetLibStrToIp6 (ValueStrPtr, &DstAddress);
1149a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    if (EFI_ERROR (Status)) {
1150a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_IP), mHiiHandle, ValueStr);
1151a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      Status = EFI_INVALID_PARAMETER;
1152a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian      goto ON_EXIT;
1153a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    }
1154a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
1155a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1156a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Get frequency to calculate the time from ticks.
1157a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1158a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = Ping6GetFrequency ();
1159a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1160a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  if (EFI_ERROR(Status)) {
1161a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian    goto ON_EXIT;
1162a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  }
1163a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1164a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  // Enter into ping6 process.
1165a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  //
1166a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  Status = Ping6 (
1167a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian             ImageHandle,
1168a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian             (UINT32)SendNumber,
1169a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian             (UINT32)BufferSize,
1170a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian             &SrcAddress,
1171a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian             &DstAddress
1172a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian             );
1173a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian
1174a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtianON_EXIT:
1175a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  ShellCommandLineFreeVarList (ParamPackage);
1176a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  HiiRemovePackages (mHiiHandle);
1177a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian  return Status;
1178a3bcde70e6dc69000f85cc5deee98101d2ae200ahhtian}
1179