1cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/** @file
26aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IpIo Library.
3cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
435f910f08b58e978bc9251872635075d6f422e48Randy Pawell(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
5cd5ebaa06dca3e6ef3c464081e6defe00d358c69hhtianCopyright (c) 2005 - 2009, Intel Corporation. All rights reserved.<BR>
6cd5ebaa06dca3e6ef3c464081e6defe00d358c69hhtianThis program and the accompanying materials
7cbf316f20726bb31b7c37424601643790dbd02d9vanjeffare licensed and made available under the terms and conditions of the BSD License
8cbf316f20726bb31b7c37424601643790dbd02d9vanjeffwhich accompanies this distribution.  The full text of the license may be found at
9cbf316f20726bb31b7c37424601643790dbd02d9vanjeffhttp://opensource.org/licenses/bsd-license.php
10cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
11cbf316f20726bb31b7c37424601643790dbd02d9vanjeffTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12cbf316f20726bb31b7c37424601643790dbd02d9vanjeffWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
14cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
156aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu#include <Uefi.h>
16cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
17cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Protocol/Udp4.h>
18cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
19cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/IpIoLib.h>
20cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/BaseLib.h>
21cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/DebugLib.h>
22752ef5d80c099b1d33bf25f62f36289dac47d83cmdkinney#include <Library/BaseMemoryLib.h>
23cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/UefiBootServicesTableLib.h>
24752ef5d80c099b1d33bf25f62f36289dac47d83cmdkinney#include <Library/MemoryAllocationLib.h>
25d8d26fb207e02aa5ef57e2bcb213f9dda16166ccmdkinney#include <Library/DpcLib.h>
26cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
27cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
281204fe8319e5e6f77df68c375ef403e9ffa9227exduGLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY  mActiveIpIoList = {
29cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  &mActiveIpIoList,
30cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  &mActiveIpIoList
31cbf316f20726bb31b7c37424601643790dbd02d9vanjeff};
32cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
331204fe8319e5e6f77df68c375ef403e9ffa9227exduGLOBAL_REMOVE_IF_UNREFERENCED EFI_IP4_CONFIG_DATA  mIp4IoDefaultIpConfigData = {
34cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP_PROTO_UDP,
35cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
36cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TRUE,
37cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
38cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
39cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
4084b5c78e89686879f799a4cd095eeef83ff7cf34qwang  {{0, 0, 0, 0}},
4184b5c78e89686879f799a4cd095eeef83ff7cf34qwang  {{0, 0, 0, 0}},
42cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0,
43cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  255,
44cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
45cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
46cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0,
47cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0
48cbf316f20726bb31b7c37424601643790dbd02d9vanjeff};
49cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
501204fe8319e5e6f77df68c375ef403e9ffa9227exduGLOBAL_REMOVE_IF_UNREFERENCED EFI_IP6_CONFIG_DATA  mIp6IoDefaultIpConfigData = {
51fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_IP_PROTO_UDP,
52fb115c61504fe6c4f94be0a87f75e28e1684657ftye  FALSE,
53fb115c61504fe6c4f94be0a87f75e28e1684657ftye  TRUE,
54fb115c61504fe6c4f94be0a87f75e28e1684657ftye  FALSE,
55fb115c61504fe6c4f94be0a87f75e28e1684657ftye  {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
56fb115c61504fe6c4f94be0a87f75e28e1684657ftye  {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
57fb115c61504fe6c4f94be0a87f75e28e1684657ftye  0,
58fb115c61504fe6c4f94be0a87f75e28e1684657ftye  255,
59fb115c61504fe6c4f94be0a87f75e28e1684657ftye  0,
60fb115c61504fe6c4f94be0a87f75e28e1684657ftye  0,
61fb115c61504fe6c4f94be0a87f75e28e1684657ftye  0
62fb115c61504fe6c4f94be0a87f75e28e1684657ftye};
63fb115c61504fe6c4f94be0a87f75e28e1684657ftye
641204fe8319e5e6f77df68c375ef403e9ffa9227exduGLOBAL_REMOVE_IF_UNREFERENCED ICMP_ERROR_INFO  mIcmpErrMap[10] = {
653cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE }, // ICMP_ERR_UNREACH_NET
663cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE }, // ICMP_ERR_UNREACH_HOST
673cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {TRUE,  TRUE }, // ICMP_ERR_UNREACH_PROTOCOL
683cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {TRUE,  TRUE }, // ICMP_ERR_UNREACH_PORT
693cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {TRUE,  TRUE }, // ICMP_ERR_MSGSIZE
703cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE }, // ICMP_ERR_UNREACH_SRCFAIL
713cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE }, // ICMP_ERR_TIMXCEED_INTRANS
723cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE }, // ICMP_ERR_TIMEXCEED_REASS
733cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, FALSE}, // ICMP_ERR_QUENCH
743cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE }  // ICMP_ERR_PARAMPROB
75fb115c61504fe6c4f94be0a87f75e28e1684657ftye};
76fb115c61504fe6c4f94be0a87f75e28e1684657ftye
771204fe8319e5e6f77df68c375ef403e9ffa9227exduGLOBAL_REMOVE_IF_UNREFERENCED ICMP_ERROR_INFO  mIcmp6ErrMap[10] = {
783cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}, // ICMP6_ERR_UNREACH_NET
793cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}, // ICMP6_ERR_UNREACH_HOST
803cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {TRUE,  TRUE}, // ICMP6_ERR_UNREACH_PROTOCOL
813cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {TRUE,  TRUE}, // ICMP6_ERR_UNREACH_PORT
823cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {TRUE,  TRUE}, // ICMP6_ERR_PACKAGE_TOOBIG
833cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}, // ICMP6_ERR_TIMXCEED_HOPLIMIT
843cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}, // ICMP6_ERR_TIMXCEED_REASS
853cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}, // ICMP6_ERR_PARAMPROB_HEADER
863cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}, // ICMP6_ERR_PARAMPROB_NEXHEADER
873cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  {FALSE, TRUE}  // ICMP6_ERR_PARAMPROB_IPV6OPTION
8801750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff};
8901750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff
906aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
916aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu/**
926aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  Notify function for IP transmit token.
936aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
946aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
956aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
966aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu**/
97cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
98cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
9936ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoTransmitHandlerDpc (
10036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
10136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  );
10236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
1036aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
1046aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu/**
1056aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  Notify function for IP transmit token.
1066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
1076aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event signaled.
1086aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
1096aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
1106aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu**/
11136ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
11236ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
113cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoTransmitHandler (
114cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_EVENT Event,
115cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
116cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  );
117cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
118cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
119cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1206aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  This function create an IP child ,open the IP protocol, and return the opened
121e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IP protocol as Interface.
122cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1236aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]    ControllerHandle   The controller handle.
1246aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]    ImageHandle        The image handle.
1256aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]    ChildHandle        Pointer to the buffer to save the IP child handle.
126fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]    IpVersion          The version of the IP protocol to use, either
127fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                   IPv4 or IPv6.
1286aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[out]   Interface          Pointer used to get the IP protocol interface.
129cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1306aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval       EFI_SUCCESS        The IP child is created and the IP protocol
1316aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   interface is retrieved.
1326aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval       Others             The required operation failed.
133cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
134cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
135cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
136cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreateIpChildOpenProtocol (
137cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  ControllerHandle,
138cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  ImageHandle,
139cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  *ChildHandle,
140b45b45b2d248892930620c33a9d01d8457ae0e54tye  IN  UINT8       IpVersion,
141cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  OUT VOID        **Interface
142cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
143cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
144cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
145fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_GUID    *ServiceBindingGuid;
146fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_GUID    *IpProtocolGuid;
147fb115c61504fe6c4f94be0a87f75e28e1684657ftye
148fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4) {
149fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;
150fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpProtocolGuid     = &gEfiIp4ProtocolGuid;
151fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (IpVersion == IP_VERSION_6){
152fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;
153fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpProtocolGuid     = &gEfiIp6ProtocolGuid;
154fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
155fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return EFI_UNSUPPORTED;
156fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
157cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
158cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1596aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Create an IP child.
160cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
161cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = NetLibCreateServiceChild (
162cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ControllerHandle,
163cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ImageHandle,
164fb115c61504fe6c4f94be0a87f75e28e1684657ftye             ServiceBindingGuid,
165cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ChildHandle
166cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
167cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
168cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
169cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
170cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
171cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1726aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Open the IP protocol installed on the *ChildHandle.
173cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
174cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->OpenProtocol (
175cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  *ChildHandle,
176fb115c61504fe6c4f94be0a87f75e28e1684657ftye                  IpProtocolGuid,
177cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  Interface,
178cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  ImageHandle,
179cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  ControllerHandle,
180cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EFI_OPEN_PROTOCOL_BY_DRIVER
181cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
182cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
183cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1846aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // On failure, destroy the IP child.
185cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
186cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    NetLibDestroyServiceChild (
187cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      ControllerHandle,
188cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      ImageHandle,
189fb115c61504fe6c4f94be0a87f75e28e1684657ftye      ServiceBindingGuid,
190cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      *ChildHandle
191cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      );
192cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
193cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
194cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
195cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
196cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
197cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
198cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
199e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function close the previously openned IP protocol and destroy the IP child.
200cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2016aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  ControllerHandle    The controller handle.
2026aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  ImageHandle         The image handle.
2036aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  ChildHandle         The child handle of the IP child.
204fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]  IpVersion           The version of the IP protocol to use, either
205fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                  IPv4 or IPv6.
206cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2076aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval     EFI_SUCCESS         The IP protocol is closed and the relevant IP child
2086aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                  is destroyed.
2096aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval     Others              The required operation failed.
210cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
211cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
212cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
213cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCloseProtocolDestroyIpChild (
214cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ControllerHandle,
215cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ImageHandle,
216fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN EFI_HANDLE  ChildHandle,
217b45b45b2d248892930620c33a9d01d8457ae0e54tye  IN UINT8       IpVersion
218cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
219cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
220cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
221fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_GUID    *ServiceBindingGuid;
222fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_GUID    *IpProtocolGuid;
223fb115c61504fe6c4f94be0a87f75e28e1684657ftye
224fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4) {
225fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;
226fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpProtocolGuid     = &gEfiIp4ProtocolGuid;
227fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (IpVersion == IP_VERSION_6) {
228fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;
229fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpProtocolGuid     = &gEfiIp6ProtocolGuid;
230fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
231fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return EFI_UNSUPPORTED;
232fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
233cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
234cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
2356aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Close the previously openned IP protocol.
236cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
237cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseProtocol (
238cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ChildHandle,
239fb115c61504fe6c4f94be0a87f75e28e1684657ftye         IpProtocolGuid,
240cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ImageHandle,
241cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ControllerHandle
242cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         );
243cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
244cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
2456aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Destroy the IP child.
246cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
247cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = NetLibDestroyServiceChild (
248cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ControllerHandle,
249cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ImageHandle,
250fb115c61504fe6c4f94be0a87f75e28e1684657ftye             ServiceBindingGuid,
251cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ChildHandle
252cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
253cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
254cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
255cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
256cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
257cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
258fb115c61504fe6c4f94be0a87f75e28e1684657ftye  This function handles ICMPv4 packets. It is the worker function of
259fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpIoIcmpHandler.
260cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
261fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       IpIo            Pointer to the IP_IO instance.
262fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in, out]  Pkt             Pointer to the ICMPv4 packet.
263fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       Session         Pointer to the net session of this ICMPv4 packet.
264cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
265fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_SUCCESS     The ICMPv4 packet is handled successfully.
266fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_ABORTED     This type of ICMPv4 packet is not supported.
267cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
268cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
269cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
270fb115c61504fe6c4f94be0a87f75e28e1684657ftyeIpIoIcmpv4Handler (
2716aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO                *IpIo,
2726aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT NET_BUF              *Pkt,
2736aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     EFI_NET_SESSION_DATA *Session
274cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
275cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
276cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP4_ICMP_ERROR_HEAD  *IcmpHdr;
277cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_HEADER       *IpHdr;
278b45b45b2d248892930620c33a9d01d8457ae0e54tye  UINT8                IcmpErr;
279cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                *PayLoadHdr;
280cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                Type;
281cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                Code;
282cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT32               TrimBytes;
283cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
284fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT (IpIo->IpVersion == IP_VERSION_4);
285fb115c61504fe6c4f94be0a87f75e28e1684657ftye
286cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IcmpHdr = NET_PROTO_HDR (Pkt, IP4_ICMP_ERROR_HEAD);
287cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpHdr   = (EFI_IP4_HEADER *) (&IcmpHdr->IpHead);
288cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
289cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
290cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Check the ICMP packet length.
291cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
292cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (Pkt->TotalSize < ICMP_ERRLEN (IpHdr)) {
293cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
294cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ABORTED;
295cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
296cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
297cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Type = IcmpHdr->Head.Type;
298cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Code = IcmpHdr->Head.Code;
299cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
300cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
301cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Analyze the ICMP Error in this ICMP pkt
302cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
303cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  switch (Type) {
304cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_UNREACH:
305cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    switch (Code) {
306cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET:
307cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST:
308cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_PROTOCOL:
309cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_PORT:
310cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_SRCFAIL:
311b45b45b2d248892930620c33a9d01d8457ae0e54tye      IcmpErr = (UINT8) (ICMP_ERR_UNREACH_NET + Code);
312cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
313cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
314cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
315cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NEEDFRAG:
316cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_MSGSIZE;
317cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
318cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
319cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
320cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET_UNKNOWN:
321cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET_PROHIB:
322cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_TOSNET:
323cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_UNREACH_NET;
324cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
325cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
326cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
327cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST_UNKNOWN:
328cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_ISOLATED:
329cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST_PROHIB:
330cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_TOSHOST:
331cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_UNREACH_HOST;
332cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
333cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
334cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
335cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    default:
336cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
337cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
338cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
339cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
340cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
341cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_TIMXCEED:
342cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code > 1) {
343cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
344cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
345cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
346b45b45b2d248892930620c33a9d01d8457ae0e54tye    IcmpErr = (UINT8) (Code + ICMP_ERR_TIMXCEED_INTRANS);
347cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
348cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
349cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
350cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_PARAMPROB:
351cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code > 1) {
352cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
353cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
354cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
355cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IcmpErr = ICMP_ERR_PARAMPROB;
356cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
357cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
358cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
359cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_SOURCEQUENCH:
360cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code != 0) {
361cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
362cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
363cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
364cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IcmpErr = ICMP_ERR_QUENCH;
365cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
366cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
367cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
368cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  default:
369cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ABORTED;
370cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
371cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
372cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
373cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Notify user the ICMP pkt only containing payload except
374cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // IP and ICMP header
375cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
376cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  PayLoadHdr = (UINT8 *) ((UINT8 *) IpHdr + EFI_IP4_HEADER_LEN (IpHdr));
377cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TrimBytes  = (UINT32) (PayLoadHdr - (UINT8 *) IcmpHdr);
378cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
379cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetbufTrim (Pkt, TrimBytes, TRUE);
380cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
381cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);
382cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
383fb115c61504fe6c4f94be0a87f75e28e1684657ftye  return EFI_SUCCESS;
384fb115c61504fe6c4f94be0a87f75e28e1684657ftye}
385fb115c61504fe6c4f94be0a87f75e28e1684657ftye
386fb115c61504fe6c4f94be0a87f75e28e1684657ftye/**
387fb115c61504fe6c4f94be0a87f75e28e1684657ftye  This function handles ICMPv6 packets. It is the worker function of
388fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpIoIcmpHandler.
389fb115c61504fe6c4f94be0a87f75e28e1684657ftye
390fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       IpIo            Pointer to the IP_IO instance.
391fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in, out]  Pkt             Pointer to the ICMPv6 packet.
392fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       Session         Pointer to the net session of this ICMPv6 packet.
393fb115c61504fe6c4f94be0a87f75e28e1684657ftye
394fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_SUCCESS     The ICMPv6 packet is handled successfully.
395fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_ABORTED     This type of ICMPv6 packet is not supported.
396fb115c61504fe6c4f94be0a87f75e28e1684657ftye
397fb115c61504fe6c4f94be0a87f75e28e1684657ftye**/
398fb115c61504fe6c4f94be0a87f75e28e1684657ftyeEFI_STATUS
399fb115c61504fe6c4f94be0a87f75e28e1684657ftyeIpIoIcmpv6Handler (
400fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     IP_IO                *IpIo,
401fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN OUT NET_BUF              *Pkt,
402fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     EFI_NET_SESSION_DATA *Session
403fb115c61504fe6c4f94be0a87f75e28e1684657ftye  )
404fb115c61504fe6c4f94be0a87f75e28e1684657ftye{
405fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IP6_ICMP_ERROR_HEAD  *IcmpHdr;
406fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_IP6_HEADER       *IpHdr;
407b45b45b2d248892930620c33a9d01d8457ae0e54tye  UINT8                IcmpErr;
408fb115c61504fe6c4f94be0a87f75e28e1684657ftye  UINT8                *PayLoadHdr;
409fb115c61504fe6c4f94be0a87f75e28e1684657ftye  UINT8                Type;
410fb115c61504fe6c4f94be0a87f75e28e1684657ftye  UINT8                Code;
411fb115c61504fe6c4f94be0a87f75e28e1684657ftye  UINT8                NextHeader;
412fb115c61504fe6c4f94be0a87f75e28e1684657ftye  UINT32               TrimBytes;
413fb115c61504fe6c4f94be0a87f75e28e1684657ftye  BOOLEAN              Flag;
414fb115c61504fe6c4f94be0a87f75e28e1684657ftye
415fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT (IpIo->IpVersion == IP_VERSION_6);
416fb115c61504fe6c4f94be0a87f75e28e1684657ftye
417fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
418fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Check the ICMPv6 packet length.
419fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
420fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (Pkt->TotalSize < sizeof (IP6_ICMP_ERROR_HEAD)) {
421fb115c61504fe6c4f94be0a87f75e28e1684657ftye
422fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return EFI_ABORTED;
423fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
424fb115c61504fe6c4f94be0a87f75e28e1684657ftye
425fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IcmpHdr = NET_PROTO_HDR (Pkt, IP6_ICMP_ERROR_HEAD);
426fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Type    = IcmpHdr->Head.Type;
427fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Code    = IcmpHdr->Head.Code;
428fb115c61504fe6c4f94be0a87f75e28e1684657ftye
429fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
430fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Analyze the ICMPv6 Error in this ICMPv6 packet
431fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
432fb115c61504fe6c4f94be0a87f75e28e1684657ftye  switch (Type) {
433fb115c61504fe6c4f94be0a87f75e28e1684657ftye  case ICMP_V6_DEST_UNREACHABLE:
434fb115c61504fe6c4f94be0a87f75e28e1684657ftye    switch (Code) {
435fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_NO_ROUTE_TO_DEST:
436fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_BEYOND_SCOPE:
437fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_ROUTE_REJECTED:
438fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IcmpErr = ICMP6_ERR_UNREACH_NET;
439fb115c61504fe6c4f94be0a87f75e28e1684657ftye
440fb115c61504fe6c4f94be0a87f75e28e1684657ftye      break;
441fb115c61504fe6c4f94be0a87f75e28e1684657ftye
442fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_COMM_PROHIBITED:
443fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_ADDR_UNREACHABLE:
444fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_SOURCE_ADDR_FAILED:
445fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IcmpErr = ICMP6_ERR_UNREACH_HOST;
446fb115c61504fe6c4f94be0a87f75e28e1684657ftye
447fb115c61504fe6c4f94be0a87f75e28e1684657ftye      break;
448fb115c61504fe6c4f94be0a87f75e28e1684657ftye
449fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case ICMP_V6_PORT_UNREACHABLE:
450fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IcmpErr = ICMP6_ERR_UNREACH_PORT;
451fb115c61504fe6c4f94be0a87f75e28e1684657ftye
452fb115c61504fe6c4f94be0a87f75e28e1684657ftye      break;
453fb115c61504fe6c4f94be0a87f75e28e1684657ftye
454fb115c61504fe6c4f94be0a87f75e28e1684657ftye     default:
455fb115c61504fe6c4f94be0a87f75e28e1684657ftye      return EFI_ABORTED;
456fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
457fb115c61504fe6c4f94be0a87f75e28e1684657ftye
458fb115c61504fe6c4f94be0a87f75e28e1684657ftye    break;
459fb115c61504fe6c4f94be0a87f75e28e1684657ftye
460fb115c61504fe6c4f94be0a87f75e28e1684657ftye  case ICMP_V6_PACKET_TOO_BIG:
461fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (Code >= 1) {
462fb115c61504fe6c4f94be0a87f75e28e1684657ftye      return EFI_ABORTED;
463fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
464fb115c61504fe6c4f94be0a87f75e28e1684657ftye
465fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IcmpErr = ICMP6_ERR_PACKAGE_TOOBIG;
466fb115c61504fe6c4f94be0a87f75e28e1684657ftye
467fb115c61504fe6c4f94be0a87f75e28e1684657ftye    break;
468fb115c61504fe6c4f94be0a87f75e28e1684657ftye
469fb115c61504fe6c4f94be0a87f75e28e1684657ftye  case ICMP_V6_TIME_EXCEEDED:
470fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (Code > 1) {
471fb115c61504fe6c4f94be0a87f75e28e1684657ftye      return EFI_ABORTED;
472fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
473fb115c61504fe6c4f94be0a87f75e28e1684657ftye
474b45b45b2d248892930620c33a9d01d8457ae0e54tye    IcmpErr = (UINT8) (ICMP6_ERR_TIMXCEED_HOPLIMIT + Code);
475fb115c61504fe6c4f94be0a87f75e28e1684657ftye
476fb115c61504fe6c4f94be0a87f75e28e1684657ftye    break;
477fb115c61504fe6c4f94be0a87f75e28e1684657ftye
478fb115c61504fe6c4f94be0a87f75e28e1684657ftye  case ICMP_V6_PARAMETER_PROBLEM:
479fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (Code > 3) {
480fb115c61504fe6c4f94be0a87f75e28e1684657ftye      return EFI_ABORTED;
481fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
482fb115c61504fe6c4f94be0a87f75e28e1684657ftye
483b45b45b2d248892930620c33a9d01d8457ae0e54tye    IcmpErr = (UINT8) (ICMP6_ERR_PARAMPROB_HEADER + Code);
484fb115c61504fe6c4f94be0a87f75e28e1684657ftye
485fb115c61504fe6c4f94be0a87f75e28e1684657ftye    break;
486fb115c61504fe6c4f94be0a87f75e28e1684657ftye
487fb115c61504fe6c4f94be0a87f75e28e1684657ftye   default:
488fb115c61504fe6c4f94be0a87f75e28e1684657ftye
489fb115c61504fe6c4f94be0a87f75e28e1684657ftye     return EFI_ABORTED;
490fb115c61504fe6c4f94be0a87f75e28e1684657ftye   }
491fb115c61504fe6c4f94be0a87f75e28e1684657ftye
492fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
493fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Notify user the ICMPv6 packet only containing payload except
494fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // IPv6 basic header, extension header and ICMP header
495fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
496fb115c61504fe6c4f94be0a87f75e28e1684657ftye
497fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpHdr      = (EFI_IP6_HEADER *) (&IcmpHdr->IpHead);
498fb115c61504fe6c4f94be0a87f75e28e1684657ftye  NextHeader = IpHdr->NextHeader;
499fb115c61504fe6c4f94be0a87f75e28e1684657ftye  PayLoadHdr = (UINT8 *) ((UINT8 *) IcmpHdr + sizeof (IP6_ICMP_ERROR_HEAD));
500fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Flag       = TRUE;
501fb115c61504fe6c4f94be0a87f75e28e1684657ftye
502fb115c61504fe6c4f94be0a87f75e28e1684657ftye  do {
503fb115c61504fe6c4f94be0a87f75e28e1684657ftye    switch (NextHeader) {
504fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case EFI_IP_PROTO_UDP:
505fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case EFI_IP_PROTO_TCP:
506fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case EFI_IP_PROTO_ICMP:
507fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case IP6_NO_NEXT_HEADER:
508fb115c61504fe6c4f94be0a87f75e28e1684657ftye      Flag = FALSE;
509fb115c61504fe6c4f94be0a87f75e28e1684657ftye
510fb115c61504fe6c4f94be0a87f75e28e1684657ftye      break;
511fb115c61504fe6c4f94be0a87f75e28e1684657ftye
512fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case IP6_HOP_BY_HOP:
513fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case IP6_DESTINATION:
514fb115c61504fe6c4f94be0a87f75e28e1684657ftye      //
515fb115c61504fe6c4f94be0a87f75e28e1684657ftye      // The Hdr Ext Len is 8-bit unsigned integer in 8-octet units, not including
516fb115c61504fe6c4f94be0a87f75e28e1684657ftye      // the first 8 octets.
517fb115c61504fe6c4f94be0a87f75e28e1684657ftye      //
518fb115c61504fe6c4f94be0a87f75e28e1684657ftye      NextHeader = *(PayLoadHdr);
519fb115c61504fe6c4f94be0a87f75e28e1684657ftye      PayLoadHdr = (UINT8 *) (PayLoadHdr + (*(PayLoadHdr + 1) + 1) * 8);
520fb115c61504fe6c4f94be0a87f75e28e1684657ftye
521fb115c61504fe6c4f94be0a87f75e28e1684657ftye      break;
522fb115c61504fe6c4f94be0a87f75e28e1684657ftye
523fb115c61504fe6c4f94be0a87f75e28e1684657ftye    case IP6_FRAGMENT:
524fb115c61504fe6c4f94be0a87f75e28e1684657ftye      //
525fb115c61504fe6c4f94be0a87f75e28e1684657ftye      // The Fragment Header Length is 8 octets.
526fb115c61504fe6c4f94be0a87f75e28e1684657ftye      //
527fb115c61504fe6c4f94be0a87f75e28e1684657ftye      NextHeader = *(PayLoadHdr);
528fb115c61504fe6c4f94be0a87f75e28e1684657ftye      PayLoadHdr = (UINT8 *) (PayLoadHdr + 8);
529fb115c61504fe6c4f94be0a87f75e28e1684657ftye
530fb115c61504fe6c4f94be0a87f75e28e1684657ftye      break;
531fb115c61504fe6c4f94be0a87f75e28e1684657ftye
532fb115c61504fe6c4f94be0a87f75e28e1684657ftye    default:
533fb115c61504fe6c4f94be0a87f75e28e1684657ftye
534fb115c61504fe6c4f94be0a87f75e28e1684657ftye      return EFI_ABORTED;
535fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
536fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } while (Flag);
537fb115c61504fe6c4f94be0a87f75e28e1684657ftye
538fb115c61504fe6c4f94be0a87f75e28e1684657ftye  TrimBytes = (UINT32) (PayLoadHdr - (UINT8 *) IcmpHdr);
539fb115c61504fe6c4f94be0a87f75e28e1684657ftye
540fb115c61504fe6c4f94be0a87f75e28e1684657ftye  NetbufTrim (Pkt, TrimBytes, TRUE);
541fb115c61504fe6c4f94be0a87f75e28e1684657ftye
542b45b45b2d248892930620c33a9d01d8457ae0e54tye  IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);
543fb115c61504fe6c4f94be0a87f75e28e1684657ftye
544cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
545cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
546cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
547fb115c61504fe6c4f94be0a87f75e28e1684657ftye/**
548fb115c61504fe6c4f94be0a87f75e28e1684657ftye  This function handles ICMP packets.
549fb115c61504fe6c4f94be0a87f75e28e1684657ftye
550fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       IpIo            Pointer to the IP_IO instance.
551fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in, out]  Pkt             Pointer to the ICMP packet.
552fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       Session         Pointer to the net session of this ICMP packet.
553fb115c61504fe6c4f94be0a87f75e28e1684657ftye
554fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_SUCCESS     The ICMP packet is handled successfully.
555fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_ABORTED     This type of ICMP packet is not supported.
556fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval          EFI_UNSUPPORTED The IP protocol version in IP_IO is not supported.
557fb115c61504fe6c4f94be0a87f75e28e1684657ftye
558fb115c61504fe6c4f94be0a87f75e28e1684657ftye**/
559fb115c61504fe6c4f94be0a87f75e28e1684657ftyeEFI_STATUS
560fb115c61504fe6c4f94be0a87f75e28e1684657ftyeIpIoIcmpHandler (
561fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     IP_IO                *IpIo,
562fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN OUT NET_BUF              *Pkt,
563fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     EFI_NET_SESSION_DATA *Session
564fb115c61504fe6c4f94be0a87f75e28e1684657ftye  )
565fb115c61504fe6c4f94be0a87f75e28e1684657ftye{
566fb115c61504fe6c4f94be0a87f75e28e1684657ftye
567fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4) {
568fb115c61504fe6c4f94be0a87f75e28e1684657ftye
569fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return IpIoIcmpv4Handler (IpIo, Pkt, Session);
570fb115c61504fe6c4f94be0a87f75e28e1684657ftye
571fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (IpIo->IpVersion == IP_VERSION_6) {
572fb115c61504fe6c4f94be0a87f75e28e1684657ftye
573fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return IpIoIcmpv6Handler (IpIo, Pkt, Session);
574fb115c61504fe6c4f94be0a87f75e28e1684657ftye
575fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
576fb115c61504fe6c4f94be0a87f75e28e1684657ftye
577fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return EFI_UNSUPPORTED;
578fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
579fb115c61504fe6c4f94be0a87f75e28e1684657ftye}
580fb115c61504fe6c4f94be0a87f75e28e1684657ftye
581cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
582cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
583e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  Free function for receive token of IP_IO. It is used to
584cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  signal the recycle event to notify IP to recycle the
585cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  data buffer.
586cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
5876aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event to be signaled.
588cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
589cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
590cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
591e798cd87ca9a3a30c4cea50c5f5de84e10a8bc5ageekboyEFIAPI
592cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoExtFree (
593cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID  *Event
594cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
595cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
596cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->SignalEvent ((EFI_EVENT) Event);
597cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
598cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
599cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
600cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
601cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Create a send entry to wrap a packet before sending
602cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  out it through IP.
603cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
6046aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo                 Pointer to the IP_IO instance.
6056aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  Pkt                  Pointer to the packet.
6066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Sender               Pointer to the IP sender.
6076aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Context              Pointer to the context.
6086aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       NotifyData           Pointer to the notify data.
6096aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Dest                 Pointer to the destination IP address.
6106aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Override             Pointer to the overriden IP_IO data.
611cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
612cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return Pointer to the data structure created to wrap the packet. If NULL,
6136aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @return resource limit occurred.
614cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
615cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
616cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_SEND_ENTRY *
617cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreateSndEntry (
6186aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO             *IpIo,
6196aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT NET_BUF           *Pkt,
6202a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang  IN     IP_IO_IP_PROTOCOL Sender,
6216aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID              *Context    OPTIONAL,
6226aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID              *NotifyData OPTIONAL,
623fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     EFI_IP_ADDRESS    *Dest       OPTIONAL,
6246aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_OVERRIDE    *Override
625cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
626cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
627cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY          *SndEntry;
628fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_EVENT                 Event;
629cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS                Status;
630fb115c61504fe6c4f94be0a87f75e28e1684657ftye  NET_FRAGMENT              *ExtFragment;
631fb115c61504fe6c4f94be0a87f75e28e1684657ftye  UINT32                    FragmentCount;
632fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IP_IO_OVERRIDE            *OverrideData;
633fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IP_IO_IP_TX_DATA          *TxData;
634fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_IP4_TRANSMIT_DATA     *Ip4TxData;
635fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_IP6_TRANSMIT_DATA     *Ip6TxData;
636fb115c61504fe6c4f94be0a87f75e28e1684657ftye
637fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if ((IpIo->IpVersion != IP_VERSION_4) && (IpIo->IpVersion != IP_VERSION_6)) {
638fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return NULL;
639fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
640fb115c61504fe6c4f94be0a87f75e28e1684657ftye
641fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Event        = NULL;
642fb115c61504fe6c4f94be0a87f75e28e1684657ftye  TxData       = NULL;
643fb115c61504fe6c4f94be0a87f75e28e1684657ftye  OverrideData = NULL;
644cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
645cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
646cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for SndEntry
647cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
648e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  SndEntry = AllocatePool (sizeof (IP_IO_SEND_ENTRY));
649cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndEntry) {
650cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return NULL;
651cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
652cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
653cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
654cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
655e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
656cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoTransmitHandler,
657cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  SndEntry,
658fb115c61504fe6c4f94be0a87f75e28e1684657ftye                  &Event
659cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
660cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
661fb115c61504fe6c4f94be0a87f75e28e1684657ftye    goto ON_ERROR;
662cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
663cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
664fb115c61504fe6c4f94be0a87f75e28e1684657ftye  FragmentCount = Pkt->BlockOpNum;
665fb115c61504fe6c4f94be0a87f75e28e1684657ftye
666cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
667cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for TxData
668cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
669fb115c61504fe6c4f94be0a87f75e28e1684657ftye  TxData = (IP_IO_IP_TX_DATA *) AllocatePool (
670fb115c61504fe6c4f94be0a87f75e28e1684657ftye    sizeof (IP_IO_IP_TX_DATA) + sizeof (NET_FRAGMENT) * (FragmentCount - 1)
671cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    );
672cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
673cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == TxData) {
674fb115c61504fe6c4f94be0a87f75e28e1684657ftye    goto ON_ERROR;
675fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
676fb115c61504fe6c4f94be0a87f75e28e1684657ftye
677fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
678fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Build a fragment table to contain the fragments in the packet.
679fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
680fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4) {
681fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ExtFragment = (NET_FRAGMENT *) TxData->Ip4TxData.FragmentTable;
682fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
683fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ExtFragment = (NET_FRAGMENT *) TxData->Ip6TxData.FragmentTable;
684cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
685cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
686fb115c61504fe6c4f94be0a87f75e28e1684657ftye  NetbufBuildExt (Pkt, ExtFragment, &FragmentCount);
687fb115c61504fe6c4f94be0a87f75e28e1684657ftye
688fb115c61504fe6c4f94be0a87f75e28e1684657ftye
689cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
690cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for OverrideData if needed
691cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
692cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL != Override) {
693cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
694fb115c61504fe6c4f94be0a87f75e28e1684657ftye    OverrideData = AllocateCopyPool (sizeof (IP_IO_OVERRIDE), Override);
695cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (NULL == OverrideData) {
696fb115c61504fe6c4f94be0a87f75e28e1684657ftye      goto ON_ERROR;
697cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
698cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
699cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
700cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
701fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Set other fields of TxData except the fragment table
702cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
703fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4) {
704cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
705fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip4TxData = &TxData->Ip4TxData;
706cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
70735f910f08b58e978bc9251872635075d6f422e48Randy Pawell    IP4_COPY_ADDRESS (&Ip4TxData->DestinationAddress, Dest);
708cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
709fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip4TxData->OverrideData    = &OverrideData->Ip4OverrideData;
710fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip4TxData->OptionsLength   = 0;
711fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip4TxData->OptionsBuffer   = NULL;
712fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip4TxData->TotalDataLength = Pkt->TotalSize;
713fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip4TxData->FragmentCount   = FragmentCount;
714fb115c61504fe6c4f94be0a87f75e28e1684657ftye
715fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
716fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // Set the fields of SndToken
717fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
718fb115c61504fe6c4f94be0a87f75e28e1684657ftye    SndEntry->SndToken.Ip4Token.Event         = Event;
719fb115c61504fe6c4f94be0a87f75e28e1684657ftye    SndEntry->SndToken.Ip4Token.Packet.TxData = Ip4TxData;
720fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
721fb115c61504fe6c4f94be0a87f75e28e1684657ftye
722fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip6TxData = &TxData->Ip6TxData;
723fb115c61504fe6c4f94be0a87f75e28e1684657ftye
724fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (Dest != NULL) {
725fb115c61504fe6c4f94be0a87f75e28e1684657ftye      CopyMem (&Ip6TxData->DestinationAddress, Dest, sizeof (EFI_IPv6_ADDRESS));
726fb115c61504fe6c4f94be0a87f75e28e1684657ftye    } else {
727fb115c61504fe6c4f94be0a87f75e28e1684657ftye      ZeroMem (&Ip6TxData->DestinationAddress, sizeof (EFI_IPv6_ADDRESS));
728fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
729fb115c61504fe6c4f94be0a87f75e28e1684657ftye
730fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip6TxData->OverrideData  = &OverrideData->Ip6OverrideData;
731fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip6TxData->DataLength    = Pkt->TotalSize;
732fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip6TxData->FragmentCount = FragmentCount;
733fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip6TxData->ExtHdrsLength = 0;
734fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Ip6TxData->ExtHdrs       = NULL;
735fb115c61504fe6c4f94be0a87f75e28e1684657ftye
736fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
737fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // Set the fields of SndToken
738fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
739fb115c61504fe6c4f94be0a87f75e28e1684657ftye    SndEntry->SndToken.Ip6Token.Event         = Event;
740fb115c61504fe6c4f94be0a87f75e28e1684657ftye    SndEntry->SndToken.Ip6Token.Packet.TxData = Ip6TxData;
741fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
742cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
743cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
744cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Set the fields of SndEntry
745cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
746cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->IpIo        = IpIo;
7476aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  SndEntry->Ip          = Sender;
748cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->Context     = Context;
749cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->NotifyData  = NotifyData;
750cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
751cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->Pkt         = Pkt;
752cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_GET_REF (Pkt);
753cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
754e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertTailList (&IpIo->PendingSndList, &SndEntry->Entry);
755cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
756cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return SndEntry;
757cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
758fb115c61504fe6c4f94be0a87f75e28e1684657ftyeON_ERROR:
759fb115c61504fe6c4f94be0a87f75e28e1684657ftye
760fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (OverrideData != NULL) {
761fb115c61504fe6c4f94be0a87f75e28e1684657ftye    FreePool (OverrideData);
762fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
763cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
764fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (TxData != NULL) {
765fb115c61504fe6c4f94be0a87f75e28e1684657ftye    FreePool (TxData);
766fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
767cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
768fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (SndEntry != NULL) {
769fb115c61504fe6c4f94be0a87f75e28e1684657ftye    FreePool (SndEntry);
770fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
771cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
772fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (Event != NULL) {
773fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->CloseEvent (Event);
774fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
775cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
776cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
777cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
778cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
779cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
780cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
781cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy the SndEntry.
782e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
783e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function pairs with IpIoCreateSndEntry().
784cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
7856aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  SndEntry              Pointer to the send entry to be destroyed.
786cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
787cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
788cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
789cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoDestroySndEntry (
790cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO_SEND_ENTRY  *SndEntry
791cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
792cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
793fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_EVENT         Event;
794fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IP_IO_IP_TX_DATA  *TxData;
795fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IP_IO_OVERRIDE    *Override;
796fb115c61504fe6c4f94be0a87f75e28e1684657ftye
797fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (SndEntry->IpIo->IpVersion == IP_VERSION_4) {
798fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Event              = SndEntry->SndToken.Ip4Token.Event;
799fb115c61504fe6c4f94be0a87f75e28e1684657ftye    TxData             = (IP_IO_IP_TX_DATA *) SndEntry->SndToken.Ip4Token.Packet.TxData;
800fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Override           = (IP_IO_OVERRIDE *) TxData->Ip4TxData.OverrideData;
801fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (SndEntry->IpIo->IpVersion == IP_VERSION_6) {
802fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Event              = SndEntry->SndToken.Ip6Token.Event;
803fb115c61504fe6c4f94be0a87f75e28e1684657ftye    TxData             = (IP_IO_IP_TX_DATA *) SndEntry->SndToken.Ip6Token.Packet.TxData;
804fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Override           = (IP_IO_OVERRIDE *) TxData->Ip6TxData.OverrideData;
805fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
806fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return ;
807fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
808cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
809fb115c61504fe6c4f94be0a87f75e28e1684657ftye  gBS->CloseEvent (Event);
810cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
811fb115c61504fe6c4f94be0a87f75e28e1684657ftye  FreePool (TxData);
812fb115c61504fe6c4f94be0a87f75e28e1684657ftye
813fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (NULL != Override) {
814fb115c61504fe6c4f94be0a87f75e28e1684657ftye    FreePool (Override);
815cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
816cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
817cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetbufFree (SndEntry->Pkt);
818cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
819e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RemoveEntryList (&SndEntry->Entry);
820cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
821fb115c61504fe6c4f94be0a87f75e28e1684657ftye  FreePool (SndEntry);
822cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
823cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
824cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
825cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
826cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Notify function for IP transmit token.
827cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
8286aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
829cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
830cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
831cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
832cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
83336ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoTransmitHandlerDpc (
834cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
835cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
836cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
837cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO             *IpIo;
838cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
839fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_STATUS        Status;
840cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
841cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry  = (IP_IO_SEND_ENTRY *) Context;
842cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
843cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo      = SndEntry->IpIo;
844cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
845fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4) {
846fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = SndEntry->SndToken.Ip4Token.Status;
847fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (IpIo->IpVersion == IP_VERSION_6){
848fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = SndEntry->SndToken.Ip6Token.Status;
849fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
850fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return ;
851fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
852fb115c61504fe6c4f94be0a87f75e28e1684657ftye
8538de75da28bbd9a4d3c54fba99d943f9019b52193niry  if ((IpIo->PktSentNotify != NULL) && (SndEntry->NotifyData != NULL)) {
854cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->PktSentNotify (
855fb115c61504fe6c4f94be0a87f75e28e1684657ftye            Status,
856cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->Context,
857cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->Ip,
858cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->NotifyData
859cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            );
860cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
861cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
862cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoDestroySndEntry (SndEntry);
863cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
864cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
8656aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
86636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff/**
86736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  Notify function for IP transmit token.
86836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
8696aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event signaled.
8706aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
87136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
87236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff**/
87336ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
87436ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
87536ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoTransmitHandler (
87636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN EFI_EVENT Event,
87736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
87836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  )
87936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff{
88036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
88136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK
88236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
883d8d26fb207e02aa5ef57e2bcb213f9dda16166ccmdkinney  QueueDpc (TPL_CALLBACK, IpIoTransmitHandlerDpc, Context);
88436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff}
88536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
886cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
887cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
888cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  The dummy handler for the dummy IP receive token.
889cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
8906aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
891cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
892cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
893cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
894cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
89536ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoDummyHandlerDpc (
896cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
897cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
898cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
899cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO             *IpInfo;
900fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_STATUS                 Status;
901fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_EVENT                  RecycleEvent;
902cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
903cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo      = (IP_IO_IP_INFO *) Context;
904cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
905fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if ((IpInfo->IpVersion != IP_VERSION_4) && (IpInfo->IpVersion != IP_VERSION_6)) {
906fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return ;
907fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
908fb115c61504fe6c4f94be0a87f75e28e1684657ftye
909fb115c61504fe6c4f94be0a87f75e28e1684657ftye  RecycleEvent = NULL;
910fb115c61504fe6c4f94be0a87f75e28e1684657ftye
911fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpInfo->IpVersion == IP_VERSION_4) {
912fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = IpInfo->DummyRcvToken.Ip4Token.Status;
913fb115c61504fe6c4f94be0a87f75e28e1684657ftye
914fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (IpInfo->DummyRcvToken.Ip4Token.Packet.RxData != NULL) {
915fb115c61504fe6c4f94be0a87f75e28e1684657ftye      RecycleEvent = IpInfo->DummyRcvToken.Ip4Token.Packet.RxData->RecycleSignal;
916fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
917fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
918fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = IpInfo->DummyRcvToken.Ip6Token.Status;
919fb115c61504fe6c4f94be0a87f75e28e1684657ftye
920fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (IpInfo->DummyRcvToken.Ip6Token.Packet.RxData != NULL) {
921fb115c61504fe6c4f94be0a87f75e28e1684657ftye      RecycleEvent = IpInfo->DummyRcvToken.Ip6Token.Packet.RxData->RecycleSignal;
922fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
923fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
924fb115c61504fe6c4f94be0a87f75e28e1684657ftye
925fb115c61504fe6c4f94be0a87f75e28e1684657ftye
926fb115c61504fe6c4f94be0a87f75e28e1684657ftye
927fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (EFI_ABORTED == Status) {
92836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
92936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    // The reception is actively aborted by the consumer, directly return.
93036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
93136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    return;
932fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (EFI_SUCCESS == Status) {
933fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
934fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // Recycle the RxData.
935fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
936fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ASSERT (RecycleEvent != NULL);
937cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
938fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->SignalEvent (RecycleEvent);
939cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
940cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
941fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
942fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Continue the receive.
943fb115c61504fe6c4f94be0a87f75e28e1684657ftye  //
944fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpInfo->IpVersion == IP_VERSION_4) {
9452a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    IpInfo->Ip.Ip4->Receive (
9462a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                      IpInfo->Ip.Ip4,
9472a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                      &IpInfo->DummyRcvToken.Ip4Token
9482a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                      );
949fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
9502a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    IpInfo->Ip.Ip6->Receive (
9512a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                      IpInfo->Ip.Ip6,
9522a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                      &IpInfo->DummyRcvToken.Ip6Token
9532a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                      );
954fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
955cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
956cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
957cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
958cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
9596aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  This function add IpIoDummyHandlerDpc to the end of the DPC queue.
960cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
9616aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event signaled.
9626aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
963cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
964cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
965cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
966cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
96736ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoDummyHandler (
968cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_EVENT Event,
969cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
970cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
971cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
97236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
97336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK
97436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
975d8d26fb207e02aa5ef57e2bcb213f9dda16166ccmdkinney  QueueDpc (TPL_CALLBACK, IpIoDummyHandlerDpc, Context);
97636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff}
97736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
97836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
97936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff/**
98036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  Notify function for the IP receive token, used to process
98136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  the received IP packets.
98236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
9836aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
98436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
98536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff**/
98636ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
98736ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
98836ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoListenHandlerDpc (
98936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
99036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  )
99136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff{
992cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO                 *IpIo;
993cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS            Status;
994fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IP_IO_IP_RX_DATA      *RxData;
995cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_NET_SESSION_DATA  Session;
996cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_BUF               *Pkt;
997cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
998fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpIo = (IP_IO *) Context;
999cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1000fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4) {
1001fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = IpIo->RcvToken.Ip4Token.Status;
1002fb115c61504fe6c4f94be0a87f75e28e1684657ftye    RxData = (IP_IO_IP_RX_DATA *) IpIo->RcvToken.Ip4Token.Packet.RxData;
1003fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (IpIo->IpVersion == IP_VERSION_6) {
1004fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Status = IpIo->RcvToken.Ip6Token.Status;
1005fb115c61504fe6c4f94be0a87f75e28e1684657ftye    RxData = (IP_IO_IP_RX_DATA *) IpIo->RcvToken.Ip6Token.Packet.RxData;
1006fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1007fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return;
1008fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1009cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
101036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  if (EFI_ABORTED == Status) {
101136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
101236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    // The reception is actively aborted by the consumer, directly return.
101336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
101436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    return;
101536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  }
101636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
1017cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (((EFI_SUCCESS != Status) && (EFI_ICMP_ERROR != Status)) || (NULL == RxData)) {
1018cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
10196aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // @bug Only process the normal packets and the icmp error packets, if RxData is NULL
10206aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // @bug with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
10216aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // @bug this should be a bug of the low layer (IP).
1022cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1023cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto Resume;
1024cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1025cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1026cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == IpIo->PktRcvdNotify) {
1027cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
1028cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1029cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1030fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4) {
1031fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if ((EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress) != 0) &&
1032f6b7393ceb34c9b3a27434268bf2ce517047641ftye      !NetIp4IsUnicast (EFI_NTOHL (((EFI_IP4_RECEIVE_DATA *) RxData)->Header->SourceAddress), 0)) {
1033cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1034cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // The source address is not zero and it's not a unicast IP address, discard it.
1035cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1036cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
1037cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1038cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1039cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1040fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Create a netbuffer representing IPv4 packet
1041cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1042cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Pkt = NetbufFromExt (
1043fb115c61504fe6c4f94be0a87f75e28e1684657ftye          (NET_FRAGMENT *) RxData->Ip4RxData.FragmentTable,
1044fb115c61504fe6c4f94be0a87f75e28e1684657ftye          RxData->Ip4RxData.FragmentCount,
1045cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          0,
1046cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          0,
1047cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          IpIoExtFree,
1048fb115c61504fe6c4f94be0a87f75e28e1684657ftye          RxData->Ip4RxData.RecycleSignal
1049cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          );
1050cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == Pkt) {
1051cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
1052cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1053cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1054cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1055cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create a net session
1056cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1057fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Session.Source.Addr[0] = EFI_IP4 (RxData->Ip4RxData.Header->SourceAddress);
1058fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Session.Dest.Addr[0]   = EFI_IP4 (RxData->Ip4RxData.Header->DestinationAddress);
1059fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Session.IpHdr.Ip4Hdr   = RxData->Ip4RxData.Header;
1060a09ee46d9a258ef08a931c0d412c62c98dbdb8aaqouyang  Session.IpHdrLen       = RxData->Ip4RxData.HeaderLength;
1061fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Session.IpVersion      = IP_VERSION_4;
1062fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1063fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1064f6b7393ceb34c9b3a27434268bf2ce517047641ftye    if (!NetIp6IsValidUnicast(&RxData->Ip6RxData.Header->SourceAddress)) {
1065fb115c61504fe6c4f94be0a87f75e28e1684657ftye      goto CleanUp;
1066fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
1067fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1068fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
1069fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // Create a netbuffer representing IPv6 packet
1070fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
1071fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Pkt = NetbufFromExt (
1072fb115c61504fe6c4f94be0a87f75e28e1684657ftye            (NET_FRAGMENT *) RxData->Ip6RxData.FragmentTable,
1073fb115c61504fe6c4f94be0a87f75e28e1684657ftye            RxData->Ip6RxData.FragmentCount,
1074fb115c61504fe6c4f94be0a87f75e28e1684657ftye            0,
1075fb115c61504fe6c4f94be0a87f75e28e1684657ftye            0,
1076fb115c61504fe6c4f94be0a87f75e28e1684657ftye            IpIoExtFree,
1077fb115c61504fe6c4f94be0a87f75e28e1684657ftye            RxData->Ip6RxData.RecycleSignal
1078fb115c61504fe6c4f94be0a87f75e28e1684657ftye            );
1079fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (NULL == Pkt) {
1080fb115c61504fe6c4f94be0a87f75e28e1684657ftye      goto CleanUp;
1081fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
1082fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1083fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
1084fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // Create a net session
1085fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
1086fb115c61504fe6c4f94be0a87f75e28e1684657ftye    CopyMem (
1087fb115c61504fe6c4f94be0a87f75e28e1684657ftye      &Session.Source,
1088fb115c61504fe6c4f94be0a87f75e28e1684657ftye      &RxData->Ip6RxData.Header->SourceAddress,
1089fb115c61504fe6c4f94be0a87f75e28e1684657ftye      sizeof(EFI_IPv6_ADDRESS)
1090fb115c61504fe6c4f94be0a87f75e28e1684657ftye      );
1091fb115c61504fe6c4f94be0a87f75e28e1684657ftye    CopyMem (
1092fb115c61504fe6c4f94be0a87f75e28e1684657ftye      &Session.Dest,
1093fb115c61504fe6c4f94be0a87f75e28e1684657ftye      &RxData->Ip6RxData.Header->DestinationAddress,
1094fb115c61504fe6c4f94be0a87f75e28e1684657ftye      sizeof(EFI_IPv6_ADDRESS)
1095fb115c61504fe6c4f94be0a87f75e28e1684657ftye      );
1096fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Session.IpHdr.Ip6Hdr = RxData->Ip6RxData.Header;
1097a09ee46d9a258ef08a931c0d412c62c98dbdb8aaqouyang    Session.IpHdrLen     = RxData->Ip6RxData.HeaderLength;
1098fb115c61504fe6c4f94be0a87f75e28e1684657ftye    Session.IpVersion    = IP_VERSION_6;
1099fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1100cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1101cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_SUCCESS == Status) {
1102cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1103b45b45b2d248892930620c33a9d01d8457ae0e54tye    IpIo->PktRcvdNotify (EFI_SUCCESS, 0, &Session, Pkt, IpIo->RcvdContext);
1104cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  } else {
1105cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1106cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // Status is EFI_ICMP_ERROR
1107cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1108cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    Status = IpIoIcmpHandler (IpIo, Pkt, &Session);
1109cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (EFI_ERROR (Status)) {
1110cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      NetbufFree (Pkt);
1111cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1112cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1113cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1114cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  goto Resume;
1115cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1116cbf316f20726bb31b7c37424601643790dbd02d9vanjeffCleanUp:
1117fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1118fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4){
1119fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->SignalEvent (RxData->Ip4RxData.RecycleSignal);
1120fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1121fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->SignalEvent (RxData->Ip6RxData.RecycleSignal);
1122fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1123cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1124cbf316f20726bb31b7c37424601643790dbd02d9vanjeffResume:
1125cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1126fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4){
11272a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    IpIo->Ip.Ip4->Receive (IpIo->Ip.Ip4, &(IpIo->RcvToken.Ip4Token));
1128fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
11292a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    IpIo->Ip.Ip6->Receive (IpIo->Ip.Ip6, &(IpIo->RcvToken.Ip6Token));
1130fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1131fb115c61504fe6c4f94be0a87f75e28e1684657ftye}
1132cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1133cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
11346aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  This function add IpIoListenHandlerDpc to the end of the DPC queue.
113536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
11366aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                The event signaled.
11376aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context              The context passed in by the event notifier.
113836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
113936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff**/
114036ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
114136ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
114236ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoListenHandler (
114336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN EFI_EVENT Event,
114436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
114536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  )
114636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff{
114736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
114836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
114936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
1150d8d26fb207e02aa5ef57e2bcb213f9dda16166ccmdkinney  QueueDpc (TPL_CALLBACK, IpIoListenHandlerDpc, Context);
115136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff}
115236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
115336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
115436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff/**
1155cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Create a new IP_IO instance.
1156e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1157fb115c61504fe6c4f94be0a87f75e28e1684657ftye  This function uses IP4/IP6 service binding protocol in Controller to create
1158fb115c61504fe6c4f94be0a87f75e28e1684657ftye  an IP4/IP6 child (aka IP4/IP6 instance).
1159cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
11606aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Image             The image handle of the driver or application that
1161e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong                                consumes IP_IO.
1162fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]  Controller        The controller handle that has IP4 or IP6 service
1163fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                binding protocol installed.
1164fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]  IpVersion         The version of the IP protocol to use, either
1165fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                IPv4 or IPv6.
1166cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1167e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  @return Pointer to a newly created IP_IO instance, or NULL if failed.
1168cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1169cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1170cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO *
11717b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1172cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreate (
1173cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE Image,
1174fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN EFI_HANDLE Controller,
1175b45b45b2d248892930620c33a9d01d8457ae0e54tye  IN UINT8      IpVersion
1176cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1177cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1178cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
1179cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO       *IpIo;
1180fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_EVENT   Event;
1181fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1182fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
1183cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1184e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  IpIo = AllocateZeroPool (sizeof (IP_IO));
1185cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == IpIo) {
1186cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return NULL;
1187cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1188cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1189e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&(IpIo->PendingSndList));
1190e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&(IpIo->IpList));
1191cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Controller  = Controller;
1192cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Image       = Image;
1193fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpIo->IpVersion   = IpVersion;
1194fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Event             = NULL;
1195cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1196cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
1197cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
1198e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
1199cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoListenHandler,
1200cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIo,
1201fb115c61504fe6c4f94be0a87f75e28e1684657ftye                  &Event
1202cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
1203cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1204cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpIo;
1205cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1206cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1207fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4) {
1208fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->RcvToken.Ip4Token.Event = Event;
1209fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1210fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->RcvToken.Ip6Token.Event = Event;
1211fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1212fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1213cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1214cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create an IP child and open IP protocol
1215cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1216cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = IpIoCreateIpChildOpenProtocol (
1217cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             Controller,
1218cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             Image,
1219cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &IpIo->ChildHandle,
1220fb115c61504fe6c4f94be0a87f75e28e1684657ftye             IpVersion,
1221cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             (VOID **)&(IpIo->Ip)
1222cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
1223cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1224cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpIo;
1225cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1226cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1227cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return IpIo;
1228cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1229cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpIo:
1230cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1231fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (Event != NULL) {
1232fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->CloseEvent (Event);
1233cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1234cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1235e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpIo);
1236cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1237cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
1238cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1239cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1240cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1241cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1242cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Open an IP_IO instance for use.
1243e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1244e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is called after IpIoCreate(). It is used for configuring the IP
1245e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  instance and register the callbacks and their context data for sending and
1246e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  receiving IP packets.
1247cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
12486aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo               Pointer to an IP_IO instance that needs
12496aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      to open.
12506aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       OpenData           The configuration data and callbacks for
12516aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      the IP_IO instance.
1252cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
12536aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS        The IP_IO instance opened with OpenData
12546aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      successfully.
12556aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_ACCESS_DENIED  The IP_IO instance is configured, avoid to
12566aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      reopen it.
12576aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others             Error condition occurred.
1258cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1259cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1260cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
12617b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1262cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoOpen (
12636aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO           *IpIo,
12646aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_OPEN_DATA *OpenData
1265cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1266cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1267cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
1268b45b45b2d248892930620c33a9d01d8457ae0e54tye  UINT8             IpVersion;
1269cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1270cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpIo->IsConfigured) {
1271cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ACCESS_DENIED;
1272cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1273cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1274fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpVersion = IpIo->IpVersion;
1275fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1276fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
1277fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1278cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1279cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // configure ip
1280cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1281fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4){
12822a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    Status = IpIo->Ip.Ip4->Configure (
12832a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             IpIo->Ip.Ip4,
12842a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             &OpenData->IpConfigData.Ip4CfgData
12852a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             );
1286fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1287fb115c61504fe6c4f94be0a87f75e28e1684657ftye
12882a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    Status = IpIo->Ip.Ip6->Configure (
12892a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             IpIo->Ip.Ip6,
12902a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             &OpenData->IpConfigData.Ip6CfgData
12912a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             );
1292fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1293fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1294cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1295cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
1296cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1297cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1298cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
12996aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // @bug To delete the default route entry in this Ip, if it is:
13006aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // @bug (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified
13016aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // @bug its code
1302cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1303fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4){
13042a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    Status = IpIo->Ip.Ip4->Routes (
13052a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             IpIo->Ip.Ip4,
13062a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             TRUE,
13072a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             &mZeroIp4Addr,
13082a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             &mZeroIp4Addr,
13092a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             &mZeroIp4Addr
13102a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             );
1311fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1312fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (EFI_ERROR (Status) && (EFI_NOT_FOUND != Status)) {
1313fb115c61504fe6c4f94be0a87f75e28e1684657ftye      return Status;
1314fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
1315cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1316cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1317cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktRcvdNotify = OpenData->PktRcvdNotify;
1318cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktSentNotify = OpenData->PktSentNotify;
1319cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1320cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->RcvdContext   = OpenData->RcvdContext;
1321cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->SndContext    = OpenData->SndContext;
1322cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1323fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4){
1324fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->Protocol = OpenData->IpConfigData.Ip4CfgData.DefaultProtocol;
1325cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1326fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
1327fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // start to listen incoming packet
1328fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
13292a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    Status = IpIo->Ip.Ip4->Receive (
13302a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             IpIo->Ip.Ip4,
13312a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             &(IpIo->RcvToken.Ip4Token)
13322a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             );
1333fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (EFI_ERROR (Status)) {
13342a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang      IpIo->Ip.Ip4->Configure (IpIo->Ip.Ip4, NULL);
1335fb115c61504fe6c4f94be0a87f75e28e1684657ftye      goto ErrorExit;
1336fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
1337fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1338fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1339fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1340fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->Protocol = OpenData->IpConfigData.Ip6CfgData.DefaultProtocol;
13412a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    Status = IpIo->Ip.Ip6->Receive (
13422a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             IpIo->Ip.Ip6,
13432a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             &(IpIo->RcvToken.Ip6Token)
13442a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                             );
1345fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (EFI_ERROR (Status)) {
13462a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang      IpIo->Ip.Ip6->Configure (IpIo->Ip.Ip6, NULL);
1347fb115c61504fe6c4f94be0a87f75e28e1684657ftye      goto ErrorExit;
1348fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
1349cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1350cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1351cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->IsConfigured = TRUE;
1352e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertTailList (&mActiveIpIoList, &IpIo->Entry);
1353cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1354cbf316f20726bb31b7c37424601643790dbd02d9vanjeffErrorExit:
1355cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1356cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
1357cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1358cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1359cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1360cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1361cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Stop an IP_IO instance.
1362e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1363e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is paired with IpIoOpen(). The IP_IO will be unconfigured and all
1364e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  the pending send/receive tokens will be canceled.
1365cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
13666aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo            Pointer to the IP_IO instance that needs to stop.
1367cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
13686aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS     The IP_IO instance stopped successfully.
13696aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others          Error condition occurred.
1370cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1371cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1372cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
1373e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgongEFIAPI
1374cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoStop (
13756aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO *IpIo
1376cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1377cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1378cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
1379cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO     *IpInfo;
1380b45b45b2d248892930620c33a9d01d8457ae0e54tye  UINT8             IpVersion;
1381cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1382cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (!IpIo->IsConfigured) {
1383cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_SUCCESS;
1384cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1385cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1386fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpVersion = IpIo->IpVersion;
1387fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1388fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
1389fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1390cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1391cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Remove the IpIo from the active IpIo list.
1392cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1393e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RemoveEntryList (&IpIo->Entry);
1394cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1395cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1396cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Configure NULL Ip
1397cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1398fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4) {
13992a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    Status = IpIo->Ip.Ip4->Configure (IpIo->Ip.Ip4, NULL);
1400fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
14012a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    Status = IpIo->Ip.Ip6->Configure (IpIo->Ip.Ip6, NULL);
1402fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1403cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1404cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
1405cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1406cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1407cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->IsConfigured = FALSE;
1408cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1409cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1410cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Detroy the Ip List used by IpIo
1411cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
141234edf2ae729941a6203e4e7f614db32204a9c47dvanjeff
1413e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  while (!IsListEmpty (&(IpIo->IpList))) {
1414cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo = NET_LIST_HEAD (&(IpIo->IpList), IP_IO_IP_INFO, Entry);
1415cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1416cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoRemoveIp (IpIo, IpInfo);
1417cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1418cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1419cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
14206aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // All pending send tokens should be flushed by reseting the IP instances.
1421cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1422e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  ASSERT (IsListEmpty (&IpIo->PendingSndList));
1423cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1424cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1425cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Close the receive event.
1426cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1427fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4){
1428fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->CloseEvent (IpIo->RcvToken.Ip4Token.Event);
1429fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1430fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->CloseEvent (IpIo->RcvToken.Ip6Token.Event);
1431fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1432cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1433cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
1434cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1435cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1436cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1437cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1438cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy an IP_IO instance.
1439e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1440e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is paired with IpIoCreate(). The IP_IO will be closed first.
14418f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  Resource will be freed afterwards. See IpIoCloseProtocolDestroyIpChild().
1442cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
14436aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo         Pointer to the IP_IO instance that needs to be
1444e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong                                destroyed.
1445cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
14466aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS  The IP_IO instance destroyed successfully.
14476aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others       Error condition occurred.
1448cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1449cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1450cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
14517b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1452cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoDestroy (
14536aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO *IpIo
1454cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1455cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1456cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1457cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Stop the IpIo.
1458cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1459cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoStop (IpIo);
1460cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1461cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1462cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Close the IP protocol and destroy the child.
1463cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1464fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpIoCloseProtocolDestroyIpChild (
1465fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->Controller,
1466fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->Image,
1467fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->ChildHandle,
1468fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIo->IpVersion
1469fb115c61504fe6c4f94be0a87f75e28e1684657ftye    );
1470cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1471e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpIo);
1472cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1473cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
1474cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1475cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1476cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1477cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1478cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Send out an IP packet.
1479e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1480e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is called after IpIoOpen(). The data to be sent are wrapped in
1481e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  Pkt. The IP instance wrapped in IpIo is used for sending by default but can be
1482e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  overriden by Sender. Other sending configs, like source address and gateway
1483e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  address etc., are specified in OverrideData.
1484cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
14856aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo                  Pointer to an IP_IO instance used for sending IP
14866aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                         packet.
14876aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  Pkt                   Pointer to the IP packet to be sent.
14886aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Sender                The IP protocol instance used for sending.
14898f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[in]       Context               Optional context data.
14908f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[in]       NotifyData            Optional notify data.
14916aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Dest                  The destination IP address to send this packet to.
14926aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       OverrideData          The data to override some configuration of the IP
14936aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                         instance used for sending.
1494cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
14956aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS           The operation is completed successfully.
14966aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_NOT_STARTED       The IpIo is not configured.
14976aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_OUT_OF_RESOURCES  Failed due to resource limit.
1498cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1499cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1500cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
15017b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1502cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoSend (
15036aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO          *IpIo,
15046aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT NET_BUF        *Pkt,
15056aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_IP_INFO  *Sender        OPTIONAL,
15066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID           *Context       OPTIONAL,
15076aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID           *NotifyData    OPTIONAL,
1508fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     EFI_IP_ADDRESS *Dest,
15096aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_OVERRIDE *OverrideData  OPTIONAL
1510cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1511cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1512cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
15132a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang  IP_IO_IP_PROTOCOL Ip;
1514cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
1515cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1516fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpIo->IpVersion != IP_VERSION_4) || (Dest != NULL));
1517fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1518cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (!IpIo->IsConfigured) {
1519cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_NOT_STARTED;
1520cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1521cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1522cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = (NULL == Sender) ? IpIo->Ip : Sender->Ip;
1523cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1524cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1525cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // create a new SndEntry
1526cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1527cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry = IpIoCreateSndEntry (IpIo, Pkt, Ip, Context, NotifyData, Dest, OverrideData);
1528cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndEntry) {
1529cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_OUT_OF_RESOURCES;
1530cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1531cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1532cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1533cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Send this Packet
1534cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1535fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpIo->IpVersion == IP_VERSION_4){
15362a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    Status = Ip.Ip4->Transmit (
15372a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                       Ip.Ip4,
15382a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                       &SndEntry->SndToken.Ip4Token
15392a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                       );
1540fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
15412a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    Status = Ip.Ip6->Transmit (
15422a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                       Ip.Ip6,
15432a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                       &SndEntry->SndToken.Ip6Token
15442a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                       );
1545fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1546fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1547cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1548cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoDestroySndEntry (SndEntry);
1549cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1550cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1551cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
1552cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1553cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1554cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1555cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1556cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Cancel the IP transmit token which wraps this Packet.
1557cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
15586aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  IpIo                  Pointer to the IP_IO instance.
15596aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Packet                Pointer to the packet of NET_BUF to cancel.
1560cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1561cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1562cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
15637b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1564cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCancelTxToken (
1565cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO  *IpIo,
1566cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID   *Packet
1567cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1568cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1569e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  LIST_ENTRY        *Node;
1570cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
15712a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang  IP_IO_IP_PROTOCOL Ip;
1572cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1573fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpIo != NULL) && (Packet != NULL));
1574cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1575cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_FOR_EACH (Node, &IpIo->PendingSndList) {
1576cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1577cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    SndEntry = NET_LIST_USER_STRUCT (Node, IP_IO_SEND_ENTRY, Entry);
1578cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1579cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (SndEntry->Pkt == Packet) {
1580cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1581cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip = SndEntry->Ip;
1582fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1583fb115c61504fe6c4f94be0a87f75e28e1684657ftye      if (IpIo->IpVersion == IP_VERSION_4) {
15842a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang        Ip.Ip4->Cancel (
15852a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                  Ip.Ip4,
15862a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                  &SndEntry->SndToken.Ip4Token
15872a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                  );
1588fb115c61504fe6c4f94be0a87f75e28e1684657ftye      } else {
15892a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang        Ip.Ip6->Cancel (
15902a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                  Ip.Ip6,
15912a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                  &SndEntry->SndToken.Ip6Token
15922a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                  );
1593fb115c61504fe6c4f94be0a87f75e28e1684657ftye      }
1594cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1595cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
1596cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1597cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1598cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1599cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1600cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1601cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1602cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1603cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Add a new IP instance for sending data.
1604e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1605e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  The function is used to add the IP_IO to the IP_IO sending list. The caller
1606e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send
1607e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  data.
1608cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
16096aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo               Pointer to a IP_IO instance to add a new IP
16106aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      instance for sending purpose.
1611cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1612e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  @return Pointer to the created IP_IO_IP_INFO structure, NULL if failed.
1613cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1614cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1615cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_IP_INFO *
16167b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1617cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoAddIp (
16186aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO  *IpIo
1619cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1620cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1621cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS     Status;
1622cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO  *IpInfo;
1623fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_EVENT      Event;
1624cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
16256aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  ASSERT (IpIo != NULL);
1626cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1627e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  IpInfo = AllocatePool (sizeof (IP_IO_IP_INFO));
1628cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo == NULL) {
1629fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return NULL;
1630cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1631cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1632cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1633cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP
1634cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // instance.
1635cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1636e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&IpInfo->Entry);
1637cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->ChildHandle = NULL;
1638fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ZeroMem (&IpInfo->Addr, sizeof (IpInfo->Addr));
1639fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ZeroMem (&IpInfo->PreMask, sizeof (IpInfo->PreMask));
1640fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1641fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpInfo->RefCnt    = 1;
1642fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpInfo->IpVersion = IpIo->IpVersion;
1643cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1644cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1645fb115c61504fe6c4f94be0a87f75e28e1684657ftye  // Create the IP instance and open the IP protocol.
1646cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1647cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = IpIoCreateIpChildOpenProtocol (
1648cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             IpIo->Controller,
1649cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             IpIo->Image,
1650cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &IpInfo->ChildHandle,
1651fb115c61504fe6c4f94be0a87f75e28e1684657ftye             IpInfo->IpVersion,
16524eb65aff715faafd9040c6fc85a5d59e22343978vanjeff             (VOID **) &IpInfo->Ip
1653cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
1654cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1655cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpInfo;
1656cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1657cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1658cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1659cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create the event for the DummyRcvToken.
1660cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1661cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
1662cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
1663e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
1664cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoDummyHandler,
1665cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpInfo,
1666fb115c61504fe6c4f94be0a87f75e28e1684657ftye                  &Event
1667cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
1668cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1669cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpChild;
1670cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1671cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1672fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpInfo->IpVersion == IP_VERSION_4) {
1673fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpInfo->DummyRcvToken.Ip4Token.Event = Event;
1674fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1675fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpInfo->DummyRcvToken.Ip6Token.Event = Event;
1676fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1677fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1678cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1679cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Link this IpInfo into the IpIo.
1680cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1681e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertTailList (&IpIo->IpList, &IpInfo->Entry);
1682cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1683cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return IpInfo;
1684cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1685cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpChild:
1686cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1687cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoCloseProtocolDestroyIpChild (
1688cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->Controller,
1689cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->Image,
1690fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpInfo->ChildHandle,
1691fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpInfo->IpVersion
1692cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    );
1693cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1694cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpInfo:
1695cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1696e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpInfo);
1697cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1698cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
1699cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1700cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1701cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1702cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1703fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Configure the IP instance of this IpInfo and start the receiving if IpConfigData
1704cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  is not NULL.
1705cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
17066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpInfo          Pointer to the IP_IO_IP_INFO instance.
1707fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in, out]  IpConfigData    The IP configure data used to configure the IP
17086aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   instance, if NULL the IP instance is reset. If
17096aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   UseDefaultAddress is set to TRUE, and the configure
17106aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   operation succeeds, the default address information
1711fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                   is written back in this IpConfigData.
1712cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
17136aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS     The IP instance of this IpInfo is configured successfully
17146aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   or no need to reconfigure it.
17156aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others          Configuration fails.
1716cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1717cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1718cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
17197b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1720cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoConfigIp (
17216aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO_IP_INFO        *IpInfo,
1722fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN OUT VOID                 *IpConfigData OPTIONAL
1723cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1724cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1725cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS         Status;
17262a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang  IP_IO_IP_PROTOCOL  Ip;
1727b45b45b2d248892930620c33a9d01d8457ae0e54tye  UINT8              IpVersion;
1728cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_MODE_DATA  Ip4ModeData;
1729fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_IP6_MODE_DATA  Ip6ModeData;
1730cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
17316aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  ASSERT (IpInfo != NULL);
1732cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1733cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo->RefCnt > 1) {
1734cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1735cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // This IP instance is shared, don't reconfigure it until it has only one
1736cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // consumer. Currently, only the tcp children cloned from their passive parent
1737fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // will share the same IP. So this cases only happens while IpConfigData is NULL,
1738cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // let the last consumer clean the IP instance.
1739cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1740cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_SUCCESS;
1741cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1742cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1743fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpVersion = IpInfo->IpVersion;
1744fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
1745fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1746cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpInfo->Ip;
1747cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1748fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpInfo->IpVersion == IP_VERSION_4) {
17492a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    Status = Ip.Ip4->Configure (Ip.Ip4, IpConfigData);
1750fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
17512a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    Status = Ip.Ip6->Configure (Ip.Ip6, IpConfigData);
1752fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1753fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1754cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1755cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto OnExit;
1756cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1757cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1758fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpConfigData != NULL) {
1759fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (IpInfo->IpVersion == IP_VERSION_4){
1760cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1761fb115c61504fe6c4f94be0a87f75e28e1684657ftye      if (((EFI_IP4_CONFIG_DATA *) IpConfigData)->UseDefaultAddress) {
17622a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang        Ip.Ip4->GetModeData (
17632a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                  Ip.Ip4,
17642a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                  &Ip4ModeData,
17652a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                  NULL,
17662a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                  NULL
17672a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                  );
1768cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
176935f910f08b58e978bc9251872635075d6f422e48Randy Pawell        IP4_COPY_ADDRESS (&((EFI_IP4_CONFIG_DATA*) IpConfigData)->StationAddress, &Ip4ModeData.ConfigData.StationAddress);
177035f910f08b58e978bc9251872635075d6f422e48Randy Pawell        IP4_COPY_ADDRESS (&((EFI_IP4_CONFIG_DATA*) IpConfigData)->SubnetMask, &Ip4ModeData.ConfigData.SubnetMask);
1771cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1772cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1773fb115c61504fe6c4f94be0a87f75e28e1684657ftye      CopyMem (
1774fb115c61504fe6c4f94be0a87f75e28e1684657ftye        &IpInfo->Addr.Addr,
1775fb115c61504fe6c4f94be0a87f75e28e1684657ftye        &((EFI_IP4_CONFIG_DATA *) IpConfigData)->StationAddress,
1776fb115c61504fe6c4f94be0a87f75e28e1684657ftye        sizeof (IP4_ADDR)
1777fb115c61504fe6c4f94be0a87f75e28e1684657ftye        );
1778fb115c61504fe6c4f94be0a87f75e28e1684657ftye      CopyMem (
1779fb115c61504fe6c4f94be0a87f75e28e1684657ftye        &IpInfo->PreMask.SubnetMask,
1780fb115c61504fe6c4f94be0a87f75e28e1684657ftye        &((EFI_IP4_CONFIG_DATA *) IpConfigData)->SubnetMask,
1781fb115c61504fe6c4f94be0a87f75e28e1684657ftye        sizeof (IP4_ADDR)
1782fb115c61504fe6c4f94be0a87f75e28e1684657ftye        );
1783fb115c61504fe6c4f94be0a87f75e28e1684657ftye
17842a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang      Status = Ip.Ip4->Receive (
17852a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                         Ip.Ip4,
17862a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                         &IpInfo->DummyRcvToken.Ip4Token
17872a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                         );
1788cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (EFI_ERROR (Status)) {
17892a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang      Ip.Ip4->Configure (Ip.Ip4, NULL);
1790cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1791cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  } else {
17922a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    Ip.Ip6->GetModeData (
17932a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang              Ip.Ip6,
17942a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang              &Ip6ModeData,
17952a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang              NULL,
17962a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang              NULL
17972a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang              );
1798fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1799fb115c61504fe6c4f94be0a87f75e28e1684657ftye      if (Ip6ModeData.IsConfigured) {
1800fb115c61504fe6c4f94be0a87f75e28e1684657ftye        CopyMem (
1801fb115c61504fe6c4f94be0a87f75e28e1684657ftye          &((EFI_IP6_CONFIG_DATA *) IpConfigData)->StationAddress,
1802fb115c61504fe6c4f94be0a87f75e28e1684657ftye          &Ip6ModeData.ConfigData.StationAddress,
1803fb115c61504fe6c4f94be0a87f75e28e1684657ftye          sizeof (EFI_IPv6_ADDRESS)
1804fb115c61504fe6c4f94be0a87f75e28e1684657ftye          );
1805fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1806fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (Ip6ModeData.AddressList != NULL) {
1807fb115c61504fe6c4f94be0a87f75e28e1684657ftye          FreePool (Ip6ModeData.AddressList);
1808fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1809fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1810fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (Ip6ModeData.GroupTable != NULL) {
1811fb115c61504fe6c4f94be0a87f75e28e1684657ftye          FreePool (Ip6ModeData.GroupTable);
1812fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1813fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1814fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (Ip6ModeData.RouteTable != NULL) {
1815fb115c61504fe6c4f94be0a87f75e28e1684657ftye          FreePool (Ip6ModeData.RouteTable);
1816fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1817fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1818fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (Ip6ModeData.NeighborCache != NULL) {
1819fb115c61504fe6c4f94be0a87f75e28e1684657ftye          FreePool (Ip6ModeData.NeighborCache);
1820fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1821fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1822fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (Ip6ModeData.PrefixTable != NULL) {
1823fb115c61504fe6c4f94be0a87f75e28e1684657ftye          FreePool (Ip6ModeData.PrefixTable);
1824fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1825fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1826fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (Ip6ModeData.IcmpTypeList != NULL) {
1827fb115c61504fe6c4f94be0a87f75e28e1684657ftye          FreePool (Ip6ModeData.IcmpTypeList);
1828fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1829fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1830fb115c61504fe6c4f94be0a87f75e28e1684657ftye      } else {
1831fb115c61504fe6c4f94be0a87f75e28e1684657ftye        Status = EFI_NO_MAPPING;
1832fb115c61504fe6c4f94be0a87f75e28e1684657ftye        goto OnExit;
1833fb115c61504fe6c4f94be0a87f75e28e1684657ftye      }
1834fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1835fb115c61504fe6c4f94be0a87f75e28e1684657ftye      CopyMem (
1836fb115c61504fe6c4f94be0a87f75e28e1684657ftye        &IpInfo->Addr,
1837fb115c61504fe6c4f94be0a87f75e28e1684657ftye        &Ip6ModeData.ConfigData.StationAddress,
1838fb115c61504fe6c4f94be0a87f75e28e1684657ftye        sizeof (EFI_IPv6_ADDRESS)
1839fb115c61504fe6c4f94be0a87f75e28e1684657ftye        );
1840fb115c61504fe6c4f94be0a87f75e28e1684657ftye
18412a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang      Status = Ip.Ip6->Receive (
18422a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                         Ip.Ip6,
18432a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                         &IpInfo->DummyRcvToken.Ip6Token
18442a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                         );
1845fb115c61504fe6c4f94be0a87f75e28e1684657ftye      if (EFI_ERROR (Status)) {
18462a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang        Ip.Ip6->Configure (Ip.Ip6, NULL);
1847fb115c61504fe6c4f94be0a87f75e28e1684657ftye      }
1848fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
1849fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1850cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1851fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // The IP instance is reset, set the stored Addr and SubnetMask to zero.
1852cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1853fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ZeroMem (&IpInfo->Addr, sizeof (IpInfo->Addr));
1854fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ZeroMem (&IpInfo->PreMask, sizeof (IpInfo->PreMask));
1855cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1856cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1857cbf316f20726bb31b7c37424601643790dbd02d9vanjeffOnExit:
1858cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1859cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
1860cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1861cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1862cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1863cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1864cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy an IP instance maintained in IpIo->IpList for
1865cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  sending purpose.
1866e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1867e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function pairs with IpIoAddIp(). The IpInfo is previously created by
1868e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance
1869e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  will be dstroyed if the RefCnt is zero.
1870cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
18716aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  IpIo                  Pointer to the IP_IO instance.
18726aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  IpInfo                Pointer to the IpInfo to be removed.
1873cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1874cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1875cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
18767b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1877cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoRemoveIp (
1878e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IN IP_IO            *IpIo,
1879e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IN IP_IO_IP_INFO    *IpInfo
1880cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1881cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1882fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1883b45b45b2d248892930620c33a9d01d8457ae0e54tye  UINT8               IpVersion;
1884fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1885cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ASSERT (IpInfo->RefCnt > 0);
1886cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1887cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_PUT_REF (IpInfo);
1888cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1889cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo->RefCnt > 0) {
1890cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1891cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return;
1892cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1893cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1894fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IpVersion = IpIo->IpVersion;
1895fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1896fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
1897fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1898e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RemoveEntryList (&IpInfo->Entry);
1899cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1900fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (IpVersion == IP_VERSION_4){
19012a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    IpInfo->Ip.Ip4->Configure (
19022a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                      IpInfo->Ip.Ip4,
19032a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                      NULL
19042a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                      );
1905fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIoCloseProtocolDestroyIpChild (
1906fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IpIo->Controller,
1907fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IpIo->Image,
1908fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IpInfo->ChildHandle,
1909fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IP_VERSION_4
1910fb115c61504fe6c4f94be0a87f75e28e1684657ftye      );
1911fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1912fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->CloseEvent (IpInfo->DummyRcvToken.Ip4Token.Event);
1913cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1914fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
1915cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
19162a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang    IpInfo->Ip.Ip6->Configure (
19172a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                      IpInfo->Ip.Ip6,
19182a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                      NULL
19192a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang                      );
1920cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1921fb115c61504fe6c4f94be0a87f75e28e1684657ftye    IpIoCloseProtocolDestroyIpChild (
1922fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IpIo->Controller,
1923fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IpIo->Image,
1924fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IpInfo->ChildHandle,
1925fb115c61504fe6c4f94be0a87f75e28e1684657ftye      IP_VERSION_6
1926fb115c61504fe6c4f94be0a87f75e28e1684657ftye      );
1927fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1928fb115c61504fe6c4f94be0a87f75e28e1684657ftye    gBS->CloseEvent (IpInfo->DummyRcvToken.Ip6Token.Event);
1929fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
1930fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1931fb115c61504fe6c4f94be0a87f75e28e1684657ftye  FreePool (IpInfo);
1932cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1933cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1934cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1935cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1936cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Find the first IP protocol maintained in IpIo whose local
1937fb115c61504fe6c4f94be0a87f75e28e1684657ftye  address is the same as Src.
1938e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1939e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is called when the caller needs the IpIo to send data to the
1940e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  specified Src. The IpIo was added previously by IpIoAddIp().
1941cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
19426aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo              Pointer to the pointer of the IP_IO instance.
1943fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]       IpVersion         The version of the IP protocol to use, either
1944fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     IPv4 or IPv6.
19456aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Src               The local IP address.
1946cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1947cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return Pointer to the IP protocol can be used for sending purpose and its local
1948fb115c61504fe6c4f94be0a87f75e28e1684657ftye          address is the same with Src.
1949cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1950cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1951cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_IP_INFO *
19527b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1953cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoFindSender (
1954fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN OUT IP_IO           **IpIo,
1955b45b45b2d248892930620c33a9d01d8457ae0e54tye  IN     UINT8           IpVersion,
1956fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN     EFI_IP_ADDRESS  *Src
1957cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1958cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1959e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  LIST_ENTRY      *IpIoEntry;
1960cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO           *IpIoPtr;
1961e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  LIST_ENTRY      *IpInfoEntry;
1962cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO   *IpInfo;
1963cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1964fb115c61504fe6c4f94be0a87f75e28e1684657ftye  ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
1965fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1966cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_FOR_EACH (IpIoEntry, &mActiveIpIoList) {
1967cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoPtr = NET_LIST_USER_STRUCT (IpIoEntry, IP_IO, Entry);
1968cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1969fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (((*IpIo != NULL) && (*IpIo != IpIoPtr)) || (IpIoPtr->IpVersion != IpVersion)) {
1970cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      continue;
1971cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1972cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1973cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    NET_LIST_FOR_EACH (IpInfoEntry, &IpIoPtr->IpList) {
1974cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IpInfo = NET_LIST_USER_STRUCT (IpInfoEntry, IP_IO_IP_INFO, Entry);
1975fb115c61504fe6c4f94be0a87f75e28e1684657ftye      if (IpInfo->IpVersion == IP_VERSION_4){
1976fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1977fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (EFI_IP4_EQUAL (&IpInfo->Addr.v4, &Src->v4)) {
1978fb115c61504fe6c4f94be0a87f75e28e1684657ftye          *IpIo = IpIoPtr;
1979fb115c61504fe6c4f94be0a87f75e28e1684657ftye          return IpInfo;
1980fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1981fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1982fb115c61504fe6c4f94be0a87f75e28e1684657ftye      } else {
1983fb115c61504fe6c4f94be0a87f75e28e1684657ftye
1984fb115c61504fe6c4f94be0a87f75e28e1684657ftye        if (EFI_IP6_EQUAL (&IpInfo->Addr.v6, &Src->v6)) {
1985fb115c61504fe6c4f94be0a87f75e28e1684657ftye          *IpIo = IpIoPtr;
1986fb115c61504fe6c4f94be0a87f75e28e1684657ftye          return IpInfo;
1987fb115c61504fe6c4f94be0a87f75e28e1684657ftye        }
1988fb115c61504fe6c4f94be0a87f75e28e1684657ftye      }
1989cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1990cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1991cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1992cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1993cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1994cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // No match.
1995cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1996cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
1997cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1998cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1999cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2000cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
2001e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  Get the ICMP error map information.
2002e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
2003e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  The ErrorStatus will be returned. The IsHard and Notify are optional. If they
2004e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  are not NULL, this routine will fill them.
2005cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
20068f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[in]   IcmpError             IcmpError Type.
2007fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]   IpVersion             The version of the IP protocol to use,
20083b1464d5ac4e8b917c54b9f29a43ad972d2a2c85rsun                                     either IPv4 or IPv6.
20093b1464d5ac4e8b917c54b9f29a43ad972d2a2c85rsun  @param[out]  IsHard                If TRUE, indicates that it is a hard error.
20103b1464d5ac4e8b917c54b9f29a43ad972d2a2c85rsun  @param[out]  Notify                If TRUE, SockError needs to be notified.
2011cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
20126aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @return ICMP Error Status, such as EFI_NETWORK_UNREACHABLE.
2013cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2014cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
2015cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
20167b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
2017cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoGetIcmpErrStatus (
2018b45b45b2d248892930620c33a9d01d8457ae0e54tye  IN  UINT8       IcmpError,
2019b45b45b2d248892930620c33a9d01d8457ae0e54tye  IN  UINT8       IpVersion,
2020e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  OUT BOOLEAN     *IsHard  OPTIONAL,
2021e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  OUT BOOLEAN     *Notify  OPTIONAL
2022cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
2023cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
20243cf888f5f90526fa0d613c2a1486e0c1f416bd67tye  if (IpVersion == IP_VERSION_4 ) {
2025b45b45b2d248892930620c33a9d01d8457ae0e54tye    ASSERT (IcmpError <= ICMP_ERR_PARAMPROB);
2026687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
20273cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    if (IsHard != NULL) {
20283cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      *IsHard = mIcmpErrMap[IcmpError].IsHard;
20293cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    }
2030687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
20313cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    if (Notify != NULL) {
20323cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      *Notify = mIcmpErrMap[IcmpError].Notify;
20333cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    }
20343cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20353cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    switch (IcmpError) {
20363cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_UNREACH_NET:
20373cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return  EFI_NETWORK_UNREACHABLE;
20383cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20393cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_TIMXCEED_INTRANS:
20403cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_TIMXCEED_REASS:
20413cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_UNREACH_HOST:
20423cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return  EFI_HOST_UNREACHABLE;
20433cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20443cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_UNREACH_PROTOCOL:
20453cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return  EFI_PROTOCOL_UNREACHABLE;
20463cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20473cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_UNREACH_PORT:
20483cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return  EFI_PORT_UNREACHABLE;
20493cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20503cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_MSGSIZE:
20513cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_UNREACH_SRCFAIL:
20523cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_QUENCH:
20533cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP_ERR_PARAMPROB:
20543cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return  EFI_ICMP_ERROR;
20553cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20563cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    default:
20573cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      ASSERT (FALSE);
20583cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_UNSUPPORTED;
20593cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    }
2060687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
2061fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else if (IpVersion == IP_VERSION_6) {
2062fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2063b45b45b2d248892930620c33a9d01d8457ae0e54tye    ASSERT (IcmpError <= ICMP6_ERR_PARAMPROB_IPV6OPTION);
2064687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
2065fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (IsHard != NULL) {
2066fb115c61504fe6c4f94be0a87f75e28e1684657ftye      *IsHard = mIcmp6ErrMap[IcmpError].IsHard;
2067fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
2068fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2069fb115c61504fe6c4f94be0a87f75e28e1684657ftye    if (Notify != NULL) {
2070fb115c61504fe6c4f94be0a87f75e28e1684657ftye      *Notify = mIcmp6ErrMap[IcmpError].Notify;
2071fb115c61504fe6c4f94be0a87f75e28e1684657ftye    }
20723cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20733cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    switch (IcmpError) {
20743cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_UNREACH_NET:
20753cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_NETWORK_UNREACHABLE;
20763cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20773cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_UNREACH_HOST:
20783cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_TIMXCEED_HOPLIMIT:
20793cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_TIMXCEED_REASS:
20803cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_HOST_UNREACHABLE;
20813cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20823cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_UNREACH_PROTOCOL:
20833cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_PROTOCOL_UNREACHABLE;
20843cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20853cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_UNREACH_PORT:
20863cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_PORT_UNREACHABLE;
20873cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20883cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_PACKAGE_TOOBIG:
20893cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_PARAMPROB_HEADER:
20903cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_PARAMPROB_NEXHEADER:
20913cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    case ICMP6_ERR_PARAMPROB_IPV6OPTION:
20923cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_ICMP_ERROR;
20933cf888f5f90526fa0d613c2a1486e0c1f416bd67tye
20943cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    default:
20953cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      ASSERT (FALSE);
20963cf888f5f90526fa0d613c2a1486e0c1f416bd67tye      return EFI_UNSUPPORTED;
20973cf888f5f90526fa0d613c2a1486e0c1f416bd67tye    }
2098fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2099fb115c61504fe6c4f94be0a87f75e28e1684657ftye  } else {
2100fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
2101fb115c61504fe6c4f94be0a87f75e28e1684657ftye    // Should never be here
2102fb115c61504fe6c4f94be0a87f75e28e1684657ftye    //
2103fb115c61504fe6c4f94be0a87f75e28e1684657ftye    ASSERT (FALSE);
2104fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return EFI_UNSUPPORTED;
2105fb115c61504fe6c4f94be0a87f75e28e1684657ftye  }
2106fb115c61504fe6c4f94be0a87f75e28e1684657ftye}
2107cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2108cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2109fb115c61504fe6c4f94be0a87f75e28e1684657ftye/**
2110fb115c61504fe6c4f94be0a87f75e28e1684657ftye  Refresh the remote peer's Neighbor Cache entries.
2111fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2112fb115c61504fe6c4f94be0a87f75e28e1684657ftye  This function is called when the caller needs the IpIo to refresh the existing
2113fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IPv6 neighbor cache entries since the neighbor is considered reachable by the
2114fb115c61504fe6c4f94be0a87f75e28e1684657ftye  node has recently received a confirmation that packets sent recently to the
2115fb115c61504fe6c4f94be0a87f75e28e1684657ftye  neighbor were received by its IP layer.
2116fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2117fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]   IpIo                  Pointer to an IP_IO instance
2118fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]   Neighbor              The IP address of the neighbor
2119fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @param[in]   Timeout               Time in 100-ns units that this entry will
2120fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     remain in the neighbor cache. A value of
2121fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     zero means that the entry is permanent.
2122fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     A value of non-zero means that the entry is
2123fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     dynamic and will be deleted after Timeout.
2124fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2125fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval      EFI_SUCCESS           The operation is completed successfully.
2126fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval      EFI_NOT_STARTED       The IpIo is not configured.
2127fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval      EFI_INVALID_PARAMETER Neighbor Address is invalid.
2128fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval      EFI_NOT_FOUND         The neighbor cache entry is not in the
2129fb115c61504fe6c4f94be0a87f75e28e1684657ftye                                     neighbor table.
2130fb115c61504fe6c4f94be0a87f75e28e1684657ftye  @retval      EFI_OUT_OF_RESOURCES  Failed due to resource limit.
2131cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2132fb115c61504fe6c4f94be0a87f75e28e1684657ftye**/
2133fb115c61504fe6c4f94be0a87f75e28e1684657ftyeEFI_STATUS
2134fb115c61504fe6c4f94be0a87f75e28e1684657ftyeIpIoRefreshNeighbor (
2135fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN IP_IO           *IpIo,
2136fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN EFI_IP_ADDRESS  *Neighbor,
2137fb115c61504fe6c4f94be0a87f75e28e1684657ftye  IN UINT32          Timeout
2138fb115c61504fe6c4f94be0a87f75e28e1684657ftye  )
2139fb115c61504fe6c4f94be0a87f75e28e1684657ftye{
2140fb115c61504fe6c4f94be0a87f75e28e1684657ftye  EFI_IP6_PROTOCOL  *Ip;
2141fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2142fb115c61504fe6c4f94be0a87f75e28e1684657ftye  if (!IpIo->IsConfigured || IpIo->IpVersion != IP_VERSION_6) {
2143fb115c61504fe6c4f94be0a87f75e28e1684657ftye    return EFI_NOT_STARTED;
2144cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
2145cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
21462a2e33b20feb245572416333bf26eb8a77e73aa9qianouyang  Ip = IpIo->Ip.Ip6;
2147fb115c61504fe6c4f94be0a87f75e28e1684657ftye
2148fb115c61504fe6c4f94be0a87f75e28e1684657ftye  return Ip->Neighbors (Ip, FALSE, &Neighbor->v6, NULL, Timeout, TRUE);
2149cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
2150cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2151