DxeIpIoLib.c revision e798cd87ca9a3a30c4cea50c5f5de84e10a8bc5a
1cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/** @file
26aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IpIo Library.
3cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
4fb115c61504fe6c4f94be0a87f75e28e1684657ftyeCopyright (c) 2005 - 2009, Intel Corporation.<BR>
5cbf316f20726bb31b7c37424601643790dbd02d9vanjeffAll rights reserved. This program and the accompanying materials
6cbf316f20726bb31b7c37424601643790dbd02d9vanjeffare licensed and made available under the terms and conditions of the BSD License
7cbf316f20726bb31b7c37424601643790dbd02d9vanjeffwhich accompanies this distribution.  The full text of the license may be found at
8cbf316f20726bb31b7c37424601643790dbd02d9vanjeffhttp://opensource.org/licenses/bsd-license.php
9cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
10cbf316f20726bb31b7c37424601643790dbd02d9vanjeffTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11cbf316f20726bb31b7c37424601643790dbd02d9vanjeffWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
13cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
146aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu#include <Uefi.h>
15cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
16cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Protocol/Udp4.h>
17cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
18cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/IpIoLib.h>
19cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/BaseLib.h>
20cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/DebugLib.h>
21752ef5d80c099b1d33bf25f62f36289dac47d83cmdkinney#include <Library/BaseMemoryLib.h>
22cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/UefiBootServicesTableLib.h>
23752ef5d80c099b1d33bf25f62f36289dac47d83cmdkinney#include <Library/MemoryAllocationLib.h>
24d8d26fb207e02aa5ef57e2bcb213f9dda16166ccmdkinney#include <Library/DpcLib.h>
25cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
26cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
271204fe8319e5e6f77df68c375ef403e9ffa9227exduGLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY  mActiveIpIoList = {
28cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  &mActiveIpIoList,
29cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  &mActiveIpIoList
30cbf316f20726bb31b7c37424601643790dbd02d9vanjeff};
31cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
321204fe8319e5e6f77df68c375ef403e9ffa9227exduGLOBAL_REMOVE_IF_UNREFERENCED EFI_IP4_CONFIG_DATA  mIp4IoDefaultIpConfigData = {
33cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP_PROTO_UDP,
34cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
35cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TRUE,
36cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
37cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
38cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
3984b5c78e89686879f799a4cd095eeef83ff7cf34qwang  {{0, 0, 0, 0}},
4084b5c78e89686879f799a4cd095eeef83ff7cf34qwang  {{0, 0, 0, 0}},
41cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0,
42cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  255,
43cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
44cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
45cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0,
46cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0
47cbf316f20726bb31b7c37424601643790dbd02d9vanjeff};
48cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
491204fe8319e5e6f77df68c375ef403e9ffa9227exduGLOBAL_REMOVE_IF_UNREFERENCED EFI_IP6_CONFIG_DATA  mIp6IoDefaultIpConfigData = {
50fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_IP_PROTO_UDP,
51fb115c61504fe6c4f94be0a87f75e28e1684657ftye  FALSE,
52fb115c61504fe6c4f94be0a87f75e28e1684657ftye  TRUE,
53fb115c61504fe6c4f94be0a87f75e28e1684657ftye  FALSE,
54fb115c61504fe6c4f94be0a87f75e28e1684657ftye  {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
55fb115c61504fe6c4f94be0a87f75e28e1684657ftye  {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
56fb115c61504fe6c4f94be0a87f75e28e1684657ftye  0,
57fb115c61504fe6c4f94be0a87f75e28e1684657ftye  255,
58fb115c61504fe6c4f94be0a87f75e28e1684657ftye  0,
59fb115c61504fe6c4f94be0a87f75e28e1684657ftye  0,
60fb115c61504fe6c4f94be0a87f75e28e1684657ftye  0
61fb115c61504fe6c4f94be0a87f75e28e1684657ftye};
62fb115c61504fe6c4f94be0a87f75e28e1684657ftye
631204fe8319e5e6f77df68c375ef403e9ffa9227exduGLOBAL_REMOVE_IF_UNREFERENCED ICMP_ERROR_INFO  mIcmpErrMap[10] = {
643cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE }, // ICMP_ERR_UNREACH_NET
653cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE }, // ICMP_ERR_UNREACH_HOST
663cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {TRUE,  TRUE }, // ICMP_ERR_UNREACH_PROTOCOL
673cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {TRUE,  TRUE }, // ICMP_ERR_UNREACH_PORT
683cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {TRUE,  TRUE }, // ICMP_ERR_MSGSIZE
693cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE }, // ICMP_ERR_UNREACH_SRCFAIL
703cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE }, // ICMP_ERR_TIMXCEED_INTRANS
713cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE }, // ICMP_ERR_TIMEXCEED_REASS
723cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, FALSE}, // ICMP_ERR_QUENCH
733cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE }  // ICMP_ERR_PARAMPROB
74fb115c61504fe6c4f94be0a87f75e28e1684657ftye};
75fb115c61504fe6c4f94be0a87f75e28e1684657ftye
761204fe8319e5e6f77df68c375ef403e9ffa9227exduGLOBAL_REMOVE_IF_UNREFERENCED ICMP_ERROR_INFO  mIcmp6ErrMap[10] = {
773cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}, // ICMP6_ERR_UNREACH_NET
783cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}, // ICMP6_ERR_UNREACH_HOST
793cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {TRUE,  TRUE}, // ICMP6_ERR_UNREACH_PROTOCOL
803cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {TRUE,  TRUE}, // ICMP6_ERR_UNREACH_PORT
813cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {TRUE,  TRUE}, // ICMP6_ERR_PACKAGE_TOOBIG
823cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}, // ICMP6_ERR_TIMXCEED_HOPLIMIT
833cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}, // ICMP6_ERR_TIMXCEED_REASS
843cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}, // ICMP6_ERR_PARAMPROB_HEADER
853cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}, // ICMP6_ERR_PARAMPROB_NEXHEADER
863cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}  // ICMP6_ERR_PARAMPROB_IPV6OPTION
8701750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff};
8801750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff
896aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
906aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu/**
916aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  Notify function for IP transmit token.
926aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
936aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
946aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
956aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu**/
96cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
97cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
9836ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoTransmitHandlerDpc (
9936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
10036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  );
10136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
1026aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
1036aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu/**
1046aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  Notify function for IP transmit token.
1056aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
1066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event signaled.
1076aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
1086aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
1096aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu**/
11036ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
11136ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
112cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoTransmitHandler (
113cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_EVENT Event,
114cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
115cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  );
116cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
117cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
118cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1196aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  This function create an IP child ,open the IP protocol, and return the opened
120e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IP protocol as Interface.
121cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1226aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]    ControllerHandle   The controller handle.
1236aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]    ImageHandle        The image handle.
1246aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]    ChildHandle        Pointer to the buffer to save the IP child handle.
125fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]    IpVersion          The version of the IP protocol to use, either
126fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                   IPv4 or IPv6.
1276aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[out]   Interface          Pointer used to get the IP protocol interface.
128cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1296aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval       EFI_SUCCESS        The IP child is created and the IP protocol
1306aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   interface is retrieved.
1316aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval       Others             The required operation failed.
132cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
133cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
134cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
135cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreateIpChildOpenProtocol (
136cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  ControllerHandle,
137cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  ImageHandle,
138cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  *ChildHandle,
139b45b45b2d248892930620c33a9d01d8457ae0e54tye  IN  UINT8       IpVersion,
140cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  OUT VOID        **Interface
141cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
142cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
143cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
144fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_GUID    *ServiceBindingGuid;
145fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_GUID    *IpProtocolGuid;
146fb115c61504fe6c4f94be0a87f75e28e1684657ftye
147fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4) {
148fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;
149fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpProtocolGuid     = &gEfiIp4ProtocolGuid;
150fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (IpVersion == IP_VERSION_6){
151fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;
152fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpProtocolGuid     = &gEfiIp6ProtocolGuid;
153fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
154fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return EFI_UNSUPPORTED;
155fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
156cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
157cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1586aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Create an IP child.
159cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
160cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = NetLibCreateServiceChild (
161cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ControllerHandle,
162cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ImageHandle,
163fb115c61504fe6c4f94be0a87f75e28e1684657ftye             ServiceBindingGuid,
164cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ChildHandle
165cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
166cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
167cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
168cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
169cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
170cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1716aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Open the IP protocol installed on the *ChildHandle.
172cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
173cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->OpenProtocol (
174cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  *ChildHandle,
175fb115c61504fe6c4f94be0a87f75e28e1684657ftye                  IpProtocolGuid,
176cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  Interface,
177cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  ImageHandle,
178cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  ControllerHandle,
179cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EFI_OPEN_PROTOCOL_BY_DRIVER
180cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
181cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
182cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1836aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // On failure, destroy the IP child.
184cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
185cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    NetLibDestroyServiceChild (
186cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      ControllerHandle,
187cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      ImageHandle,
188fb115c61504fe6c4f94be0a87f75e28e1684657ftye      ServiceBindingGuid,
189cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      *ChildHandle
190cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      );
191cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
192cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
193cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
194cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
195cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
196cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
197cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
198e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function close the previously openned IP protocol and destroy the IP child.
199cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2006aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  ControllerHandle    The controller handle.
2016aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  ImageHandle         The image handle.
2026aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  ChildHandle         The child handle of the IP child.
203fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]  IpVersion           The version of the IP protocol to use, either
204fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                  IPv4 or IPv6.
205cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval     EFI_SUCCESS         The IP protocol is closed and the relevant IP child
2076aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                  is destroyed.
2086aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval     Others              The required operation failed.
209cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
210cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
211cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
212cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCloseProtocolDestroyIpChild (
213cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ControllerHandle,
214cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ImageHandle,
215fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN EFI_HANDLE  ChildHandle,
216b45b45b2d248892930620c33a9d01d8457ae0e54tye  IN UINT8       IpVersion
217cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
218cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
219cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
220fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_GUID    *ServiceBindingGuid;
221fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_GUID    *IpProtocolGuid;
222fb115c61504fe6c4f94be0a87f75e28e1684657ftye
223fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4) {
224fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;
225fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpProtocolGuid     = &gEfiIp4ProtocolGuid;
226fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (IpVersion == IP_VERSION_6) {
227fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;
228fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpProtocolGuid     = &gEfiIp6ProtocolGuid;
229fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
230fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return EFI_UNSUPPORTED;
231fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
232cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
233cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
2346aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Close the previously openned IP protocol.
235cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
236cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseProtocol (
237cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ChildHandle,
238fb115c61504fe6c4f94be0a87f75e28e1684657ftye         IpProtocolGuid,
239cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ImageHandle,
240cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ControllerHandle
241cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         );
242cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
243cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
2446aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Destroy the IP child.
245cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
246cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = NetLibDestroyServiceChild (
247cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ControllerHandle,
248cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ImageHandle,
249fb115c61504fe6c4f94be0a87f75e28e1684657ftye             ServiceBindingGuid,
250cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ChildHandle
251cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
252cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
253cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
254cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
255cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
256cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
257fb115c61504fe6c4f94be0a87f75e28e1684657ftye  This function handles ICMPv4 packets. It is the worker function of
258fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpIoIcmpHandler.
259cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
260fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       IpIo            Pointer to the IP_IO instance.
261fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in, out]  Pkt             Pointer to the ICMPv4 packet.
262fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       Session         Pointer to the net session of this ICMPv4 packet.
263cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
264fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_SUCCESS     The ICMPv4 packet is handled successfully.
265fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_ABORTED     This type of ICMPv4 packet is not supported.
266cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
267cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
268cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
269fb115c61504fe6c4f94be0a87f75e28e1684657ftyeIpIoIcmpv4Handler (
2706aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO                *IpIo,
2716aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT NET_BUF              *Pkt,
2726aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     EFI_NET_SESSION_DATA *Session
273cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
274cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
275cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP4_ICMP_ERROR_HEAD  *IcmpHdr;
276cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_HEADER       *IpHdr;
277b45b45b2d248892930620c33a9d01d8457ae0e54tye  UINT8                IcmpErr;
278cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                *PayLoadHdr;
279cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                Type;
280cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                Code;
281cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT32               TrimBytes;
282cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
283fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT (IpIo->IpVersion == IP_VERSION_4);
284fb115c61504fe6c4f94be0a87f75e28e1684657ftye
285cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IcmpHdr = NET_PROTO_HDR (Pkt, IP4_ICMP_ERROR_HEAD);
286cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpHdr   = (EFI_IP4_HEADER *) (&IcmpHdr->IpHead);
287cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
288cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
289cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Check the ICMP packet length.
290cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
291cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (Pkt->TotalSize < ICMP_ERRLEN (IpHdr)) {
292cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
293cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ABORTED;
294cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
295cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
296cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Type = IcmpHdr->Head.Type;
297cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Code = IcmpHdr->Head.Code;
298cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
299cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
300cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Analyze the ICMP Error in this ICMP pkt
301cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
302cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  switch (Type) {
303cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_UNREACH:
304cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    switch (Code) {
305cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET:
306cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST:
307cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_PROTOCOL:
308cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_PORT:
309cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_SRCFAIL:
310b45b45b2d248892930620c33a9d01d8457ae0e54tye      IcmpErr = (UINT8) (ICMP_ERR_UNREACH_NET + Code);
311cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
312cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
313cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
314cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NEEDFRAG:
315cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_MSGSIZE;
316cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
317cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
318cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
319cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET_UNKNOWN:
320cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET_PROHIB:
321cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_TOSNET:
322cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_UNREACH_NET;
323cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
324cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
325cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
326cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST_UNKNOWN:
327cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_ISOLATED:
328cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST_PROHIB:
329cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_TOSHOST:
330cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_UNREACH_HOST;
331cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
332cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
333cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
334cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    default:
335cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
336cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
337cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
338cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
339cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
340cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_TIMXCEED:
341cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code > 1) {
342cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
343cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
344cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
345b45b45b2d248892930620c33a9d01d8457ae0e54tye    IcmpErr = (UINT8) (Code + ICMP_ERR_TIMXCEED_INTRANS);
346cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
347cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
348cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
349cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_PARAMPROB:
350cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code > 1) {
351cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
352cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
353cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
354cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IcmpErr = ICMP_ERR_PARAMPROB;
355cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
356cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
357cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
358cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_SOURCEQUENCH:
359cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code != 0) {
360cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
361cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
362cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
363cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IcmpErr = ICMP_ERR_QUENCH;
364cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
365cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
366cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
367cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  default:
368cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ABORTED;
369cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
370cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
371cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
372cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Notify user the ICMP pkt only containing payload except
373cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // IP and ICMP header
374cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
375cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  PayLoadHdr = (UINT8 *) ((UINT8 *) IpHdr + EFI_IP4_HEADER_LEN (IpHdr));
376cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TrimBytes  = (UINT32) (PayLoadHdr - (UINT8 *) IcmpHdr);
377cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
378cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetbufTrim (Pkt, TrimBytes, TRUE);
379cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
380cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);
381cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
382fb115c61504fe6c4f94be0a87f75e28e1684657ftye  return EFI_SUCCESS;
383fb115c61504fe6c4f94be0a87f75e28e1684657ftye}
384fb115c61504fe6c4f94be0a87f75e28e1684657ftye
385fb115c61504fe6c4f94be0a87f75e28e1684657ftye/**
386fb115c61504fe6c4f94be0a87f75e28e1684657ftye  This function handles ICMPv6 packets. It is the worker function of
387fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpIoIcmpHandler.
388fb115c61504fe6c4f94be0a87f75e28e1684657ftye
389fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       IpIo            Pointer to the IP_IO instance.
390fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in, out]  Pkt             Pointer to the ICMPv6 packet.
391fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       Session         Pointer to the net session of this ICMPv6 packet.
392fb115c61504fe6c4f94be0a87f75e28e1684657ftye
393fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_SUCCESS     The ICMPv6 packet is handled successfully.
394fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_ABORTED     This type of ICMPv6 packet is not supported.
395fb115c61504fe6c4f94be0a87f75e28e1684657ftye
396fb115c61504fe6c4f94be0a87f75e28e1684657ftye**/
397fb115c61504fe6c4f94be0a87f75e28e1684657ftyeEFI_STATUS
398fb115c61504fe6c4f94be0a87f75e28e1684657ftyeIpIoIcmpv6Handler (
399fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     IP_IO                *IpIo,
400fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN OUT NET_BUF              *Pkt,
401fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     EFI_NET_SESSION_DATA *Session
402fb115c61504fe6c4f94be0a87f75e28e1684657ftye  )
403fb115c61504fe6c4f94be0a87f75e28e1684657ftye{
404fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IP6_ICMP_ERROR_HEAD  *IcmpHdr;
405fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_IP6_HEADER       *IpHdr;
406b45b45b2d248892930620c33a9d01d8457ae0e54tye  UINT8                IcmpErr;
407fb115c61504fe6c4f94be0a87f75e28e1684657ftye  UINT8                *PayLoadHdr;
408fb115c61504fe6c4f94be0a87f75e28e1684657ftye  UINT8                Type;
409fb115c61504fe6c4f94be0a87f75e28e1684657ftye  UINT8                Code;
410fb115c61504fe6c4f94be0a87f75e28e1684657ftye  UINT8                NextHeader;
411fb115c61504fe6c4f94be0a87f75e28e1684657ftye  UINT32               TrimBytes;
412fb115c61504fe6c4f94be0a87f75e28e1684657ftye  BOOLEAN              Flag;
413fb115c61504fe6c4f94be0a87f75e28e1684657ftye
414fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT (IpIo->IpVersion == IP_VERSION_6);
415fb115c61504fe6c4f94be0a87f75e28e1684657ftye
416fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
417fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Check the ICMPv6 packet length.
418fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
419fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (Pkt->TotalSize < sizeof (IP6_ICMP_ERROR_HEAD)) {
420fb115c61504fe6c4f94be0a87f75e28e1684657ftye
421fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return EFI_ABORTED;
422fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
423fb115c61504fe6c4f94be0a87f75e28e1684657ftye
424fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IcmpHdr = NET_PROTO_HDR (Pkt, IP6_ICMP_ERROR_HEAD);
425fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Type    = IcmpHdr->Head.Type;
426fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Code    = IcmpHdr->Head.Code;
427fb115c61504fe6c4f94be0a87f75e28e1684657ftye
428fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
429fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Analyze the ICMPv6 Error in this ICMPv6 packet
430fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
431fb115c61504fe6c4f94be0a87f75e28e1684657ftye  switch (Type) {
432fb115c61504fe6c4f94be0a87f75e28e1684657ftye  case ICMP_V6_DEST_UNREACHABLE:
433fb115c61504fe6c4f94be0a87f75e28e1684657ftye    switch (Code) {
434fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_NO_ROUTE_TO_DEST:
435fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_BEYOND_SCOPE:
436fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_ROUTE_REJECTED:
437fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IcmpErr = ICMP6_ERR_UNREACH_NET;
438fb115c61504fe6c4f94be0a87f75e28e1684657ftye
439fb115c61504fe6c4f94be0a87f75e28e1684657ftye      break;
440fb115c61504fe6c4f94be0a87f75e28e1684657ftye
441fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_COMM_PROHIBITED:
442fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_ADDR_UNREACHABLE:
443fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_SOURCE_ADDR_FAILED:
444fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IcmpErr = ICMP6_ERR_UNREACH_HOST;
445fb115c61504fe6c4f94be0a87f75e28e1684657ftye
446fb115c61504fe6c4f94be0a87f75e28e1684657ftye      break;
447fb115c61504fe6c4f94be0a87f75e28e1684657ftye
448fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_PORT_UNREACHABLE:
449fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IcmpErr = ICMP6_ERR_UNREACH_PORT;
450fb115c61504fe6c4f94be0a87f75e28e1684657ftye
451fb115c61504fe6c4f94be0a87f75e28e1684657ftye      break;
452fb115c61504fe6c4f94be0a87f75e28e1684657ftye
453fb115c61504fe6c4f94be0a87f75e28e1684657ftye     default:
454fb115c61504fe6c4f94be0a87f75e28e1684657ftye      return EFI_ABORTED;
455fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
456fb115c61504fe6c4f94be0a87f75e28e1684657ftye
457fb115c61504fe6c4f94be0a87f75e28e1684657ftye    break;
458fb115c61504fe6c4f94be0a87f75e28e1684657ftye
459fb115c61504fe6c4f94be0a87f75e28e1684657ftye  case ICMP_V6_PACKET_TOO_BIG:
460fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (Code >= 1) {
461fb115c61504fe6c4f94be0a87f75e28e1684657ftye      return EFI_ABORTED;
462fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
463fb115c61504fe6c4f94be0a87f75e28e1684657ftye
464fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IcmpErr = ICMP6_ERR_PACKAGE_TOOBIG;
465fb115c61504fe6c4f94be0a87f75e28e1684657ftye
466fb115c61504fe6c4f94be0a87f75e28e1684657ftye    break;
467fb115c61504fe6c4f94be0a87f75e28e1684657ftye
468fb115c61504fe6c4f94be0a87f75e28e1684657ftye  case ICMP_V6_TIME_EXCEEDED:
469fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (Code > 1) {
470fb115c61504fe6c4f94be0a87f75e28e1684657ftye      return EFI_ABORTED;
471fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
472fb115c61504fe6c4f94be0a87f75e28e1684657ftye
473b45b45b2d248892930620c33a9d01d8457ae0e54tye    IcmpErr = (UINT8) (ICMP6_ERR_TIMXCEED_HOPLIMIT + Code);
474fb115c61504fe6c4f94be0a87f75e28e1684657ftye
475fb115c61504fe6c4f94be0a87f75e28e1684657ftye    break;
476fb115c61504fe6c4f94be0a87f75e28e1684657ftye
477fb115c61504fe6c4f94be0a87f75e28e1684657ftye  case ICMP_V6_PARAMETER_PROBLEM:
478fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (Code > 3) {
479fb115c61504fe6c4f94be0a87f75e28e1684657ftye      return EFI_ABORTED;
480fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
481fb115c61504fe6c4f94be0a87f75e28e1684657ftye
482b45b45b2d248892930620c33a9d01d8457ae0e54tye    IcmpErr = (UINT8) (ICMP6_ERR_PARAMPROB_HEADER + Code);
483fb115c61504fe6c4f94be0a87f75e28e1684657ftye
484fb115c61504fe6c4f94be0a87f75e28e1684657ftye    break;
485fb115c61504fe6c4f94be0a87f75e28e1684657ftye
486fb115c61504fe6c4f94be0a87f75e28e1684657ftye   default:
487fb115c61504fe6c4f94be0a87f75e28e1684657ftye
488fb115c61504fe6c4f94be0a87f75e28e1684657ftye     return EFI_ABORTED;
489fb115c61504fe6c4f94be0a87f75e28e1684657ftye   }
490fb115c61504fe6c4f94be0a87f75e28e1684657ftye
491fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
492fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Notify user the ICMPv6 packet only containing payload except
493fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // IPv6 basic header, extension header and ICMP header
494fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
495fb115c61504fe6c4f94be0a87f75e28e1684657ftye
496fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpHdr      = (EFI_IP6_HEADER *) (&IcmpHdr->IpHead);
497fb115c61504fe6c4f94be0a87f75e28e1684657ftye  NextHeader = IpHdr->NextHeader;
498fb115c61504fe6c4f94be0a87f75e28e1684657ftye  PayLoadHdr = (UINT8 *) ((UINT8 *) IcmpHdr + sizeof (IP6_ICMP_ERROR_HEAD));
499fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Flag       = TRUE;
500fb115c61504fe6c4f94be0a87f75e28e1684657ftye
501fb115c61504fe6c4f94be0a87f75e28e1684657ftye  do {
502fb115c61504fe6c4f94be0a87f75e28e1684657ftye    switch (NextHeader) {
503fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case EFI_IP_PROTO_UDP:
504fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case EFI_IP_PROTO_TCP:
505fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case EFI_IP_PROTO_ICMP:
506fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case IP6_NO_NEXT_HEADER:
507fb115c61504fe6c4f94be0a87f75e28e1684657ftye      Flag = FALSE;
508fb115c61504fe6c4f94be0a87f75e28e1684657ftye
509fb115c61504fe6c4f94be0a87f75e28e1684657ftye      break;
510fb115c61504fe6c4f94be0a87f75e28e1684657ftye
511fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case IP6_HOP_BY_HOP:
512fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case IP6_DESTINATION:
513fb115c61504fe6c4f94be0a87f75e28e1684657ftye      //
514fb115c61504fe6c4f94be0a87f75e28e1684657ftye      // The Hdr Ext Len is 8-bit unsigned integer in 8-octet units, not including
515fb115c61504fe6c4f94be0a87f75e28e1684657ftye      // the first 8 octets.
516fb115c61504fe6c4f94be0a87f75e28e1684657ftye      //
517fb115c61504fe6c4f94be0a87f75e28e1684657ftye      NextHeader = *(PayLoadHdr);
518fb115c61504fe6c4f94be0a87f75e28e1684657ftye      PayLoadHdr = (UINT8 *) (PayLoadHdr + (*(PayLoadHdr + 1) + 1) * 8);
519fb115c61504fe6c4f94be0a87f75e28e1684657ftye
520fb115c61504fe6c4f94be0a87f75e28e1684657ftye      break;
521fb115c61504fe6c4f94be0a87f75e28e1684657ftye
522fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case IP6_FRAGMENT:
523fb115c61504fe6c4f94be0a87f75e28e1684657ftye      //
524fb115c61504fe6c4f94be0a87f75e28e1684657ftye      // The Fragment Header Length is 8 octets.
525fb115c61504fe6c4f94be0a87f75e28e1684657ftye      //
526fb115c61504fe6c4f94be0a87f75e28e1684657ftye      NextHeader = *(PayLoadHdr);
527fb115c61504fe6c4f94be0a87f75e28e1684657ftye      PayLoadHdr = (UINT8 *) (PayLoadHdr + 8);
528fb115c61504fe6c4f94be0a87f75e28e1684657ftye
529fb115c61504fe6c4f94be0a87f75e28e1684657ftye      break;
530fb115c61504fe6c4f94be0a87f75e28e1684657ftye
531fb115c61504fe6c4f94be0a87f75e28e1684657ftye    default:
532fb115c61504fe6c4f94be0a87f75e28e1684657ftye
533fb115c61504fe6c4f94be0a87f75e28e1684657ftye      return EFI_ABORTED;
534fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
535fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } while (Flag);
536fb115c61504fe6c4f94be0a87f75e28e1684657ftye
537fb115c61504fe6c4f94be0a87f75e28e1684657ftye  TrimBytes = (UINT32) (PayLoadHdr - (UINT8 *) IcmpHdr);
538fb115c61504fe6c4f94be0a87f75e28e1684657ftye
539fb115c61504fe6c4f94be0a87f75e28e1684657ftye  NetbufTrim (Pkt, TrimBytes, TRUE);
540fb115c61504fe6c4f94be0a87f75e28e1684657ftye
541b45b45b2d248892930620c33a9d01d8457ae0e54tye  IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);
542fb115c61504fe6c4f94be0a87f75e28e1684657ftye
543cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
544cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
545cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
546fb115c61504fe6c4f94be0a87f75e28e1684657ftye/**
547fb115c61504fe6c4f94be0a87f75e28e1684657ftye  This function handles ICMP packets.
548fb115c61504fe6c4f94be0a87f75e28e1684657ftye
549fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       IpIo            Pointer to the IP_IO instance.
550fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in, out]  Pkt             Pointer to the ICMP packet.
551fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       Session         Pointer to the net session of this ICMP packet.
552fb115c61504fe6c4f94be0a87f75e28e1684657ftye
553fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_SUCCESS     The ICMP packet is handled successfully.
554fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_ABORTED     This type of ICMP packet is not supported.
555fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_UNSUPPORTED The IP protocol version in IP_IO is not supported.
556fb115c61504fe6c4f94be0a87f75e28e1684657ftye
557fb115c61504fe6c4f94be0a87f75e28e1684657ftye**/
558fb115c61504fe6c4f94be0a87f75e28e1684657ftyeEFI_STATUS
559fb115c61504fe6c4f94be0a87f75e28e1684657ftyeIpIoIcmpHandler (
560fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     IP_IO                *IpIo,
561fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN OUT NET_BUF              *Pkt,
562fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     EFI_NET_SESSION_DATA *Session
563fb115c61504fe6c4f94be0a87f75e28e1684657ftye  )
564fb115c61504fe6c4f94be0a87f75e28e1684657ftye{
565fb115c61504fe6c4f94be0a87f75e28e1684657ftye
566fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4) {
567fb115c61504fe6c4f94be0a87f75e28e1684657ftye
568fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return IpIoIcmpv4Handler (IpIo, Pkt, Session);
569fb115c61504fe6c4f94be0a87f75e28e1684657ftye
570fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (IpIo->IpVersion == IP_VERSION_6) {
571fb115c61504fe6c4f94be0a87f75e28e1684657ftye
572fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return IpIoIcmpv6Handler (IpIo, Pkt, Session);
573fb115c61504fe6c4f94be0a87f75e28e1684657ftye
574fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
575fb115c61504fe6c4f94be0a87f75e28e1684657ftye
576fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return EFI_UNSUPPORTED;
577fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
578fb115c61504fe6c4f94be0a87f75e28e1684657ftye}
579fb115c61504fe6c4f94be0a87f75e28e1684657ftye
580cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
581cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
582e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  Free function for receive token of IP_IO. It is used to
583cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  signal the recycle event to notify IP to recycle the
584cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  data buffer.
585cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
5866aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event to be signaled.
587cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
588cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
589cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
590e798cd87ca9a3a30c4cea50c5f5de84e10a8bc5ageekboyEFIAPI
591cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoExtFree (
592cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID  *Event
593cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
594cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
595cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->SignalEvent ((EFI_EVENT) Event);
596cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
597cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
598cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
599cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
600cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Create a send entry to wrap a packet before sending
601cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  out it through IP.
602cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
6036aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo                 Pointer to the IP_IO instance.
6046aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  Pkt                  Pointer to the packet.
6056aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Sender               Pointer to the IP sender.
6066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Context              Pointer to the context.
6076aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       NotifyData           Pointer to the notify data.
6086aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Dest                 Pointer to the destination IP address.
6096aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Override             Pointer to the overriden IP_IO data.
610cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
611cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return Pointer to the data structure created to wrap the packet. If NULL,
6126aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @return resource limit occurred.
613cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
614cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
615cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_SEND_ENTRY *
616cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreateSndEntry (
6176aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO             *IpIo,
6186aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT NET_BUF           *Pkt,
619fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     VOID              *Sender,
6206aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID              *Context    OPTIONAL,
6216aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID              *NotifyData OPTIONAL,
622fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     EFI_IP_ADDRESS    *Dest       OPTIONAL,
6236aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_OVERRIDE    *Override
624cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
625cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
626cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY          *SndEntry;
627fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_EVENT                 Event;
628cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS                Status;
629fb115c61504fe6c4f94be0a87f75e28e1684657ftye  NET_FRAGMENT              *ExtFragment;
630fb115c61504fe6c4f94be0a87f75e28e1684657ftye  UINT32                    FragmentCount;
631fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IP_IO_OVERRIDE            *OverrideData;
632fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IP_IO_IP_TX_DATA          *TxData;
633fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_IP4_TRANSMIT_DATA     *Ip4TxData;
634fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_IP6_TRANSMIT_DATA     *Ip6TxData;
635fb115c61504fe6c4f94be0a87f75e28e1684657ftye
636fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if ((IpIo->IpVersion != IP_VERSION_4) && (IpIo->IpVersion != IP_VERSION_6)) {
637fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return NULL;
638fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
639fb115c61504fe6c4f94be0a87f75e28e1684657ftye
640fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Event        = NULL;
641fb115c61504fe6c4f94be0a87f75e28e1684657ftye  TxData       = NULL;
642fb115c61504fe6c4f94be0a87f75e28e1684657ftye  OverrideData = NULL;
643cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
644cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
645cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for SndEntry
646cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
647e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  SndEntry = AllocatePool (sizeof (IP_IO_SEND_ENTRY));
648cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndEntry) {
649cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return NULL;
650cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
651cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
652cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
653cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
654e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
655cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoTransmitHandler,
656cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  SndEntry,
657fb115c61504fe6c4f94be0a87f75e28e1684657ftye                  &Event
658cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
659cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
660fb115c61504fe6c4f94be0a87f75e28e1684657ftye    goto ON_ERROR;
661cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
662cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
663fb115c61504fe6c4f94be0a87f75e28e1684657ftye  FragmentCount = Pkt->BlockOpNum;
664fb115c61504fe6c4f94be0a87f75e28e1684657ftye
665cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
666cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for TxData
667cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
668fb115c61504fe6c4f94be0a87f75e28e1684657ftye  TxData = (IP_IO_IP_TX_DATA *) AllocatePool (
669fb115c61504fe6c4f94be0a87f75e28e1684657ftye    sizeof (IP_IO_IP_TX_DATA) + sizeof (NET_FRAGMENT) * (FragmentCount - 1)
670cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    );
671cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
672cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == TxData) {
673fb115c61504fe6c4f94be0a87f75e28e1684657ftye    goto ON_ERROR;
674fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
675fb115c61504fe6c4f94be0a87f75e28e1684657ftye
676fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
677fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Build a fragment table to contain the fragments in the packet.
678fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
679fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4) {
680fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ExtFragment = (NET_FRAGMENT *) TxData->Ip4TxData.FragmentTable;
681fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
682fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ExtFragment = (NET_FRAGMENT *) TxData->Ip6TxData.FragmentTable;
683cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
684cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
685fb115c61504fe6c4f94be0a87f75e28e1684657ftye  NetbufBuildExt (Pkt, ExtFragment, &FragmentCount);
686fb115c61504fe6c4f94be0a87f75e28e1684657ftye
687fb115c61504fe6c4f94be0a87f75e28e1684657ftye
688cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
689cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for OverrideData if needed
690cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
691cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL != Override) {
692cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
693fb115c61504fe6c4f94be0a87f75e28e1684657ftye    OverrideData = AllocateCopyPool (sizeof (IP_IO_OVERRIDE), Override);
694cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (NULL == OverrideData) {
695fb115c61504fe6c4f94be0a87f75e28e1684657ftye      goto ON_ERROR;
696cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
697cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
698cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
699cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
700fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Set other fields of TxData except the fragment table
701cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
702fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4) {
703cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
704fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip4TxData = &TxData->Ip4TxData;
705cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
706fb115c61504fe6c4f94be0a87f75e28e1684657ftye    CopyMem (&Ip4TxData->DestinationAddress, Dest, sizeof (EFI_IPv4_ADDRESS));
707cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
708fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip4TxData->OverrideData    = &OverrideData->Ip4OverrideData;
709fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip4TxData->OptionsLength   = 0;
710fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip4TxData->OptionsBuffer   = NULL;
711fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip4TxData->TotalDataLength = Pkt->TotalSize;
712fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip4TxData->FragmentCount   = FragmentCount;
713fb115c61504fe6c4f94be0a87f75e28e1684657ftye
714fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
715fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // Set the fields of SndToken
716fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
717fb115c61504fe6c4f94be0a87f75e28e1684657ftye    SndEntry->SndToken.Ip4Token.Event         = Event;
718fb115c61504fe6c4f94be0a87f75e28e1684657ftye    SndEntry->SndToken.Ip4Token.Packet.TxData = Ip4TxData;
719fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
720fb115c61504fe6c4f94be0a87f75e28e1684657ftye
721fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip6TxData = &TxData->Ip6TxData;
722fb115c61504fe6c4f94be0a87f75e28e1684657ftye
723fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (Dest != NULL) {
724fb115c61504fe6c4f94be0a87f75e28e1684657ftye      CopyMem (&Ip6TxData->DestinationAddress, Dest, sizeof (EFI_IPv6_ADDRESS));
725fb115c61504fe6c4f94be0a87f75e28e1684657ftye    } else {
726fb115c61504fe6c4f94be0a87f75e28e1684657ftye      ZeroMem (&Ip6TxData->DestinationAddress, sizeof (EFI_IPv6_ADDRESS));
727fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
728fb115c61504fe6c4f94be0a87f75e28e1684657ftye
729fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip6TxData->OverrideData  = &OverrideData->Ip6OverrideData;
730fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip6TxData->DataLength    = Pkt->TotalSize;
731fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip6TxData->FragmentCount = FragmentCount;
732fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip6TxData->ExtHdrsLength = 0;
733fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip6TxData->ExtHdrs       = NULL;
734fb115c61504fe6c4f94be0a87f75e28e1684657ftye
735fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
736fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // Set the fields of SndToken
737fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
738fb115c61504fe6c4f94be0a87f75e28e1684657ftye    SndEntry->SndToken.Ip6Token.Event         = Event;
739fb115c61504fe6c4f94be0a87f75e28e1684657ftye    SndEntry->SndToken.Ip6Token.Packet.TxData = Ip6TxData;
740fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
741cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
742cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
743cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Set the fields of SndEntry
744cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
745cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->IpIo        = IpIo;
7466aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  SndEntry->Ip          = Sender;
747cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->Context     = Context;
748cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->NotifyData  = NotifyData;
749cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
750cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->Pkt         = Pkt;
751cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_GET_REF (Pkt);
752cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
753e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertTailList (&IpIo->PendingSndList, &SndEntry->Entry);
754cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
755cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return SndEntry;
756cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
757fb115c61504fe6c4f94be0a87f75e28e1684657ftyeON_ERROR:
758fb115c61504fe6c4f94be0a87f75e28e1684657ftye
759fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (OverrideData != NULL) {
760fb115c61504fe6c4f94be0a87f75e28e1684657ftye    FreePool (OverrideData);
761fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
762cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
763fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (TxData != NULL) {
764fb115c61504fe6c4f94be0a87f75e28e1684657ftye    FreePool (TxData);
765fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
766cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
767fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (SndEntry != NULL) {
768fb115c61504fe6c4f94be0a87f75e28e1684657ftye    FreePool (SndEntry);
769fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
770cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
771fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (Event != NULL) {
772fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->CloseEvent (Event);
773fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
774cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
775cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
776cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
777cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
778cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
779cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
780cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy the SndEntry.
781e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
782e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function pairs with IpIoCreateSndEntry().
783cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
7846aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  SndEntry              Pointer to the send entry to be destroyed.
785cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
786cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
787cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
788cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoDestroySndEntry (
789cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO_SEND_ENTRY  *SndEntry
790cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
791cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
792fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_EVENT         Event;
793fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IP_IO_IP_TX_DATA  *TxData;
794fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IP_IO_OVERRIDE    *Override;
795fb115c61504fe6c4f94be0a87f75e28e1684657ftye
796fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (SndEntry->IpIo->IpVersion == IP_VERSION_4) {
797fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Event              = SndEntry->SndToken.Ip4Token.Event;
798fb115c61504fe6c4f94be0a87f75e28e1684657ftye    TxData             = (IP_IO_IP_TX_DATA *) SndEntry->SndToken.Ip4Token.Packet.TxData;
799fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Override           = (IP_IO_OVERRIDE *) TxData->Ip4TxData.OverrideData;
800fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (SndEntry->IpIo->IpVersion == IP_VERSION_6) {
801fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Event              = SndEntry->SndToken.Ip6Token.Event;
802fb115c61504fe6c4f94be0a87f75e28e1684657ftye    TxData             = (IP_IO_IP_TX_DATA *) SndEntry->SndToken.Ip6Token.Packet.TxData;
803fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Override           = (IP_IO_OVERRIDE *) TxData->Ip6TxData.OverrideData;
804fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
805fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return ;
806fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
807cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
808fb115c61504fe6c4f94be0a87f75e28e1684657ftye  gBS->CloseEvent (Event);
809cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
810fb115c61504fe6c4f94be0a87f75e28e1684657ftye  FreePool (TxData);
811fb115c61504fe6c4f94be0a87f75e28e1684657ftye
812fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (NULL != Override) {
813fb115c61504fe6c4f94be0a87f75e28e1684657ftye    FreePool (Override);
814cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
815cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
816cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetbufFree (SndEntry->Pkt);
817cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
818e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RemoveEntryList (&SndEntry->Entry);
819cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
820fb115c61504fe6c4f94be0a87f75e28e1684657ftye  FreePool (SndEntry);
821cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
822cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
823cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
824cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
825cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Notify function for IP transmit token.
826cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
8276aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
828cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
829cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
830cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
831cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
83236ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoTransmitHandlerDpc (
833cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
834cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
835cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
836cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO             *IpIo;
837cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
838fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_STATUS        Status;
839cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
840cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry  = (IP_IO_SEND_ENTRY *) Context;
841cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
842cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo      = SndEntry->IpIo;
843cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
844fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4) {
845fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = SndEntry->SndToken.Ip4Token.Status;
846fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (IpIo->IpVersion == IP_VERSION_6){
847fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = SndEntry->SndToken.Ip6Token.Status;
848fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
849fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return ;
850fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
851fb115c61504fe6c4f94be0a87f75e28e1684657ftye
8528de75da28bbd9a4d3c54fba99d943f9019b52193niry  if ((IpIo->PktSentNotify != NULL) && (SndEntry->NotifyData != NULL)) {
853cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->PktSentNotify (
854fb115c61504fe6c4f94be0a87f75e28e1684657ftye            Status,
855cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->Context,
856cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->Ip,
857cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->NotifyData
858cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            );
859cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
860cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
861cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoDestroySndEntry (SndEntry);
862cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
863cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
8646aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
86536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff/**
86636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  Notify function for IP transmit token.
86736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
8686aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event signaled.
8696aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
87036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
87136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff**/
87236ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
87336ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
87436ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoTransmitHandler (
87536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN EFI_EVENT Event,
87636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
87736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  )
87836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff{
87936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
88036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK
88136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
882d8d26fb207e02aa5ef57e2bcb213f9dda16166ccmdkinney  QueueDpc (TPL_CALLBACK, IpIoTransmitHandlerDpc, Context);
88336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff}
88436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
885cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
886cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
887cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  The dummy handler for the dummy IP receive token.
888cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
8896aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
890cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
891cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
892cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
893cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
89436ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoDummyHandlerDpc (
895cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
896cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
897cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
898cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO             *IpInfo;
899fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_STATUS                 Status;
900fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_EVENT                  RecycleEvent;
901cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
902cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo      = (IP_IO_IP_INFO *) Context;
903cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
904fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if ((IpInfo->IpVersion != IP_VERSION_4) && (IpInfo->IpVersion != IP_VERSION_6)) {
905fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return ;
906fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
907fb115c61504fe6c4f94be0a87f75e28e1684657ftye
908fb115c61504fe6c4f94be0a87f75e28e1684657ftye  RecycleEvent = NULL;
909fb115c61504fe6c4f94be0a87f75e28e1684657ftye
910fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpInfo->IpVersion == IP_VERSION_4) {
911fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = IpInfo->DummyRcvToken.Ip4Token.Status;
912fb115c61504fe6c4f94be0a87f75e28e1684657ftye
913fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (IpInfo->DummyRcvToken.Ip4Token.Packet.RxData != NULL) {
914fb115c61504fe6c4f94be0a87f75e28e1684657ftye      RecycleEvent = IpInfo->DummyRcvToken.Ip4Token.Packet.RxData->RecycleSignal;
915fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
916fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
917fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = IpInfo->DummyRcvToken.Ip6Token.Status;
918fb115c61504fe6c4f94be0a87f75e28e1684657ftye
919fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (IpInfo->DummyRcvToken.Ip6Token.Packet.RxData != NULL) {
920fb115c61504fe6c4f94be0a87f75e28e1684657ftye      RecycleEvent = IpInfo->DummyRcvToken.Ip6Token.Packet.RxData->RecycleSignal;
921fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
922fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
923fb115c61504fe6c4f94be0a87f75e28e1684657ftye
924fb115c61504fe6c4f94be0a87f75e28e1684657ftye
925fb115c61504fe6c4f94be0a87f75e28e1684657ftye
926fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (EFI_ABORTED == Status) {
92736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
92836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    // The reception is actively aborted by the consumer, directly return.
92936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
93036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    return;
931fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (EFI_SUCCESS == Status) {
932fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
933fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // Recycle the RxData.
934fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
935fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ASSERT (RecycleEvent != NULL);
936cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
937fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->SignalEvent (RecycleEvent);
938cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
939cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
940fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
941fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Continue the receive.
942fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
943fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpInfo->IpVersion == IP_VERSION_4) {
944fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ((EFI_IP4_PROTOCOL *) (IpInfo->Ip))->Receive (
945fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                           (EFI_IP4_PROTOCOL *) (IpInfo->Ip),
946fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                           &IpInfo->DummyRcvToken.Ip4Token
947fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                           );
948fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
949fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ((EFI_IP6_PROTOCOL *) (IpInfo->Ip))->Receive (
950fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                           (EFI_IP6_PROTOCOL *) (IpInfo->Ip),
951fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                           &IpInfo->DummyRcvToken.Ip6Token
952fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                           );
953fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
954cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
955cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
956cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
957cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
9586aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  This function add IpIoDummyHandlerDpc to the end of the DPC queue.
959cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
9606aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event signaled.
9616aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
962cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
963cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
964cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
965cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
96636ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoDummyHandler (
967cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_EVENT Event,
968cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
969cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
970cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
97136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
97236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK
97336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
974d8d26fb207e02aa5ef57e2bcb213f9dda16166ccmdkinney  QueueDpc (TPL_CALLBACK, IpIoDummyHandlerDpc, Context);
97536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff}
97636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
97736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
97836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff/**
97936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  Notify function for the IP receive token, used to process
98036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  the received IP packets.
98136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
9826aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
98336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
98436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff**/
98536ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
98636ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
98736ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoListenHandlerDpc (
98836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
98936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  )
99036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff{
991cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO                 *IpIo;
992cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS            Status;
993fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IP_IO_IP_RX_DATA      *RxData;
994fb115c61504fe6c4f94be0a87f75e28e1684657ftye  VOID                  *Ip;
995cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_NET_SESSION_DATA  Session;
996cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_BUF               *Pkt;
997cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
998fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpIo = (IP_IO *) Context;
999fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Ip   = IpIo->Ip;
1000cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1001fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4) {
1002fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = IpIo->RcvToken.Ip4Token.Status;
1003fb115c61504fe6c4f94be0a87f75e28e1684657ftye    RxData = (IP_IO_IP_RX_DATA *) IpIo->RcvToken.Ip4Token.Packet.RxData;
1004fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (IpIo->IpVersion == IP_VERSION_6) {
1005fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = IpIo->RcvToken.Ip6Token.Status;
1006fb115c61504fe6c4f94be0a87f75e28e1684657ftye    RxData = (IP_IO_IP_RX_DATA *) IpIo->RcvToken.Ip6Token.Packet.RxData;
1007fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1008fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return;
1009fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1010cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
101136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  if (EFI_ABORTED == Status) {
101236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
101336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    // The reception is actively aborted by the consumer, directly return.
101436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
101536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    return;
101636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  }
101736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
1018cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (((EFI_SUCCESS != Status) && (EFI_ICMP_ERROR != Status)) || (NULL == RxData)) {
1019cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
10206aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // @bug Only process the normal packets and the icmp error packets, if RxData is NULL
10216aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // @bug with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
10226aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // @bug this should be a bug of the low layer (IP).
1023cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1024cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto Resume;
1025cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1026cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1027cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == IpIo->PktRcvdNotify) {
1028cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
1029cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1030cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1031fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4) {
1032fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if ((EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress) != 0) &&
1033f6b7393ceb34c9b3a27434268bf2ce517047641ftye      !NetIp4IsUnicast (EFI_NTOHL (((EFI_IP4_RECEIVE_DATA *) RxData)->Header->SourceAddress), 0)) {
1034cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1035cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // The source address is not zero and it's not a unicast IP address, discard it.
1036cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1037cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
1038cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1039cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1040cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1041fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Create a netbuffer representing IPv4 packet
1042cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1043cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Pkt = NetbufFromExt (
1044fb115c61504fe6c4f94be0a87f75e28e1684657ftye          (NET_FRAGMENT *) RxData->Ip4RxData.FragmentTable,
1045fb115c61504fe6c4f94be0a87f75e28e1684657ftye          RxData->Ip4RxData.FragmentCount,
1046cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          0,
1047cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          0,
1048cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          IpIoExtFree,
1049fb115c61504fe6c4f94be0a87f75e28e1684657ftye          RxData->Ip4RxData.RecycleSignal
1050cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          );
1051cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == Pkt) {
1052cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
1053cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1054cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1055cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1056cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create a net session
1057cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1058fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Session.Source.Addr[0] = EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress);
1059fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Session.Dest.Addr[0]   = EFI_IP4 (RxData->Ip4RxData.Header->DestinationAddress);
1060fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Session.IpHdr.Ip4Hdr   = RxData->Ip4RxData.Header;
1061a09ee46d9a258ef08a931c0d412c62c98dbdb8aaqouyang  Session.IpHdrLen       = RxData->Ip4RxData.HeaderLength;
1062fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Session.IpVersion      = IP_VERSION_4;
1063fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1064fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1065f6b7393ceb34c9b3a27434268bf2ce517047641ftye    if (!NetIp6IsValidUnicast(&RxData->Ip6RxData.Header->SourceAddress)) {
1066fb115c61504fe6c4f94be0a87f75e28e1684657ftye      goto CleanUp;
1067fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
1068fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1069fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
1070fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // Create a netbuffer representing IPv6 packet
1071fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
1072fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Pkt = NetbufFromExt (
1073fb115c61504fe6c4f94be0a87f75e28e1684657ftye            (NET_FRAGMENT *) RxData->Ip6RxData.FragmentTable,
1074fb115c61504fe6c4f94be0a87f75e28e1684657ftye            RxData->Ip6RxData.FragmentCount,
1075fb115c61504fe6c4f94be0a87f75e28e1684657ftye            0,
1076fb115c61504fe6c4f94be0a87f75e28e1684657ftye            0,
1077fb115c61504fe6c4f94be0a87f75e28e1684657ftye            IpIoExtFree,
1078fb115c61504fe6c4f94be0a87f75e28e1684657ftye            RxData->Ip6RxData.RecycleSignal
1079fb115c61504fe6c4f94be0a87f75e28e1684657ftye            );
1080fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (NULL == Pkt) {
1081fb115c61504fe6c4f94be0a87f75e28e1684657ftye      goto CleanUp;
1082fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
1083fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1084fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
1085fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // Create a net session
1086fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
1087fb115c61504fe6c4f94be0a87f75e28e1684657ftye    CopyMem (
1088fb115c61504fe6c4f94be0a87f75e28e1684657ftye      &Session.Source,
1089fb115c61504fe6c4f94be0a87f75e28e1684657ftye      &RxData->Ip6RxData.Header->SourceAddress,
1090fb115c61504fe6c4f94be0a87f75e28e1684657ftye      sizeof(EFI_IPv6_ADDRESS)
1091fb115c61504fe6c4f94be0a87f75e28e1684657ftye      );
1092fb115c61504fe6c4f94be0a87f75e28e1684657ftye    CopyMem (
1093fb115c61504fe6c4f94be0a87f75e28e1684657ftye      &Session.Dest,
1094fb115c61504fe6c4f94be0a87f75e28e1684657ftye      &RxData->Ip6RxData.Header->DestinationAddress,
1095fb115c61504fe6c4f94be0a87f75e28e1684657ftye      sizeof(EFI_IPv6_ADDRESS)
1096fb115c61504fe6c4f94be0a87f75e28e1684657ftye      );
1097fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Session.IpHdr.Ip6Hdr = RxData->Ip6RxData.Header;
1098a09ee46d9a258ef08a931c0d412c62c98dbdb8aaqouyang    Session.IpHdrLen     = RxData->Ip6RxData.HeaderLength;
1099fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Session.IpVersion    = IP_VERSION_6;
1100fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1101cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1102cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_SUCCESS == Status) {
1103cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1104b45b45b2d248892930620c33a9d01d8457ae0e54tye    IpIo->PktRcvdNotify (EFI_SUCCESS, 0, &Session, Pkt, IpIo->RcvdContext);
1105cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  } else {
1106cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1107cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // Status is EFI_ICMP_ERROR
1108cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1109cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    Status = IpIoIcmpHandler (IpIo, Pkt, &Session);
1110cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (EFI_ERROR (Status)) {
1111cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      NetbufFree (Pkt);
1112cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1113cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1114cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1115cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  goto Resume;
1116cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1117cbf316f20726bb31b7c37424601643790dbd02d9vanjeffCleanUp:
1118fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1119fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4){
1120fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->SignalEvent (RxData->Ip4RxData.RecycleSignal);
1121fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1122fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->SignalEvent (RxData->Ip6RxData.RecycleSignal);
1123fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1124cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1125cbf316f20726bb31b7c37424601643790dbd02d9vanjeffResume:
1126cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1127fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4){
1128fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ((EFI_IP4_PROTOCOL *) Ip)->Receive (Ip, &(IpIo->RcvToken.Ip4Token));
1129fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1130fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ((EFI_IP6_PROTOCOL *) Ip)->Receive (Ip, &(IpIo->RcvToken.Ip6Token));
1131fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1132fb115c61504fe6c4f94be0a87f75e28e1684657ftye}
1133cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1134cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
11356aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  This function add IpIoListenHandlerDpc to the end of the DPC queue.
113636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
11376aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                The event signaled.
11386aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context              The context passed in by the event notifier.
113936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
114036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff**/
114136ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
114236ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
114336ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoListenHandler (
114436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN EFI_EVENT Event,
114536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
114636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  )
114736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff{
114836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
114936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
115036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
1151d8d26fb207e02aa5ef57e2bcb213f9dda16166ccmdkinney  QueueDpc (TPL_CALLBACK, IpIoListenHandlerDpc, Context);
115236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff}
115336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
115436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
115536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff/**
1156cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Create a new IP_IO instance.
1157e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1158fb115c61504fe6c4f94be0a87f75e28e1684657ftye  This function uses IP4/IP6 service binding protocol in Controller to create
1159fb115c61504fe6c4f94be0a87f75e28e1684657ftye  an IP4/IP6 child (aka IP4/IP6 instance).
1160cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
11616aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Image             The image handle of the driver or application that
1162e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong                                consumes IP_IO.
1163fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]  Controller        The controller handle that has IP4 or IP6 service
1164fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                binding protocol installed.
1165fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]  IpVersion         The version of the IP protocol to use, either
1166fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                IPv4 or IPv6.
1167cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1168e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  @return Pointer to a newly created IP_IO instance, or NULL if failed.
1169cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1170cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1171cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO *
11727b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1173cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreate (
1174cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE Image,
1175fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN EFI_HANDLE Controller,
1176b45b45b2d248892930620c33a9d01d8457ae0e54tye  IN UINT8      IpVersion
1177cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1178cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1179cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
1180cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO       *IpIo;
1181fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_EVENT   Event;
1182fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1183fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
1184cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1185e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  IpIo = AllocateZeroPool (sizeof (IP_IO));
1186cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == IpIo) {
1187cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return NULL;
1188cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1189cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1190e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&(IpIo->PendingSndList));
1191e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&(IpIo->IpList));
1192cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Controller  = Controller;
1193cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Image       = Image;
1194fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpIo->IpVersion   = IpVersion;
1195fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Event             = NULL;
1196cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1197cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
1198cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
1199e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
1200cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoListenHandler,
1201cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIo,
1202fb115c61504fe6c4f94be0a87f75e28e1684657ftye                  &Event
1203cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
1204cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1205cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpIo;
1206cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1207cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1208fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4) {
1209fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->RcvToken.Ip4Token.Event = Event;
1210fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1211fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->RcvToken.Ip6Token.Event = Event;
1212fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1213fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1214cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1215cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create an IP child and open IP protocol
1216cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1217cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = IpIoCreateIpChildOpenProtocol (
1218cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             Controller,
1219cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             Image,
1220cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &IpIo->ChildHandle,
1221fb115c61504fe6c4f94be0a87f75e28e1684657ftye             IpVersion,
1222cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             (VOID **)&(IpIo->Ip)
1223cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
1224cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1225cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpIo;
1226cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1227cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1228cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return IpIo;
1229cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1230cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpIo:
1231cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1232fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (Event != NULL) {
1233fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->CloseEvent (Event);
1234cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1235cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1236e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpIo);
1237cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1238cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
1239cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1240cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1241cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1242cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1243cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Open an IP_IO instance for use.
1244e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1245e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is called after IpIoCreate(). It is used for configuring the IP
1246e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  instance and register the callbacks and their context data for sending and
1247e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  receiving IP packets.
1248cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
12496aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo               Pointer to an IP_IO instance that needs
12506aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      to open.
12516aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       OpenData           The configuration data and callbacks for
12526aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      the IP_IO instance.
1253cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
12546aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS        The IP_IO instance opened with OpenData
12556aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      successfully.
12566aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_ACCESS_DENIED  The IP_IO instance is configured, avoid to
12576aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      reopen it.
12586aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others             Error condition occurred.
1259cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1260cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1261cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
12627b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1263cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoOpen (
12646aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO           *IpIo,
12656aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_OPEN_DATA *OpenData
1266cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1267cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1268cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
1269fb115c61504fe6c4f94be0a87f75e28e1684657ftye  VOID              *Ip;
1270b45b45b2d248892930620c33a9d01d8457ae0e54tye  UINT8             IpVersion;
1271cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1272cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpIo->IsConfigured) {
1273cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ACCESS_DENIED;
1274cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1275cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1276fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpVersion = IpIo->IpVersion;
1277fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1278fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
1279fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1280cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpIo->Ip;
1281cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1282cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1283cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // configure ip
1284cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1285fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4){
1286fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = ((EFI_IP4_PROTOCOL *) Ip)->Configure (
1287fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          (EFI_IP4_PROTOCOL *) Ip,
1288fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          &OpenData->IpConfigData.Ip4CfgData
1289fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          );
1290fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1291fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1292fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = ((EFI_IP6_PROTOCOL *) Ip)->Configure (
1293fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          (EFI_IP6_PROTOCOL *) Ip,
1294fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          &OpenData->IpConfigData.Ip6CfgData
1295fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          );
1296fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1297fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1298cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1299cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
1300cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1301cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1302cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
13036aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // @bug To delete the default route entry in this Ip, if it is:
13046aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // @bug (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified
13056aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // @bug its code
1306cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1307fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4){
1308fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = ((EFI_IP4_PROTOCOL *) Ip)->Routes (
1309fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          (EFI_IP4_PROTOCOL *) Ip,
1310fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          TRUE,
1311fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          &mZeroIp4Addr,
1312fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          &mZeroIp4Addr,
1313fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          &mZeroIp4Addr
1314fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          );
1315fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1316fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (EFI_ERROR (Status) && (EFI_NOT_FOUND != Status)) {
1317fb115c61504fe6c4f94be0a87f75e28e1684657ftye      return Status;
1318fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
1319cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1320cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1321cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktRcvdNotify = OpenData->PktRcvdNotify;
1322cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktSentNotify = OpenData->PktSentNotify;
1323cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1324cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->RcvdContext   = OpenData->RcvdContext;
1325cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->SndContext    = OpenData->SndContext;
1326cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1327fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4){
1328fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->Protocol = OpenData->IpConfigData.Ip4CfgData.DefaultProtocol;
1329cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1330fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
1331fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // start to listen incoming packet
1332fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
1333fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = ((EFI_IP4_PROTOCOL *) Ip)->Receive (
1334fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          (EFI_IP4_PROTOCOL *) Ip,
1335fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          &(IpIo->RcvToken.Ip4Token)
1336fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          );
1337fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (EFI_ERROR (Status)) {
1338fb115c61504fe6c4f94be0a87f75e28e1684657ftye      ((EFI_IP4_PROTOCOL *) Ip)->Configure ((EFI_IP4_PROTOCOL *) Ip, NULL);
1339fb115c61504fe6c4f94be0a87f75e28e1684657ftye      goto ErrorExit;
1340fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
1341fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1342fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1343fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1344fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->Protocol = OpenData->IpConfigData.Ip6CfgData.DefaultProtocol;
1345fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = ((EFI_IP6_PROTOCOL *) Ip)->Receive (
1346fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          (EFI_IP6_PROTOCOL *) Ip,
1347fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          &(IpIo->RcvToken.Ip6Token)
1348fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          );
1349fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (EFI_ERROR (Status)) {
1350fb115c61504fe6c4f94be0a87f75e28e1684657ftye      ((EFI_IP6_PROTOCOL *) Ip)->Configure ((EFI_IP6_PROTOCOL *) Ip, NULL);
1351fb115c61504fe6c4f94be0a87f75e28e1684657ftye      goto ErrorExit;
1352fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
1353cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1354cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1355cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->IsConfigured = TRUE;
1356e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertTailList (&mActiveIpIoList, &IpIo->Entry);
1357cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1358cbf316f20726bb31b7c37424601643790dbd02d9vanjeffErrorExit:
1359cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1360cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
1361cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1362cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1363cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1364cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1365cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Stop an IP_IO instance.
1366e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1367e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is paired with IpIoOpen(). The IP_IO will be unconfigured and all
1368e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  the pending send/receive tokens will be canceled.
1369cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
13706aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo            Pointer to the IP_IO instance that needs to stop.
1371cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
13726aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS     The IP_IO instance stopped successfully.
13736aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others          Error condition occurred.
1374cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1375cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1376cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
1377e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgongEFIAPI
1378cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoStop (
13796aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO *IpIo
1380cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1381cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1382cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
1383fb115c61504fe6c4f94be0a87f75e28e1684657ftye  VOID              *Ip;
1384cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO     *IpInfo;
1385b45b45b2d248892930620c33a9d01d8457ae0e54tye  UINT8             IpVersion;
1386cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1387cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (!IpIo->IsConfigured) {
1388cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_SUCCESS;
1389cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1390cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1391fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpVersion = IpIo->IpVersion;
1392fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1393fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
1394fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1395cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1396cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Remove the IpIo from the active IpIo list.
1397cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1398e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RemoveEntryList (&IpIo->Entry);
1399cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1400cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpIo->Ip;
1401cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1402cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1403cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Configure NULL Ip
1404cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1405fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4) {
1406fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = ((EFI_IP4_PROTOCOL *) Ip)->Configure ((EFI_IP4_PROTOCOL *) Ip, NULL);
1407fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1408fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = ((EFI_IP6_PROTOCOL *) Ip)->Configure ((EFI_IP6_PROTOCOL *) Ip, NULL);
1409fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1410cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1411cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
1412cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1413cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1414cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->IsConfigured = FALSE;
1415cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1416cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1417cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Detroy the Ip List used by IpIo
1418cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
141934edf2ae729941a6203e4e7f614db32204a9c47dvanjeff
1420e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  while (!IsListEmpty (&(IpIo->IpList))) {
1421cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo = NET_LIST_HEAD (&(IpIo->IpList), IP_IO_IP_INFO, Entry);
1422cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1423cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoRemoveIp (IpIo, IpInfo);
1424cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1425cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1426cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
14276aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // All pending send tokens should be flushed by reseting the IP instances.
1428cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1429e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  ASSERT (IsListEmpty (&IpIo->PendingSndList));
1430cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1431cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1432cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Close the receive event.
1433cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1434fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4){
1435fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->CloseEvent (IpIo->RcvToken.Ip4Token.Event);
1436fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1437fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->CloseEvent (IpIo->RcvToken.Ip6Token.Event);
1438fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1439cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1440cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
1441cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1442cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1443cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1444cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1445cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy an IP_IO instance.
1446e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1447e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is paired with IpIoCreate(). The IP_IO will be closed first.
14488f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  Resource will be freed afterwards. See IpIoCloseProtocolDestroyIpChild().
1449cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
14506aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo         Pointer to the IP_IO instance that needs to be
1451e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong                                destroyed.
1452cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
14536aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS  The IP_IO instance destroyed successfully.
14546aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others       Error condition occurred.
1455cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1456cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1457cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
14587b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1459cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoDestroy (
14606aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO *IpIo
1461cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1462cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1463cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1464cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Stop the IpIo.
1465cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1466cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoStop (IpIo);
1467cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1468cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1469cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Close the IP protocol and destroy the child.
1470cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1471fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpIoCloseProtocolDestroyIpChild (
1472fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->Controller,
1473fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->Image,
1474fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->ChildHandle,
1475fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->IpVersion
1476fb115c61504fe6c4f94be0a87f75e28e1684657ftye    );
1477cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1478e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpIo);
1479cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1480cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
1481cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1482cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1483cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1484cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1485cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Send out an IP packet.
1486e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1487e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is called after IpIoOpen(). The data to be sent are wrapped in
1488e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  Pkt. The IP instance wrapped in IpIo is used for sending by default but can be
1489e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  overriden by Sender. Other sending configs, like source address and gateway
1490e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  address etc., are specified in OverrideData.
1491cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
14926aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo                  Pointer to an IP_IO instance used for sending IP
14936aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                         packet.
14946aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  Pkt                   Pointer to the IP packet to be sent.
14956aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Sender                The IP protocol instance used for sending.
14968f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[in]       Context               Optional context data.
14978f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[in]       NotifyData            Optional notify data.
14986aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Dest                  The destination IP address to send this packet to.
14996aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       OverrideData          The data to override some configuration of the IP
15006aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                         instance used for sending.
1501cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
15026aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS           The operation is completed successfully.
15036aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_NOT_STARTED       The IpIo is not configured.
15046aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_OUT_OF_RESOURCES  Failed due to resource limit.
1505cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1506cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1507cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
15087b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1509cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoSend (
15106aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO          *IpIo,
15116aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT NET_BUF        *Pkt,
15126aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_IP_INFO  *Sender        OPTIONAL,
15136aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID           *Context       OPTIONAL,
15146aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID           *NotifyData    OPTIONAL,
1515fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     EFI_IP_ADDRESS *Dest,
15166aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_OVERRIDE *OverrideData  OPTIONAL
1517cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1518cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1519cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
1520fb115c61504fe6c4f94be0a87f75e28e1684657ftye  VOID              *Ip;
1521cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
1522cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1523fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpIo->IpVersion != IP_VERSION_4) || (Dest != NULL));
1524fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1525cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (!IpIo->IsConfigured) {
1526cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_NOT_STARTED;
1527cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1528cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1529cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = (NULL == Sender) ? IpIo->Ip : Sender->Ip;
1530cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1531cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1532cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // create a new SndEntry
1533cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1534cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry = IpIoCreateSndEntry (IpIo, Pkt, Ip, Context, NotifyData, Dest, OverrideData);
1535cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndEntry) {
1536cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_OUT_OF_RESOURCES;
1537cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1538cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1539cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1540cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Send this Packet
1541cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1542fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4){
1543fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = ((EFI_IP4_PROTOCOL *) Ip)->Transmit (
1544fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          (EFI_IP4_PROTOCOL *) Ip,
1545fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          &SndEntry->SndToken.Ip4Token
1546fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          );
1547fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1548fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = ((EFI_IP6_PROTOCOL *) Ip)->Transmit (
1549fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          (EFI_IP6_PROTOCOL *) Ip,
1550fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          &SndEntry->SndToken.Ip6Token
1551fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                          );
1552fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1553fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1554cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1555cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoDestroySndEntry (SndEntry);
1556cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1557cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1558cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
1559cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1560cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1561cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1562cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1563cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Cancel the IP transmit token which wraps this Packet.
1564cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
15656aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  IpIo                  Pointer to the IP_IO instance.
15666aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Packet                Pointer to the packet of NET_BUF to cancel.
1567cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1568cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1569cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
15707b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1571cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCancelTxToken (
1572cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO  *IpIo,
1573cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID   *Packet
1574cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1575cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1576e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  LIST_ENTRY        *Node;
1577cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
1578fb115c61504fe6c4f94be0a87f75e28e1684657ftye  VOID              *Ip;
1579cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1580fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpIo != NULL) && (Packet != NULL));
1581cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1582cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_FOR_EACH (Node, &IpIo->PendingSndList) {
1583cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1584cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    SndEntry = NET_LIST_USER_STRUCT (Node, IP_IO_SEND_ENTRY, Entry);
1585cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1586cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (SndEntry->Pkt == Packet) {
1587cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1588cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip = SndEntry->Ip;
1589fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1590fb115c61504fe6c4f94be0a87f75e28e1684657ftye      if (IpIo->IpVersion == IP_VERSION_4) {
1591fb115c61504fe6c4f94be0a87f75e28e1684657ftye        ((EFI_IP4_PROTOCOL *) Ip)->Cancel (
1592fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     (EFI_IP4_PROTOCOL *) Ip,
1593fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     &SndEntry->SndToken.Ip4Token
1594fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     );
1595fb115c61504fe6c4f94be0a87f75e28e1684657ftye      } else {
1596fb115c61504fe6c4f94be0a87f75e28e1684657ftye        ((EFI_IP6_PROTOCOL *) Ip)->Cancel (
1597fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     (EFI_IP6_PROTOCOL *) Ip,
1598fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     &SndEntry->SndToken.Ip6Token
1599fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     );
1600fb115c61504fe6c4f94be0a87f75e28e1684657ftye      }
1601cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1602cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
1603cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1604cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1605cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1606cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1607cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1608cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1609cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1610cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Add a new IP instance for sending data.
1611e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1612e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  The function is used to add the IP_IO to the IP_IO sending list. The caller
1613e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send
1614e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  data.
1615cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
16166aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo               Pointer to a IP_IO instance to add a new IP
16176aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      instance for sending purpose.
1618cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1619e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  @return Pointer to the created IP_IO_IP_INFO structure, NULL if failed.
1620cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1621cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1622cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_IP_INFO *
16237b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1624cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoAddIp (
16256aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO  *IpIo
1626cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1627cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1628cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS     Status;
1629cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO  *IpInfo;
1630fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_EVENT      Event;
1631cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
16326aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  ASSERT (IpIo != NULL);
1633cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1634e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  IpInfo = AllocatePool (sizeof (IP_IO_IP_INFO));
1635cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo == NULL) {
1636fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return NULL;
1637cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1638cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1639cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1640cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP
1641cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // instance.
1642cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1643e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&IpInfo->Entry);
1644cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->ChildHandle = NULL;
1645fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ZeroMem (&IpInfo->Addr, sizeof (IpInfo->Addr));
1646fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ZeroMem (&IpInfo->PreMask, sizeof (IpInfo->PreMask));
1647fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1648fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpInfo->RefCnt    = 1;
1649fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpInfo->IpVersion = IpIo->IpVersion;
1650cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1651cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1652fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Create the IP instance and open the IP protocol.
1653cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1654cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = IpIoCreateIpChildOpenProtocol (
1655cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             IpIo->Controller,
1656cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             IpIo->Image,
1657cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &IpInfo->ChildHandle,
1658fb115c61504fe6c4f94be0a87f75e28e1684657ftye             IpInfo->IpVersion,
16594eb65aff715faafd9040c6fc85a5d59e22343978vanjeff             (VOID **) &IpInfo->Ip
1660cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
1661cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1662cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpInfo;
1663cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1664cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1665cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1666cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create the event for the DummyRcvToken.
1667cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1668cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
1669cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
1670e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
1671cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoDummyHandler,
1672cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpInfo,
1673fb115c61504fe6c4f94be0a87f75e28e1684657ftye                  &Event
1674cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
1675cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1676cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpChild;
1677cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1678cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1679fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpInfo->IpVersion == IP_VERSION_4) {
1680fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpInfo->DummyRcvToken.Ip4Token.Event = Event;
1681fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1682fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpInfo->DummyRcvToken.Ip6Token.Event = Event;
1683fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1684fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1685cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1686cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Link this IpInfo into the IpIo.
1687cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1688e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertTailList (&IpIo->IpList, &IpInfo->Entry);
1689cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1690cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return IpInfo;
1691cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1692cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpChild:
1693cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1694cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoCloseProtocolDestroyIpChild (
1695cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->Controller,
1696cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->Image,
1697fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpInfo->ChildHandle,
1698fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpInfo->IpVersion
1699cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    );
1700cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1701cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpInfo:
1702cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1703e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpInfo);
1704cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1705cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
1706cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1707cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1708cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1709cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1710fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Configure the IP instance of this IpInfo and start the receiving if IpConfigData
1711cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  is not NULL.
1712cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
17136aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpInfo          Pointer to the IP_IO_IP_INFO instance.
1714fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in, out]  IpConfigData    The IP configure data used to configure the IP
17156aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   instance, if NULL the IP instance is reset. If
17166aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   UseDefaultAddress is set to TRUE, and the configure
17176aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   operation succeeds, the default address information
1718fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                   is written back in this IpConfigData.
1719cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
17206aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS     The IP instance of this IpInfo is configured successfully
17216aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   or no need to reconfigure it.
17226aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others          Configuration fails.
1723cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1724cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1725cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
17267b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1727cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoConfigIp (
17286aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO_IP_INFO        *IpInfo,
1729fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN OUT VOID                 *IpConfigData OPTIONAL
1730cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1731cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1732cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS         Status;
1733fb115c61504fe6c4f94be0a87f75e28e1684657ftye  VOID               *Ip;
1734b45b45b2d248892930620c33a9d01d8457ae0e54tye  UINT8              IpVersion;
1735cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_MODE_DATA  Ip4ModeData;
1736fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_IP6_MODE_DATA  Ip6ModeData;
1737cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
17386aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  ASSERT (IpInfo != NULL);
1739cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1740cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo->RefCnt > 1) {
1741cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1742cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // This IP instance is shared, don't reconfigure it until it has only one
1743cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // consumer. Currently, only the tcp children cloned from their passive parent
1744fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // will share the same IP. So this cases only happens while IpConfigData is NULL,
1745cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // let the last consumer clean the IP instance.
1746cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1747cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_SUCCESS;
1748cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1749cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1750fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpVersion = IpInfo->IpVersion;
1751fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
1752fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1753cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpInfo->Ip;
1754cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1755fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpInfo->IpVersion == IP_VERSION_4) {
1756fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = ((EFI_IP4_PROTOCOL *) Ip)->Configure ((EFI_IP4_PROTOCOL *) Ip, IpConfigData);
1757fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1758fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = ((EFI_IP6_PROTOCOL *) Ip)->Configure ((EFI_IP6_PROTOCOL *) Ip, IpConfigData);
1759fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1760fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1761cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1762cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto OnExit;
1763cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1764cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1765fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpConfigData != NULL) {
1766fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (IpInfo->IpVersion == IP_VERSION_4){
1767cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1768fb115c61504fe6c4f94be0a87f75e28e1684657ftye      if (((EFI_IP4_CONFIG_DATA *) IpConfigData)->UseDefaultAddress) {
1769fb115c61504fe6c4f94be0a87f75e28e1684657ftye        ((EFI_IP4_PROTOCOL *) Ip)->GetModeData (
1770fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     (EFI_IP4_PROTOCOL *) Ip,
1771fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     &Ip4ModeData,
1772fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     NULL,
1773fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     NULL
1774fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     );
1775cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1776fb115c61504fe6c4f94be0a87f75e28e1684657ftye        ((EFI_IP4_CONFIG_DATA*) IpConfigData)->StationAddress = Ip4ModeData.ConfigData.StationAddress;
1777fb115c61504fe6c4f94be0a87f75e28e1684657ftye        ((EFI_IP4_CONFIG_DATA*) IpConfigData)->SubnetMask     = Ip4ModeData.ConfigData.SubnetMask;
1778cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1779cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1780fb115c61504fe6c4f94be0a87f75e28e1684657ftye      CopyMem (
1781fb115c61504fe6c4f94be0a87f75e28e1684657ftye        &IpInfo->Addr.Addr,
1782fb115c61504fe6c4f94be0a87f75e28e1684657ftye        &((EFI_IP4_CONFIG_DATA *) IpConfigData)->StationAddress,
1783fb115c61504fe6c4f94be0a87f75e28e1684657ftye        sizeof (IP4_ADDR)
1784fb115c61504fe6c4f94be0a87f75e28e1684657ftye        );
1785fb115c61504fe6c4f94be0a87f75e28e1684657ftye      CopyMem (
1786fb115c61504fe6c4f94be0a87f75e28e1684657ftye        &IpInfo->PreMask.SubnetMask,
1787fb115c61504fe6c4f94be0a87f75e28e1684657ftye        &((EFI_IP4_CONFIG_DATA *) IpConfigData)->SubnetMask,
1788fb115c61504fe6c4f94be0a87f75e28e1684657ftye        sizeof (IP4_ADDR)
1789fb115c61504fe6c4f94be0a87f75e28e1684657ftye        );
1790fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1791fb115c61504fe6c4f94be0a87f75e28e1684657ftye      Status = ((EFI_IP4_PROTOCOL *) Ip)->Receive (
1792fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                            (EFI_IP4_PROTOCOL *) Ip,
1793fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                            &IpInfo->DummyRcvToken.Ip4Token
1794fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                            );
1795cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (EFI_ERROR (Status)) {
1796fb115c61504fe6c4f94be0a87f75e28e1684657ftye        ((EFI_IP4_PROTOCOL*)Ip)->Configure (Ip, NULL);
1797cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1798cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  } else {
1799cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1800fb115c61504fe6c4f94be0a87f75e28e1684657ftye      ((EFI_IP6_PROTOCOL *) Ip)->GetModeData (
1801fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                   (EFI_IP6_PROTOCOL *) Ip,
1802fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                   &Ip6ModeData,
1803fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                   NULL,
1804fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                   NULL
1805fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                   );
1806fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1807fb115c61504fe6c4f94be0a87f75e28e1684657ftye      if (Ip6ModeData.IsConfigured) {
1808fb115c61504fe6c4f94be0a87f75e28e1684657ftye        CopyMem (
1809fb115c61504fe6c4f94be0a87f75e28e1684657ftye          &((EFI_IP6_CONFIG_DATA *) IpConfigData)->StationAddress,
1810fb115c61504fe6c4f94be0a87f75e28e1684657ftye          &Ip6ModeData.ConfigData.StationAddress,
1811fb115c61504fe6c4f94be0a87f75e28e1684657ftye          sizeof (EFI_IPv6_ADDRESS)
1812fb115c61504fe6c4f94be0a87f75e28e1684657ftye          );
1813fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1814fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (Ip6ModeData.AddressList != NULL) {
1815fb115c61504fe6c4f94be0a87f75e28e1684657ftye          FreePool (Ip6ModeData.AddressList);
1816fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1817fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1818fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (Ip6ModeData.GroupTable != NULL) {
1819fb115c61504fe6c4f94be0a87f75e28e1684657ftye          FreePool (Ip6ModeData.GroupTable);
1820fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1821fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1822fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (Ip6ModeData.RouteTable != NULL) {
1823fb115c61504fe6c4f94be0a87f75e28e1684657ftye          FreePool (Ip6ModeData.RouteTable);
1824fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1825fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1826fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (Ip6ModeData.NeighborCache != NULL) {
1827fb115c61504fe6c4f94be0a87f75e28e1684657ftye          FreePool (Ip6ModeData.NeighborCache);
1828fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1829fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1830fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (Ip6ModeData.PrefixTable != NULL) {
1831fb115c61504fe6c4f94be0a87f75e28e1684657ftye          FreePool (Ip6ModeData.PrefixTable);
1832fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1833fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1834fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (Ip6ModeData.IcmpTypeList != NULL) {
1835fb115c61504fe6c4f94be0a87f75e28e1684657ftye          FreePool (Ip6ModeData.IcmpTypeList);
1836fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1837fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1838fb115c61504fe6c4f94be0a87f75e28e1684657ftye      } else {
1839fb115c61504fe6c4f94be0a87f75e28e1684657ftye        Status = EFI_NO_MAPPING;
1840fb115c61504fe6c4f94be0a87f75e28e1684657ftye        goto OnExit;
1841fb115c61504fe6c4f94be0a87f75e28e1684657ftye      }
1842fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1843fb115c61504fe6c4f94be0a87f75e28e1684657ftye      CopyMem (
1844fb115c61504fe6c4f94be0a87f75e28e1684657ftye        &IpInfo->Addr,
1845fb115c61504fe6c4f94be0a87f75e28e1684657ftye        &Ip6ModeData.ConfigData.StationAddress,
1846fb115c61504fe6c4f94be0a87f75e28e1684657ftye        sizeof (EFI_IPv6_ADDRESS)
1847fb115c61504fe6c4f94be0a87f75e28e1684657ftye        );
1848fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1849fb115c61504fe6c4f94be0a87f75e28e1684657ftye      Status = ((EFI_IP6_PROTOCOL *) Ip)->Receive (
1850fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                            (EFI_IP6_PROTOCOL *) Ip,
1851fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                            &IpInfo->DummyRcvToken.Ip6Token
1852fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                            );
1853fb115c61504fe6c4f94be0a87f75e28e1684657ftye      if (EFI_ERROR (Status)) {
1854fb115c61504fe6c4f94be0a87f75e28e1684657ftye        ((EFI_IP6_PROTOCOL *) Ip)->Configure ((EFI_IP6_PROTOCOL *) Ip, NULL);
1855fb115c61504fe6c4f94be0a87f75e28e1684657ftye      }
1856fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
1857fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1858cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1859fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // The IP instance is reset, set the stored Addr and SubnetMask to zero.
1860cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1861fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ZeroMem (&IpInfo->Addr, sizeof (IpInfo->Addr));
1862fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ZeroMem (&IpInfo->PreMask, sizeof (IpInfo->PreMask));
1863cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1864cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1865cbf316f20726bb31b7c37424601643790dbd02d9vanjeffOnExit:
1866cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1867cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
1868cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1869cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1870cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1871cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1872cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy an IP instance maintained in IpIo->IpList for
1873cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  sending purpose.
1874e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1875e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function pairs with IpIoAddIp(). The IpInfo is previously created by
1876e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance
1877e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  will be dstroyed if the RefCnt is zero.
1878cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
18796aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  IpIo                  Pointer to the IP_IO instance.
18806aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  IpInfo                Pointer to the IpInfo to be removed.
1881cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1882cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1883cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
18847b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1885cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoRemoveIp (
1886e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IN IP_IO            *IpIo,
1887e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IN IP_IO_IP_INFO    *IpInfo
1888cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1889cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1890fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1891b45b45b2d248892930620c33a9d01d8457ae0e54tye  UINT8               IpVersion;
1892fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1893cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ASSERT (IpInfo->RefCnt > 0);
1894cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1895cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_PUT_REF (IpInfo);
1896cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1897cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo->RefCnt > 0) {
1898cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1899cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return;
1900cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1901cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1902fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpVersion = IpIo->IpVersion;
1903fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1904fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
1905fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1906e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RemoveEntryList (&IpInfo->Entry);
1907cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1908fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4){
1909fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ((EFI_IP4_PROTOCOL *) (IpInfo->Ip))->Configure (
1910fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                           (EFI_IP4_PROTOCOL *) (IpInfo->Ip),
1911fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                           NULL
1912fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                           );
1913fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIoCloseProtocolDestroyIpChild (
1914fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IpIo->Controller,
1915fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IpIo->Image,
1916fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IpInfo->ChildHandle,
1917fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IP_VERSION_4
1918fb115c61504fe6c4f94be0a87f75e28e1684657ftye      );
1919fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1920fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->CloseEvent (IpInfo->DummyRcvToken.Ip4Token.Event);
1921cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1922fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1923cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1924fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ((EFI_IP6_PROTOCOL *) (IpInfo->Ip))->Configure (
1925fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                           (EFI_IP6_PROTOCOL *) (IpInfo->Ip),
1926fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                           NULL
1927fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                           );
1928cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1929fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIoCloseProtocolDestroyIpChild (
1930fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IpIo->Controller,
1931fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IpIo->Image,
1932fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IpInfo->ChildHandle,
1933fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IP_VERSION_6
1934fb115c61504fe6c4f94be0a87f75e28e1684657ftye      );
1935fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1936fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->CloseEvent (IpInfo->DummyRcvToken.Ip6Token.Event);
1937fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1938fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1939fb115c61504fe6c4f94be0a87f75e28e1684657ftye  FreePool (IpInfo);
1940cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1941cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1942cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1943cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1944cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Find the first IP protocol maintained in IpIo whose local
1945fb115c61504fe6c4f94be0a87f75e28e1684657ftye  address is the same as Src.
1946e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1947e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is called when the caller needs the IpIo to send data to the
1948e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  specified Src. The IpIo was added previously by IpIoAddIp().
1949cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
19506aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo              Pointer to the pointer of the IP_IO instance.
1951fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       IpVersion         The version of the IP protocol to use, either
1952fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     IPv4 or IPv6.
19536aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Src               The local IP address.
1954cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1955cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return Pointer to the IP protocol can be used for sending purpose and its local
1956fb115c61504fe6c4f94be0a87f75e28e1684657ftye          address is the same with Src.
1957cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1958cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1959cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_IP_INFO *
19607b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1961cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoFindSender (
1962fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN OUT IP_IO           **IpIo,
1963b45b45b2d248892930620c33a9d01d8457ae0e54tye  IN     UINT8           IpVersion,
1964fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     EFI_IP_ADDRESS  *Src
1965cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1966cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1967e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  LIST_ENTRY      *IpIoEntry;
1968cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO           *IpIoPtr;
1969e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  LIST_ENTRY      *IpInfoEntry;
1970cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO   *IpInfo;
1971cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1972fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
1973fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1974cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_FOR_EACH (IpIoEntry, &mActiveIpIoList) {
1975cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoPtr = NET_LIST_USER_STRUCT (IpIoEntry, IP_IO, Entry);
1976cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1977fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (((*IpIo != NULL) && (*IpIo != IpIoPtr)) || (IpIoPtr->IpVersion != IpVersion)) {
1978cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      continue;
1979cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1980cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1981cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    NET_LIST_FOR_EACH (IpInfoEntry, &IpIoPtr->IpList) {
1982cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IpInfo = NET_LIST_USER_STRUCT (IpInfoEntry, IP_IO_IP_INFO, Entry);
1983fb115c61504fe6c4f94be0a87f75e28e1684657ftye      if (IpInfo->IpVersion == IP_VERSION_4){
1984fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1985fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (EFI_IP4_EQUAL (&IpInfo->Addr.v4, &Src->v4)) {
1986fb115c61504fe6c4f94be0a87f75e28e1684657ftye          *IpIo = IpIoPtr;
1987fb115c61504fe6c4f94be0a87f75e28e1684657ftye          return IpInfo;
1988fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1989fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1990fb115c61504fe6c4f94be0a87f75e28e1684657ftye      } else {
1991fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1992fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (EFI_IP6_EQUAL (&IpInfo->Addr.v6, &Src->v6)) {
1993fb115c61504fe6c4f94be0a87f75e28e1684657ftye          *IpIo = IpIoPtr;
1994fb115c61504fe6c4f94be0a87f75e28e1684657ftye          return IpInfo;
1995fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1996fb115c61504fe6c4f94be0a87f75e28e1684657ftye      }
1997cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1998cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1999cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
2000cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2001cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
2002cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // No match.
2003cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
2004cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
2005cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
2006cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2007cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2008cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
2009e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  Get the ICMP error map information.
2010e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
2011e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  The ErrorStatus will be returned. The IsHard and Notify are optional. If they
2012e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  are not NULL, this routine will fill them.
2013cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
20148f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[in]   IcmpError             IcmpError Type.
2015fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]   IpVersion             The version of the IP protocol to use,
20163b1464d5ac4e8b917c54b9f29a43ad972d2a2c85rsun                                     either IPv4 or IPv6.
20173b1464d5ac4e8b917c54b9f29a43ad972d2a2c85rsun  @param[out]  IsHard                If TRUE, indicates that it is a hard error.
20183b1464d5ac4e8b917c54b9f29a43ad972d2a2c85rsun  @param[out]  Notify                If TRUE, SockError needs to be notified.
2019cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
20206aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @return ICMP Error Status, such as EFI_NETWORK_UNREACHABLE.
2021cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2022cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
2023cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
20247b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
2025cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoGetIcmpErrStatus (
2026b45b45b2d248892930620c33a9d01d8457ae0e54tye  IN  UINT8       IcmpError,
2027b45b45b2d248892930620c33a9d01d8457ae0e54tye  IN  UINT8       IpVersion,
2028e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  OUT BOOLEAN     *IsHard  OPTIONAL,
2029e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  OUT BOOLEAN     *Notify  OPTIONAL
2030cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
2031cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
20323cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  if (IpVersion == IP_VERSION_4 ) {
2033b45b45b2d248892930620c33a9d01d8457ae0e54tye    ASSERT (IcmpError <= ICMP_ERR_PARAMPROB);
2034687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
20353cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    if (IsHard != NULL) {
20363cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      *IsHard = mIcmpErrMap[IcmpError].IsHard;
20373cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    }
2038687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
20393cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    if (Notify != NULL) {
20403cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      *Notify = mIcmpErrMap[IcmpError].Notify;
20413cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    }
20423cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20433cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    switch (IcmpError) {
20443cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_UNREACH_NET:
20453cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return  EFI_NETWORK_UNREACHABLE;
20463cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20473cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_TIMXCEED_INTRANS:
20483cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_TIMXCEED_REASS:
20493cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_UNREACH_HOST:
20503cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return  EFI_HOST_UNREACHABLE;
20513cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20523cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_UNREACH_PROTOCOL:
20533cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return  EFI_PROTOCOL_UNREACHABLE;
20543cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20553cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_UNREACH_PORT:
20563cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return  EFI_PORT_UNREACHABLE;
20573cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20583cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_MSGSIZE:
20593cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_UNREACH_SRCFAIL:
20603cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_QUENCH:
20613cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_PARAMPROB:
20623cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return  EFI_ICMP_ERROR;
20633cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20643cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    default:
20653cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      ASSERT (FALSE);
20663cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_UNSUPPORTED;
20673cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    }
2068687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
2069fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (IpVersion == IP_VERSION_6) {
2070fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2071b45b45b2d248892930620c33a9d01d8457ae0e54tye    ASSERT (IcmpError <= ICMP6_ERR_PARAMPROB_IPV6OPTION);
2072687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
2073fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (IsHard != NULL) {
2074fb115c61504fe6c4f94be0a87f75e28e1684657ftye      *IsHard = mIcmp6ErrMap[IcmpError].IsHard;
2075fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
2076fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2077fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (Notify != NULL) {
2078fb115c61504fe6c4f94be0a87f75e28e1684657ftye      *Notify = mIcmp6ErrMap[IcmpError].Notify;
2079fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
20803cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20813cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    switch (IcmpError) {
20823cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_UNREACH_NET:
20833cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_NETWORK_UNREACHABLE;
20843cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20853cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_UNREACH_HOST:
20863cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_TIMXCEED_HOPLIMIT:
20873cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_TIMXCEED_REASS:
20883cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_HOST_UNREACHABLE;
20893cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20903cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_UNREACH_PROTOCOL:
20913cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_PROTOCOL_UNREACHABLE;
20923cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20933cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_UNREACH_PORT:
20943cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_PORT_UNREACHABLE;
20953cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20963cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_PACKAGE_TOOBIG:
20973cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_PARAMPROB_HEADER:
20983cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_PARAMPROB_NEXHEADER:
20993cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_PARAMPROB_IPV6OPTION:
21003cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_ICMP_ERROR;
21013cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
21023cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    default:
21033cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      ASSERT (FALSE);
21043cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_UNSUPPORTED;
21053cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    }
2106fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2107fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
2108fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
2109fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // Should never be here
2110fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
2111fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ASSERT (FALSE);
2112fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return EFI_UNSUPPORTED;
2113fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
2114fb115c61504fe6c4f94be0a87f75e28e1684657ftye}
2115cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2116cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2117fb115c61504fe6c4f94be0a87f75e28e1684657ftye/**
2118fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Refresh the remote peer's Neighbor Cache entries.
2119fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2120fb115c61504fe6c4f94be0a87f75e28e1684657ftye  This function is called when the caller needs the IpIo to refresh the existing
2121fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IPv6 neighbor cache entries since the neighbor is considered reachable by the
2122fb115c61504fe6c4f94be0a87f75e28e1684657ftye  node has recently received a confirmation that packets sent recently to the
2123fb115c61504fe6c4f94be0a87f75e28e1684657ftye  neighbor were received by its IP layer.
2124fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2125fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]   IpIo                  Pointer to an IP_IO instance
2126fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]   Neighbor              The IP address of the neighbor
2127fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]   Timeout               Time in 100-ns units that this entry will
2128fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     remain in the neighbor cache. A value of
2129fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     zero means that the entry is permanent.
2130fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     A value of non-zero means that the entry is
2131fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     dynamic and will be deleted after Timeout.
2132fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2133fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval      EFI_SUCCESS           The operation is completed successfully.
2134fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval      EFI_NOT_STARTED       The IpIo is not configured.
2135fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval      EFI_INVALID_PARAMETER Neighbor Address is invalid.
2136fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval      EFI_NOT_FOUND         The neighbor cache entry is not in the
2137fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     neighbor table.
2138fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval      EFI_OUT_OF_RESOURCES  Failed due to resource limit.
2139cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2140fb115c61504fe6c4f94be0a87f75e28e1684657ftye**/
2141fb115c61504fe6c4f94be0a87f75e28e1684657ftyeEFI_STATUS
2142fb115c61504fe6c4f94be0a87f75e28e1684657ftyeIpIoRefreshNeighbor (
2143fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN IP_IO           *IpIo,
2144fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN EFI_IP_ADDRESS  *Neighbor,
2145fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN UINT32          Timeout
2146fb115c61504fe6c4f94be0a87f75e28e1684657ftye  )
2147fb115c61504fe6c4f94be0a87f75e28e1684657ftye{
2148fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_IP6_PROTOCOL  *Ip;
2149fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2150fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (!IpIo->IsConfigured || IpIo->IpVersion != IP_VERSION_6) {
2151fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return EFI_NOT_STARTED;
2152cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
2153cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2154fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Ip = (EFI_IP6_PROTOCOL *) (IpIo->Ip);
2155fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2156fb115c61504fe6c4f94be0a87f75e28e1684657ftye  return Ip->Neighbors (Ip, FALSE, &Neighbor->v6, NULL, Timeout, TRUE);
2157cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
2158cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2159