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