DxeIpIoLib.c revision 687a2e5f6902fa26c7a1d7a7705e0747c4095125
1cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/** @file
2cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
3cbf316f20726bb31b7c37424601643790dbd02d9vanjeffCopyright (c) 2005 - 2007, Intel Corporation
4cbf316f20726bb31b7c37424601643790dbd02d9vanjeffAll rights reserved. This program and the accompanying materials
5cbf316f20726bb31b7c37424601643790dbd02d9vanjeffare licensed and made available under the terms and conditions of the BSD License
6cbf316f20726bb31b7c37424601643790dbd02d9vanjeffwhich accompanies this distribution.  The full text of the license may be found at
7cbf316f20726bb31b7c37424601643790dbd02d9vanjeffhttp://opensource.org/licenses/bsd-license.php
8cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
9cbf316f20726bb31b7c37424601643790dbd02d9vanjeffTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10cbf316f20726bb31b7c37424601643790dbd02d9vanjeffWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
12cbf316f20726bb31b7c37424601643790dbd02d9vanjeffModule Name:
13cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
14cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo.c
15cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
16cbf316f20726bb31b7c37424601643790dbd02d9vanjeffAbstract:
17cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
18cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  The implementation of the IpIo layer.
19cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
20cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
21cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
22cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
23cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <PiDxe.h>
24cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
25cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Protocol/Udp4.h>
26cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
27cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/IpIoLib.h>
28cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/BaseLib.h>
29cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/DebugLib.h>
30cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/UefiBootServicesTableLib.h>
31cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/MemoryAllocationLib.h>
32cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
33cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
34cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#define NET_PROTO_HDR(Buf, Type)  ((Type *) ((Buf)->BlockOp[0].Head))
35cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#define ICMP_ERRLEN(IpHdr) \
36cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  (sizeof(IP4_ICMP_HEAD) + EFI_IP4_HEADER_LEN(IpHdr) + 8)
37cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
38cbf316f20726bb31b7c37424601643790dbd02d9vanjeffNET_LIST_ENTRY  mActiveIpIoList = {
39cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  &mActiveIpIoList,
40cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  &mActiveIpIoList
41cbf316f20726bb31b7c37424601643790dbd02d9vanjeff};
42cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
43cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_IP4_CONFIG_DATA  mIpIoDefaultIpConfigData = {
44cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP_PROTO_UDP,
45cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
46cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TRUE,
47cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
48cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
49cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
50cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  {0, 0, 0, 0},
51cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  {0, 0, 0, 0},
52cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0,
53cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  255,
54cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
55cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
56cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0,
57cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0
58cbf316f20726bb31b7c37424601643790dbd02d9vanjeff};
59cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
60cbf316f20726bb31b7c37424601643790dbd02d9vanjeffSTATIC
61cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
62cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
63cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoTransmitHandler (
64cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_EVENT Event,
65cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
66cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  );
67cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
68cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
69cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
70cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  This function create an ip child ,open the IP protocol, return the opened
71cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip protocol to Interface.
72cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
73cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  ControllerHandle      The controller handle.
74cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  ImageHandle           The image handle.
75cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  ChildHandle           Pointer to the buffer to save the ip child handle.
76cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Interface             Pointer used to get the ip protocol interface.
77cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
78cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval EFI_SUCCESS           The ip child is created and the ip protocol
79cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                interface is retrieved.
80cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval other                 The required operation failed.
81cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
82cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
83cbf316f20726bb31b7c37424601643790dbd02d9vanjeffSTATIC
84cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
85cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreateIpChildOpenProtocol (
86cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  ControllerHandle,
87cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  ImageHandle,
88cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  *ChildHandle,
89cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  OUT VOID        **Interface
90cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
91cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
92cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
93cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
94cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
95cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create an ip child.
96cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
97cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = NetLibCreateServiceChild (
98cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ControllerHandle,
99cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ImageHandle,
100cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &gEfiIp4ServiceBindingProtocolGuid,
101cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ChildHandle
102cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
103cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
104cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
105cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
106cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
107cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
108cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Open the ip protocol installed on the *ChildHandle.
109cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
110cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->OpenProtocol (
111cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  *ChildHandle,
112cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  &gEfiIp4ProtocolGuid,
113cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  Interface,
114cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  ImageHandle,
115cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  ControllerHandle,
116cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EFI_OPEN_PROTOCOL_BY_DRIVER
117cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
118cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
119cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
120cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // On failure, destroy the ip child.
121cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
122cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    NetLibDestroyServiceChild (
123cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      ControllerHandle,
124cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      ImageHandle,
125cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      &gEfiIp4ServiceBindingProtocolGuid,
126cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      *ChildHandle
127cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      );
128cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
129cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
130cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
131cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
132cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
133cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
134cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
135cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  This function close the previously openned ip protocol and destroy the ip child.
136cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
137cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  ControllerHandle      The controller handle.
138cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  ImageHandle           the image handle.
139cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  ChildHandle           The child handle of the ip child.
140cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
141cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval EFI_SUCCESS           The ip protocol is closed and the relevant ip child
142cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                is destroyed.
143cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval other                 The required operation failed.
144cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
145cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
146cbf316f20726bb31b7c37424601643790dbd02d9vanjeffSTATIC
147cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
148cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCloseProtocolDestroyIpChild (
149cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ControllerHandle,
150cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ImageHandle,
151cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ChildHandle
152cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
153cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
154cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
155cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
156cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
157cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Close the previously openned ip protocol.
158cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
159cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseProtocol (
160cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ChildHandle,
161cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         &gEfiIp4ProtocolGuid,
162cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ImageHandle,
163cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ControllerHandle
164cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         );
165cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
166cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
167cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Destroy the ip child.
168cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
169cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = NetLibDestroyServiceChild (
170cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ControllerHandle,
171cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ImageHandle,
172cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &gEfiIp4ServiceBindingProtocolGuid,
173cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ChildHandle
174cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
175cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
176cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
177cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
178cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
179cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
180cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
181cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Handle ICMP packets.
182cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
183cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IpIo                  Pointer to the IP_IO instance.
184cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Pkt                   Pointer to the ICMP packet.
185cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Session               Pointer to the net session of this ICMP packet.
186cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
187cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval EFI_SUCCESS           The ICMP packet is handled successfully.
188cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval EFI_ABORTED           This type of ICMP packet is not supported.
189cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
190cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
191cbf316f20726bb31b7c37424601643790dbd02d9vanjeffSTATIC
192cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
193cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoIcmpHandler (
194cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO                *IpIo,
195cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN NET_BUF              *Pkt,
196cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_NET_SESSION_DATA *Session
197cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
198cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
199cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP4_ICMP_ERROR_HEAD  *IcmpHdr;
200cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_HEADER       *IpHdr;
201cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ICMP_ERROR           IcmpErr;
202cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                *PayLoadHdr;
203cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                Type;
204cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                Code;
205cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT32               TrimBytes;
206cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
207cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IcmpHdr = NET_PROTO_HDR (Pkt, IP4_ICMP_ERROR_HEAD);
208cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpHdr   = (EFI_IP4_HEADER *) (&IcmpHdr->IpHead);
209cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
210cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
211cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Check the ICMP packet length.
212cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
213cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (Pkt->TotalSize < ICMP_ERRLEN (IpHdr)) {
214cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
215cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ABORTED;
216cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
217cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
218cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Type = IcmpHdr->Head.Type;
219cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Code = IcmpHdr->Head.Code;
220cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
221cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
222cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Analyze the ICMP Error in this ICMP pkt
223cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
224cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  switch (Type) {
225cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_UNREACH:
226cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    switch (Code) {
227cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET:
228cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST:
229cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_PROTOCOL:
230cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_PORT:
231cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_SRCFAIL:
2324eb65aff715faafd9040c6fc85a5d59e22343978vanjeff      IcmpErr = (ICMP_ERROR) (ICMP_ERR_UNREACH_NET + Code);
233cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
234cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
235cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
236cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NEEDFRAG:
237cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_MSGSIZE;
238cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
239cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
240cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
241cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET_UNKNOWN:
242cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET_PROHIB:
243cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_TOSNET:
244cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_UNREACH_NET;
245cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
246cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
247cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
248cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST_UNKNOWN:
249cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_ISOLATED:
250cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST_PROHIB:
251cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_TOSHOST:
252cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_UNREACH_HOST;
253cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
254cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
255cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
256cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    default:
257cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
258cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
259cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
260cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
261cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
262cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
263cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
264cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_TIMXCEED:
265cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code > 1) {
266cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
267cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
268cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2694eb65aff715faafd9040c6fc85a5d59e22343978vanjeff    IcmpErr = (ICMP_ERROR) (Code + ICMP_ERR_TIMXCEED_INTRANS);
270cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
271cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
272cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
273cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_PARAMPROB:
274cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code > 1) {
275cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
276cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
277cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
278cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IcmpErr = ICMP_ERR_PARAMPROB;
279cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
280cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
281cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
282cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_SOURCEQUENCH:
283cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code != 0) {
284cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
285cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
286cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
287cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IcmpErr = ICMP_ERR_QUENCH;
288cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
289cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
290cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
291cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  default:
292cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ABORTED;
293cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
294cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
295cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
296cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
297cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
298cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Notify user the ICMP pkt only containing payload except
299cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // IP and ICMP header
300cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
301cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  PayLoadHdr = (UINT8 *) ((UINT8 *) IpHdr + EFI_IP4_HEADER_LEN (IpHdr));
302cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TrimBytes  = (UINT32) (PayLoadHdr - (UINT8 *) IcmpHdr);
303cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
304cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetbufTrim (Pkt, TrimBytes, TRUE);
305cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
306cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);
307cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
308cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
309cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
310cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
311cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
312cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
313cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ext free function for net buffer. This function is
314cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  called when the net buffer is freed. It is used to
315cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  signal the recycle event to notify IP to recycle the
316cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  data buffer.
317cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
318cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Event                 The event to be signaled.
319cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
320cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return None.
321cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
322cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
323cbf316f20726bb31b7c37424601643790dbd02d9vanjeffSTATIC
324cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
325cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoExtFree (
326cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID  *Event
327cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
328cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
329cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->SignalEvent ((EFI_EVENT) Event);
330cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
331cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
332cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
333cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
334cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Create a send entry to wrap a packet before sending
335cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  out it through IP.
336cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
337cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IpIo                  Pointer to the IP_IO instance.
338cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Pkt                   Pointer to the packet.
339cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Sender                Pointer to the IP sender.
340cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  NotifyData            Pointer to the notify data.
341cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Dest                  Pointer to the destination IP address.
342cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Override              Pointer to the overriden IP_IO data.
343cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
344cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return Pointer to the data structure created to wrap the packet. If NULL,
345cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return resource limit occurred.
346cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
347cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
348cbf316f20726bb31b7c37424601643790dbd02d9vanjeffSTATIC
349cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_SEND_ENTRY *
350cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreateSndEntry (
351cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO             *IpIo,
352cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN NET_BUF           *Pkt,
353cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_IP4_PROTOCOL  *Sender,
354cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID              *Context    OPTIONAL,
355cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID              *NotifyData OPTIONAL,
356cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP4_ADDR          Dest,
357cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO_OVERRIDE    *Override
358cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
359cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
360cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY          *SndEntry;
361cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_COMPLETION_TOKEN  *SndToken;
362cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_TRANSMIT_DATA     *TxData;
363cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS                Status;
364cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_OVERRIDE_DATA     *OverrideData;
36534edf2ae729941a6203e4e7f614db32204a9c47dvanjeff  volatile UINT32           Index;
366cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
367cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
368cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for SndEntry
369cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
370cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry = NetAllocatePool (sizeof (IP_IO_SEND_ENTRY));
371cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndEntry) {
372cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return NULL;
373cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
374cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
375cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
376cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for SndToken
377cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
378cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndToken = NetAllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN));
379cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndToken) {
380cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseSndEntry;
381cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
382cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
383cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
384cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
385cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  NET_TPL_EVENT,
386cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoTransmitHandler,
387cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  SndEntry,
388cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  &(SndToken->Event)
389cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
390cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
391cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseSndToken;
392cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
393cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
394cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
395cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for TxData
396cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
397cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData = NetAllocatePool (
398cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    sizeof (EFI_IP4_TRANSMIT_DATA) +
399cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    sizeof (EFI_IP4_FRAGMENT_DATA) * (Pkt->BlockOpNum - 1)
400cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    );
401cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
402cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == TxData) {
403cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseEvent;
404cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
405cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
406cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
407cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for OverrideData if needed
408cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
409cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  OverrideData = NULL;
410cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL != Override) {
411cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
412cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    OverrideData = NetAllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA));
413cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (NULL == OverrideData) {
414cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      goto ReleaseResource;
415cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
416cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
417cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // Set the fields of OverrideData
418cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
419cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    *OverrideData = * (EFI_IP4_OVERRIDE_DATA *) Override;
420cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
421cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
422cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
423cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Set the fields of TxData
424cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
425cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4 (TxData->DestinationAddress)  = Dest;
426cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->OverrideData                  = OverrideData;
427cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->OptionsLength                 = 0;
428cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->OptionsBuffer                 = NULL;
429cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->TotalDataLength               = Pkt->TotalSize;
430cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->FragmentCount                 = Pkt->BlockOpNum;
431cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
432cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
43334edf2ae729941a6203e4e7f614db32204a9c47dvanjeff  for (Index = 0; Index < Pkt->BlockOpNum; Index++) {
434cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    TxData->FragmentTable[Index].FragmentBuffer = Pkt->BlockOp[Index].Head;
435cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    TxData->FragmentTable[Index].FragmentLength = Pkt->BlockOp[Index].Size;
436cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
437cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
438cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
439cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Set the fields of SndToken
440cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
441cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndToken->Packet.TxData = TxData;
442cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
443cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
444cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Set the fields of SndEntry
445cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
446cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->IpIo        = IpIo;
447cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->Ip      = Sender;
448cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->Context     = Context;
449cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->NotifyData  = NotifyData;
450cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
451cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->Pkt         = Pkt;
452cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_GET_REF (Pkt);
453cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
454cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->SndToken = SndToken;
455cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
456cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetListInsertTail (&IpIo->PendingSndList, &SndEntry->Entry);
457cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
458cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return SndEntry;
459cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
460cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseResource:
461cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetFreePool (TxData);
462cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
463cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseEvent:
464cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseEvent (SndToken->Event);
465cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
466cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseSndToken:
467cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetFreePool (SndToken);
468cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
469cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseSndEntry:
470cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetFreePool (SndEntry);
471cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
472cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
473cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
474cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
475cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
476cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
477cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy the SndEntry.
478cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
479cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  SndEntry              Pointer to the send entry to be destroyed.
480cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
481cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return None.
482cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
483cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
484cbf316f20726bb31b7c37424601643790dbd02d9vanjeffSTATIC
485cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
486cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoDestroySndEntry (
487cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO_SEND_ENTRY  *SndEntry
488cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
489cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
490cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_TRANSMIT_DATA  *TxData;
491cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
492cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData = SndEntry->SndToken->Packet.TxData;
493cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
494cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL != TxData->OverrideData) {
495cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    NetFreePool (TxData->OverrideData);
496cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
497cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
498cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetFreePool (TxData);
499cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetbufFree (SndEntry->Pkt);
500cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseEvent (SndEntry->SndToken->Event);
501cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
502cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetFreePool (SndEntry->SndToken);
503cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetListRemoveEntry (&SndEntry->Entry);
504cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
505cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetFreePool (SndEntry);
506cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
507cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
508cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
509cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
510cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Notify function for IP transmit token.
511cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
512cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Event                 The event signaled.
513cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Context               The context passed in by the event notifier.
514cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
515cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return None.
516cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
517cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
518cbf316f20726bb31b7c37424601643790dbd02d9vanjeffSTATIC
519cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
520cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
521cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoTransmitHandler (
522cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_EVENT Event,
523cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
524cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
525cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
526cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO             *IpIo;
527cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
528cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
529cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry  = (IP_IO_SEND_ENTRY *) Context;
530cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
531cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo      = SndEntry->IpIo;
532cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
533cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpIo->PktSentNotify && SndEntry->NotifyData) {
534cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->PktSentNotify (
535cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->SndToken->Status,
536cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->Context,
537cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->Ip,
538cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->NotifyData
539cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            );
540cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
541cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
542cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoDestroySndEntry (SndEntry);
543cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
544cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
545cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
546cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
547cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  The dummy handler for the dummy IP receive token.
548cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
549cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Evt                   The event signaled.
550cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Context               The context passed in by the event notifier.
551cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
552cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return None.
553cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
554cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
555cbf316f20726bb31b7c37424601643790dbd02d9vanjeffSTATIC
556cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
557cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
558cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoDummyHandler (
559cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_EVENT Event,
560cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
561cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
562cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
563cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO             *IpInfo;
564cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_COMPLETION_TOKEN  *DummyToken;
565cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
566cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ASSERT (Event && Context);
567cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
568cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo      = (IP_IO_IP_INFO *) Context;
569cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  DummyToken  = &(IpInfo->DummyRcvToken);
570cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
571cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_SUCCESS == DummyToken->Status) {
572cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    ASSERT (DummyToken->Packet.RxData);
573cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
574cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    gBS->SignalEvent (DummyToken->Packet.RxData->RecycleSignal);
575cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
576cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
577cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->Ip->Receive (IpInfo->Ip, DummyToken);
578cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
579cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
580cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
581cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
582cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Notify function for the IP receive token, used to process
583cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  the received IP packets.
584cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
585cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Event                 The event signaled.
586cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Context               The context passed in by the event notifier.
587cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
588cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return None.
589cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
590cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
591cbf316f20726bb31b7c37424601643790dbd02d9vanjeffSTATIC
592cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
593cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
594cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoListenHandler (
595cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_EVENT Event,
596cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
597cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
598cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
599cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO                 *IpIo;
600cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS            Status;
601cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_RECEIVE_DATA  *RxData;
602cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL      *Ip;
603cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_NET_SESSION_DATA  Session;
604cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_BUF               *Pkt;
605cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
606cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo    = (IP_IO *) Context;
607cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
608cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip      = IpIo->Ip;
609cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status  = IpIo->RcvToken.Status;
610cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  RxData  = IpIo->RcvToken.Packet.RxData;
611cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
612cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (((EFI_SUCCESS != Status) && (EFI_ICMP_ERROR != Status)) || (NULL == RxData)) {
613cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
614cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // Only process the normal packets and the icmp error packets, if RxData is NULL
615cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
616cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // this should be a bug of the low layer (IP).
617cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
618cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto Resume;
619cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
620cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
621cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == IpIo->PktRcvdNotify) {
622cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
623cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
624cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
625cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if ((EFI_IP4 (RxData->Header->SourceAddress) != 0) &&
626cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    !Ip4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), 0)) {
627cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
628cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // The source address is not zero and it's not a unicast IP address, discard it.
629cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
630cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
631cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
632cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
633cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
634cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create a netbuffer representing packet
635cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
636cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Pkt = NetbufFromExt (
637cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          (NET_FRAGMENT *) RxData->FragmentTable,
638cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          RxData->FragmentCount,
639cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          0,
640cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          0,
641cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          IpIoExtFree,
642cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          RxData->RecycleSignal
643cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          );
644cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == Pkt) {
645cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
646cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
647cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
648cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
649cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create a net session
650cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
651cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Session.Source = EFI_IP4 (RxData->Header->SourceAddress);
652cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Session.Dest   = EFI_IP4 (RxData->Header->DestinationAddress);
653cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Session.IpHdr  = RxData->Header;
654cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
655cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_SUCCESS == Status) {
656cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
6574eb65aff715faafd9040c6fc85a5d59e22343978vanjeff    IpIo->PktRcvdNotify (EFI_SUCCESS, (ICMP_ERROR) 0, &Session, Pkt, IpIo->RcvdContext);
658cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  } else {
659cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
660cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // Status is EFI_ICMP_ERROR
661cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
662cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    Status = IpIoIcmpHandler (IpIo, Pkt, &Session);
663cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (EFI_ERROR (Status)) {
664cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      NetbufFree (Pkt);
665cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
666cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
667cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
668cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  goto Resume;
669cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
670cbf316f20726bb31b7c37424601643790dbd02d9vanjeffCleanUp:
671cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->SignalEvent (RxData->RecycleSignal);
672cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
673cbf316f20726bb31b7c37424601643790dbd02d9vanjeffResume:
674cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip->Receive (Ip, &(IpIo->RcvToken));
675cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
676cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
677cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
678cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
679cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Create a new IP_IO instance.
680cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
681cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Image                 The image handle of an IP_IO consumer protocol.
682cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Controller            The controller handle of an IP_IO consumer protocol
683cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                installed on.
684cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
685cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return Pointer to a newly created IP_IO instance.
686cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
687cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
688cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO *
689cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreate (
690cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE Image,
691cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE Controller
692cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
693cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
694cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
695cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO       *IpIo;
696cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
697cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo = NetAllocateZeroPool (sizeof (IP_IO));
698cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == IpIo) {
699cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return NULL;
700cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
701cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
702cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetListInit (&(IpIo->PendingSndList));
703cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetListInit (&(IpIo->IpList));
704cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Controller  = Controller;
705cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Image       = Image;
706cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
707cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
708cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
709cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  NET_TPL_EVENT,
710cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoListenHandler,
711cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIo,
712cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  &(IpIo->RcvToken.Event)
713cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
714cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
715cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpIo;
716cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
717cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
718cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
719cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create an IP child and open IP protocol
720cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
721cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = IpIoCreateIpChildOpenProtocol (
722cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             Controller,
723cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             Image,
724cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &IpIo->ChildHandle,
725cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             (VOID **)&(IpIo->Ip)
726cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
727cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
728cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpIo;
729cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
730cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
731cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return IpIo;
732cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
733cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpIo:
734cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
735cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL != IpIo->RcvToken.Event) {
736cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    gBS->CloseEvent (IpIo->RcvToken.Event);
737cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
738cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
739cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetFreePool (IpIo);
740cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
741cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
742cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
743cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
744cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
745cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
746cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Open an IP_IO instance for use.
747cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
748cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IpIo                  Pointer to an IP_IO instance that needs to open.
749cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  OpenData              The configuration data for the IP_IO instance.
750cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
751cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval EFI_SUCCESS           The IP_IO instance opened with OpenData
752cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                successfully.
753cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval other                 Error condition occurred.
754cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
755cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
756cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
757cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoOpen (
758cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO           *IpIo,
759cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO_OPEN_DATA *OpenData
760cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
761cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
762cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
763cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL  *Ip;
764cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IPv4_ADDRESS  ZeroIp;
765cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
766cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpIo->IsConfigured) {
767cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ACCESS_DENIED;
768cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
769cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
770cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpIo->Ip;
771cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
772cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
773cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // configure ip
774cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
775cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Configure (Ip, &OpenData->IpConfigData);
776cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
777cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
778cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
779cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
780cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
781cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // bugbug: to delete the default route entry in this Ip, if it is:
782cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified
783cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // its code
784cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
785cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4 (ZeroIp) = 0;
786cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Routes (Ip, TRUE, &ZeroIp, &ZeroIp, &ZeroIp);
787cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
788cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status) && (EFI_NOT_FOUND != Status)) {
789cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
790cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
791cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
792cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktRcvdNotify = OpenData->PktRcvdNotify;
793cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktSentNotify = OpenData->PktSentNotify;
794cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
795cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->RcvdContext   = OpenData->RcvdContext;
796cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->SndContext    = OpenData->SndContext;
797cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
798cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Protocol      = OpenData->IpConfigData.DefaultProtocol;
799cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
800cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
801cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // start to listen incoming packet
802cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
803cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Receive (Ip, &(IpIo->RcvToken));
804cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
805cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    Ip->Configure (Ip, NULL);
806cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ErrorExit;
807cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
808cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
809cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->IsConfigured = TRUE;
810cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetListInsertTail (&mActiveIpIoList, &IpIo->Entry);
811cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
812cbf316f20726bb31b7c37424601643790dbd02d9vanjeffErrorExit:
813cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
814cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
815cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
816cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
817cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
818cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
819cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Stop an IP_IO instance.
820cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
821cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IpIo                  Pointer to the IP_IO instance that needs to stop.
822cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
823cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval EFI_SUCCESS           The IP_IO instance stopped successfully.
824cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval other                 Error condition occurred.
825cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
826cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
827cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
828cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoStop (
829cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO *IpIo
830cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
831cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
832cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
833cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL  *Ip;
834cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO     *IpInfo;
835cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
836cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (!IpIo->IsConfigured) {
837cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_SUCCESS;
838cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
839cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
840cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
841cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Remove the IpIo from the active IpIo list.
842cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
843cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetListRemoveEntry (&IpIo->Entry);
844cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
845cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpIo->Ip;
846cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
847cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
848cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Configure NULL Ip
849cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
850cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Configure (Ip, NULL);
851cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
852cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
853cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
854cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
855cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->IsConfigured = FALSE;
856cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
857cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
858cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Detroy the Ip List used by IpIo
859cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
86034edf2ae729941a6203e4e7f614db32204a9c47dvanjeff
861cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  while (!NetListIsEmpty (&(IpIo->IpList))) {
862cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo = NET_LIST_HEAD (&(IpIo->IpList), IP_IO_IP_INFO, Entry);
863cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
864cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoRemoveIp (IpIo, IpInfo);
865cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
866cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
867cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
868cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // All pending snd tokens should be flushed by reseting the IP instances.
869cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
870cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ASSERT (NetListIsEmpty (&IpIo->PendingSndList));
871cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
872cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
873cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Close the receive event.
874cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
875cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseEvent (IpIo->RcvToken.Event);
876cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
877cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
878cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
879cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
880cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
881cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
882cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy an IP_IO instance.
883cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
884cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IpIo                  Pointer to the IP_IO instance that needs to
885cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                destroy.
886cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
887cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval EFI_SUCCESS           The IP_IO instance destroyed successfully.
888cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval other                 Error condition occurred.
889cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
890cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
891cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
892cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoDestroy (
893cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO *IpIo
894cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
895cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
896cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
897cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Stop the IpIo.
898cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
899cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoStop (IpIo);
900cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
901cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
902cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Close the IP protocol and destroy the child.
903cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
904cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpIo->ChildHandle);
905cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
906cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetFreePool (IpIo);
907cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
908cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
909cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
910cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
911cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
912cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
913cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Send out an IP packet.
914cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
915cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IpIo                  Pointer to an IP_IO instance used for sending IP
916cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                packet.
917cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Pkt                   Pointer to the IP packet to be sent.
918cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Sender                The IP protocol instance used for sending.
919cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  NotifyData
920cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Dest                  The destination IP address to send this packet to.
921cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  OverrideData          The data to override some configuration of the IP
922cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                instance used for sending.
923cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
924cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval EFI_SUCCESS           The operation is completed successfully.
925cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval EFI_NOT_STARTED       The IpIo is not configured.
926cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval EFI_OUT_OF_RESOURCES  Failed due to resource limit.
927cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
928cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
929cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
930cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoSend (
931cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO           *IpIo,
932cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN NET_BUF         *Pkt,
933cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO_IP_INFO   *Sender,
934cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID            *Context    OPTIONAL,
935cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID            *NotifyData OPTIONAL,
936cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP4_ADDR        Dest,
937cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO_OVERRIDE  *OverrideData
938cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
939cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
940cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
941cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL  *Ip;
942cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
943cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
944cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (!IpIo->IsConfigured) {
945cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_NOT_STARTED;
946cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
947cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
948cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = (NULL == Sender) ? IpIo->Ip : Sender->Ip;
949cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
950cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
951cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // create a new SndEntry
952cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
953cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry = IpIoCreateSndEntry (IpIo, Pkt, Ip, Context, NotifyData, Dest, OverrideData);
954cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndEntry) {
955cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_OUT_OF_RESOURCES;
956cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
957cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
958cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
959cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Send this Packet
960cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
961cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Transmit (Ip, SndEntry->SndToken);
962cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
963cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoDestroySndEntry (SndEntry);
964cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
965cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
966cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
967cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
968cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
969cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
970cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
971cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Cancel the IP transmit token which wraps this Packet.
972cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
973cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IpIo                  Pointer to the IP_IO instance.
974cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Packet                Pointer to the packet to cancel.
975cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
976cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return N/A.
977cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
978cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
979cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
980cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCancelTxToken (
981cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO  *IpIo,
982cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID   *Packet
983cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
984cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
985cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_ENTRY    *Node;
986cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
987cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL  *Ip;
988cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
989cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ASSERT (IpIo && Packet);
990cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
991cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_FOR_EACH (Node, &IpIo->PendingSndList) {
992cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
993cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    SndEntry = NET_LIST_USER_STRUCT (Node, IP_IO_SEND_ENTRY, Entry);
994cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
995cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (SndEntry->Pkt == Packet) {
996cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
997cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip = SndEntry->Ip;
998cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip->Cancel (Ip, SndEntry->SndToken);
999cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1000cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      //
1001cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      // Abort the user token.
1002cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      //
1003cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      SndEntry->SndToken->Status = EFI_ABORTED;
1004cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IpIoTransmitHandler (NULL, SndEntry);
1005cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1006cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
1007cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1008cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1009cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1010cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1011cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1012cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1013cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1014cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Add a new IP instance for sending data.
1015cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1016cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IpIo                  Pointer to a IP_IO instance to add a new IP
1017cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                instance for sending purpose.
1018cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1019cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return Pointer to the created IP_IO_IP_INFO structure, NULL is failed.
1020cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1021cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1022cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_IP_INFO *
1023cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoAddIp (
1024cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO  *IpIo
1025cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1026cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1027cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS     Status;
1028cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO  *IpInfo;
1029cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1030cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ASSERT (IpIo);
1031cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1032cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo = NetAllocatePool (sizeof (IP_IO_IP_INFO));
1033cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo == NULL) {
1034cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return IpInfo;
1035cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1036cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1037cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1038cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP
1039cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // instance.
1040cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1041cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetListInit (&IpInfo->Entry);
1042cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->ChildHandle = NULL;
1043cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->Addr        = 0;
1044cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->SubnetMask  = 0;
1045cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->RefCnt      = 1;
1046cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1047cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1048cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create the IP instance and open the Ip4 protocol.
1049cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1050cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = IpIoCreateIpChildOpenProtocol (
1051cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             IpIo->Controller,
1052cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             IpIo->Image,
1053cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &IpInfo->ChildHandle,
10544eb65aff715faafd9040c6fc85a5d59e22343978vanjeff             (VOID **) &IpInfo->Ip
1055cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
1056cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1057cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpInfo;
1058cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1059cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1060cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1061cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create the event for the DummyRcvToken.
1062cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1063cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
1064cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
1065cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  NET_TPL_EVENT,
1066cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoDummyHandler,
1067cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpInfo,
1068cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  &IpInfo->DummyRcvToken.Event
1069cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
1070cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1071cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpChild;
1072cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1073cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1074cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1075cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Link this IpInfo into the IpIo.
1076cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1077cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetListInsertTail (&IpIo->IpList, &IpInfo->Entry);
1078cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1079cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return IpInfo;
1080cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1081cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpChild:
1082cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1083cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoCloseProtocolDestroyIpChild (
1084cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->Controller,
1085cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->Image,
1086cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo->ChildHandle
1087cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    );
1088cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1089cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpInfo:
1090cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1091cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetFreePool (IpInfo);
1092cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1093cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
1094cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1095cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1096cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1097cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1098cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Configure the IP instance of this IpInfo and start the receiving if Ip4ConfigData
1099cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  is not NULL.
1100cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1101cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IpInfo                Pointer to the IP_IO_IP_INFO instance.
1102cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Ip4ConfigData         The IP4 configure data used to configure the ip
1103cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                instance, if NULL the ip instance is reseted. If
1104cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                UseDefaultAddress is set to TRUE, and the configure
1105cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                operation succeeds, the default address information
1106cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                is written back in this Ip4ConfigData.
1107cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1108cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @retval EFI_STATUS            The status returned by IP4->Configure or
1109cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                                IP4->Receive.
1110cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1111cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1112cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
1113cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoConfigIp (
1114cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN     IP_IO_IP_INFO        *IpInfo,
1115cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN OUT EFI_IP4_CONFIG_DATA  *Ip4ConfigData OPTIONAL
1116cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1117cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1118cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS         Status;
1119cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL   *Ip;
1120cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_MODE_DATA  Ip4ModeData;
1121cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1122cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ASSERT (IpInfo);
1123cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1124cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo->RefCnt > 1) {
1125cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1126cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // This IP instance is shared, don't reconfigure it until it has only one
1127cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // consumer. Currently, only the tcp children cloned from their passive parent
1128cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,
1129cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // let the last consumer clean the IP instance.
1130cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1131cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_SUCCESS;
1132cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1133cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1134cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpInfo->Ip;
1135cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1136cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Configure (Ip, Ip4ConfigData);
1137cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1138cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto OnExit;
1139cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1140cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1141cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (Ip4ConfigData != NULL) {
1142cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1143cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Ip4ConfigData->UseDefaultAddress) {
1144cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip->GetModeData (Ip, &Ip4ModeData, NULL, NULL);
1145cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1146cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip4ConfigData->StationAddress = Ip4ModeData.ConfigData.StationAddress;
1147cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip4ConfigData->SubnetMask     = Ip4ModeData.ConfigData.SubnetMask;
1148cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1149cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1150cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo->Addr       = EFI_IP4 (Ip4ConfigData->StationAddress);
1151cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo->SubnetMask = EFI_IP4 (Ip4ConfigData->SubnetMask);
1152cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1153cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    Status = Ip->Receive (Ip, &IpInfo->DummyRcvToken);
1154cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (EFI_ERROR (Status)) {
1155cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip->Configure (Ip, NULL);
1156cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1157cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  } else {
1158cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1159cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1160cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // The IP instance is reseted, set the stored Addr and SubnetMask to zero.
1161cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1162cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo->Addr       = 0;
1163cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo->SubnetMask =0;
1164cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1165cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1166cbf316f20726bb31b7c37424601643790dbd02d9vanjeffOnExit:
1167cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1168cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
1169cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1170cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1171cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1172cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1173cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy an IP instance maintained in IpIo->IpList for
1174cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  sending purpose.
1175cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1176cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IpIo                  Pointer to the IP_IO instance.
1177cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IpInfo                Pointer to the IpInfo to be removed.
1178cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1179cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return None.
1180cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1181cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1182cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
1183cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoRemoveIp (
1184cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO          *IpIo,
1185cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO_IP_INFO  *IpInfo
1186cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1187cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1188cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ASSERT (IpInfo->RefCnt > 0);
1189cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1190cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_PUT_REF (IpInfo);
1191cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1192cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo->RefCnt > 0) {
1193cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1194cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return;
1195cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1196cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1197cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetListRemoveEntry (&IpInfo->Entry);
1198cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1199cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->Ip->Configure (IpInfo->Ip, NULL);
1200cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1201cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpInfo->ChildHandle);
1202cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1203cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseEvent (IpInfo->DummyRcvToken.Event);
1204cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1205cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetFreePool (IpInfo);
1206cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1207cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1208cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1209cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1210cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Find the first IP protocol maintained in IpIo whose local
1211cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  address is the same with Src.
1212cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1213cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IpIo                  Pointer to the pointer of the IP_IO instance.
1214cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Src                   The local IP address.
1215cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1216cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return Pointer to the IP protocol can be used for sending purpose and its local
1217cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return address is the same with Src.
1218cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1219cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1220cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_IP_INFO *
1221cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoFindSender (
1222cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN OUT IP_IO     **IpIo,
1223cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN     IP4_ADDR  Src
1224cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1225cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1226cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_ENTRY  *IpIoEntry;
1227cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO           *IpIoPtr;
1228cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_ENTRY  *IpInfoEntry;
1229cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO   *IpInfo;
1230cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1231cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_FOR_EACH (IpIoEntry, &mActiveIpIoList) {
1232cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoPtr = NET_LIST_USER_STRUCT (IpIoEntry, IP_IO, Entry);
1233cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1234cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if ((*IpIo != NULL) && (*IpIo != IpIoPtr)) {
1235cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      continue;
1236cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1237cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1238cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    NET_LIST_FOR_EACH (IpInfoEntry, &IpIoPtr->IpList) {
1239cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IpInfo = NET_LIST_USER_STRUCT (IpInfoEntry, IP_IO_IP_INFO, Entry);
1240cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1241cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      if (IpInfo->Addr == Src) {
1242cbf316f20726bb31b7c37424601643790dbd02d9vanjeff        *IpIo = IpIoPtr;
1243cbf316f20726bb31b7c37424601643790dbd02d9vanjeff        return IpInfo;
1244cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      }
1245cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1246cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1247cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1248cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1249cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // No match.
1250cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1251cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
1252cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1253cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1254cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1255cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1256cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Get the ICMP error map information, the ErrorStatus will be returned.
1257cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  The IsHard and Notify are optional. If they are not NULL, this rouine will
1258cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  fill them.
1259cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  We move IcmpErrMap[] to local variable to enable EBC build.
1260cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1261cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IcmpError             IcmpError Type
1262cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  IsHard                Whether it is a hard error
1263cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @param  Notify                Whether it need to notify SockError
1264cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1265cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return ICMP Error Status
1266cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1267cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1268cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
1269cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoGetIcmpErrStatus (
1270cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  ICMP_ERROR  IcmpError,
1271cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  OUT BOOLEAN     *IsHard, OPTIONAL
1272cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  OUT BOOLEAN     *Notify OPTIONAL
1273cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1274cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1275687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  ICMP_ERROR_INFO  IcmpErrMap[10];
1276687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
1277687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[0].Error  = EFI_NETWORK_UNREACHABLE;
1278687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[0].IsHard = FALSE;
1279687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[0].Notify = TRUE;
1280687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
1281687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[1].Error = EFI_HOST_UNREACHABLE;
1282687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[1].IsHard = FALSE;
1283687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[1].Notify = TRUE;
1284687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
1285687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[2].Error = EFI_PROTOCOL_UNREACHABLE;
1286687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[2].IsHard = TRUE;
1287687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[2].Notify = TRUE;
1288687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
1289687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[3].Error = EFI_PORT_UNREACHABLE;
1290687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[3].IsHard = TRUE;
1291687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[3].Notify = TRUE;
1292687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
1293687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[4].Error = EFI_ICMP_ERROR;
1294687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[4].IsHard = TRUE;
1295687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[4].Notify = TRUE;
1296687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
1297687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[5].Error = EFI_ICMP_ERROR;
1298687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[5].IsHard = FALSE;
1299687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[5].Notify = TRUE;
1300687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
1301687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[6].Error = EFI_HOST_UNREACHABLE;
1302687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[6].IsHard = FALSE;
1303687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[6].Notify = TRUE;
1304687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
1305687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[7].Error = EFI_HOST_UNREACHABLE;
1306687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[7].IsHard = FALSE;
1307687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[7].Notify = TRUE;
1308687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
1309687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[8].Error = EFI_ICMP_ERROR;
1310687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[8].IsHard = FALSE;
1311687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[8].Notify = FALSE;
1312687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
1313687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[9].Error = EFI_ICMP_ERROR;
1314687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[9].IsHard = FALSE;
1315687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff  IcmpErrMap[9].Notify = TRUE;
1316cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1317cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ASSERT ((IcmpError >= ICMP_ERR_UNREACH_NET) && (IcmpError <= ICMP_ERR_PARAMPROB));
1318cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1319cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IsHard != NULL) {
1320cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    *IsHard = IcmpErrMap[IcmpError].IsHard;
1321cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1322cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1323cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (Notify != NULL) {
1324cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    *Notify = IcmpErrMap[IcmpError].Notify;
1325cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1326cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1327cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return IcmpErrMap[IcmpError].Error;
1328cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1329cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1330