DxeIpIoLib.c revision 752ef5d80c099b1d33bf25f62f36289dac47d83c
1cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/** @file
26aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IpIo Library.
3cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
46aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywuCopyright (c) 2005 - 2007, Intel Corporation.<BR>
5cbf316f20726bb31b7c37424601643790dbd02d9vanjeffAll rights reserved. This program and the accompanying materials
6cbf316f20726bb31b7c37424601643790dbd02d9vanjeffare licensed and made available under the terms and conditions of the BSD License
7cbf316f20726bb31b7c37424601643790dbd02d9vanjeffwhich accompanies this distribution.  The full text of the license may be found at
8cbf316f20726bb31b7c37424601643790dbd02d9vanjeffhttp://opensource.org/licenses/bsd-license.php
9cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
10cbf316f20726bb31b7c37424601643790dbd02d9vanjeffTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11cbf316f20726bb31b7c37424601643790dbd02d9vanjeffWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
13cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
146aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu#include <Uefi.h>
15cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
16cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Protocol/Udp4.h>
17cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
18cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/IpIoLib.h>
19cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/BaseLib.h>
20cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/DebugLib.h>
21752ef5d80c099b1d33bf25f62f36289dac47d83cmdkinney#include <Library/BaseMemoryLib.h>
22cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/UefiBootServicesTableLib.h>
23752ef5d80c099b1d33bf25f62f36289dac47d83cmdkinney#include <Library/MemoryAllocationLib.h>
24cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
25cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
26e48e37fce2611df7a52aff271835ff72ee396d9bvanjeffLIST_ENTRY  mActiveIpIoList = {
27cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  &mActiveIpIoList,
28cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  &mActiveIpIoList
29cbf316f20726bb31b7c37424601643790dbd02d9vanjeff};
30cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
31cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_IP4_CONFIG_DATA  mIpIoDefaultIpConfigData = {
32cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP_PROTO_UDP,
33cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
34cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TRUE,
35cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
36cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
37cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
3884b5c78e89686879f799a4cd095eeef83ff7cf34qwang  {{0, 0, 0, 0}},
3984b5c78e89686879f799a4cd095eeef83ff7cf34qwang  {{0, 0, 0, 0}},
40cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0,
41cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  255,
42cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
43cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
44cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0,
45cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0
46cbf316f20726bb31b7c37424601643790dbd02d9vanjeff};
47cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
48fe1e36e550c6ffcd2561903d434683d3939e1942jjiICMP_ERROR_INFO  mIcmpErrMap[10] = {
4901750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, TRUE},
5001750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, TRUE},
5101750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {TRUE, TRUE},
5201750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {TRUE, TRUE},
5301750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {TRUE, TRUE},
5401750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, TRUE},
5501750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, TRUE},
5601750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, TRUE},
5701750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, FALSE},
5801750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, TRUE}
5901750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff};
6001750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff
616aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
626aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu/**
636aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  Notify function for IP transmit token.
646aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
656aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
666aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
676aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu**/
68cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
69cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
7036ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoTransmitHandlerDpc (
7136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
7236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  );
7336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
746aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
756aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu/**
766aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  Notify function for IP transmit token.
776aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
786aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event signaled.
796aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
806aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
816aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu**/
8236ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
8336ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
84cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoTransmitHandler (
85cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_EVENT Event,
86cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
87cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  );
88cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
89cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
90cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
916aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  This function create an IP child ,open the IP protocol, and return the opened
92e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IP protocol as Interface.
93cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
946aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]    ControllerHandle   The controller handle.
956aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]    ImageHandle        The image handle.
966aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]    ChildHandle        Pointer to the buffer to save the IP child handle.
976aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[out]   Interface          Pointer used to get the IP protocol interface.
98cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
996aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval       EFI_SUCCESS        The IP child is created and the IP protocol
1006aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   interface is retrieved.
1016aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval       Others             The required operation failed.
102cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
103cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
104cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
105cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreateIpChildOpenProtocol (
106cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  ControllerHandle,
107cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  ImageHandle,
108cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  *ChildHandle,
109cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  OUT VOID        **Interface
110cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
111cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
112cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
113cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
114cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1156aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Create an IP child.
116cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
117cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = NetLibCreateServiceChild (
118cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ControllerHandle,
119cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ImageHandle,
120cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &gEfiIp4ServiceBindingProtocolGuid,
121cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ChildHandle
122cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
123cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
124cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
125cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
126cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
127cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1286aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Open the IP protocol installed on the *ChildHandle.
129cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
130cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->OpenProtocol (
131cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  *ChildHandle,
132cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  &gEfiIp4ProtocolGuid,
133cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  Interface,
134cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  ImageHandle,
135cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  ControllerHandle,
136cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EFI_OPEN_PROTOCOL_BY_DRIVER
137cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
138cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
139cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1406aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // On failure, destroy the IP child.
141cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
142cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    NetLibDestroyServiceChild (
143cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      ControllerHandle,
144cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      ImageHandle,
145cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      &gEfiIp4ServiceBindingProtocolGuid,
146cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      *ChildHandle
147cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      );
148cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
149cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
150cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
151cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
152cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
153cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
154cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
155e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function close the previously openned IP protocol and destroy the IP child.
156cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1576aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  ControllerHandle    The controller handle.
1586aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  ImageHandle         The image handle.
1596aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  ChildHandle         The child handle of the IP child.
160cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1616aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval     EFI_SUCCESS         The IP protocol is closed and the relevant IP child
1626aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                  is destroyed.
1636aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval     Others              The required operation failed.
164cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
165cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
166cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
167cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCloseProtocolDestroyIpChild (
168cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ControllerHandle,
169cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ImageHandle,
170cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ChildHandle
171cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
172cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
173cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
174cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
175cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1766aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Close the previously openned IP protocol.
177cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
178cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseProtocol (
179cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ChildHandle,
180cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         &gEfiIp4ProtocolGuid,
181cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ImageHandle,
182cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ControllerHandle
183cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         );
184cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
185cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1866aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Destroy the IP child.
187cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
188cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = NetLibDestroyServiceChild (
189cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ControllerHandle,
190cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ImageHandle,
191cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &gEfiIp4ServiceBindingProtocolGuid,
192cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ChildHandle
193cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
194cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
195cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
196cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
197cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
198cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
199cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
200e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function handles ICMP packets.
201cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2026aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       IpIo          Pointer to the IP_IO instance.
2036aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  Pkt           Pointer to the ICMP packet.
2046aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Session       Pointer to the net session of this ICMP packet.
205cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS   The ICMP packet is handled successfully.
2076aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_ABORTED   This type of ICMP packet is not supported.
208cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
209cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
210cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
211cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoIcmpHandler (
2126aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO                *IpIo,
2136aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT NET_BUF              *Pkt,
2146aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     EFI_NET_SESSION_DATA *Session
215cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
216cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
217cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP4_ICMP_ERROR_HEAD  *IcmpHdr;
218cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_HEADER       *IpHdr;
219cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ICMP_ERROR           IcmpErr;
220cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                *PayLoadHdr;
221cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                Type;
222cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                Code;
223cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT32               TrimBytes;
224cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
225cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IcmpHdr = NET_PROTO_HDR (Pkt, IP4_ICMP_ERROR_HEAD);
226cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpHdr   = (EFI_IP4_HEADER *) (&IcmpHdr->IpHead);
227cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
228cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
229cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Check the ICMP packet length.
230cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
231cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (Pkt->TotalSize < ICMP_ERRLEN (IpHdr)) {
232cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
233cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ABORTED;
234cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
235cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
236cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Type = IcmpHdr->Head.Type;
237cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Code = IcmpHdr->Head.Code;
238cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
239cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
240cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Analyze the ICMP Error in this ICMP pkt
241cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
242cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  switch (Type) {
243cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_UNREACH:
244cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    switch (Code) {
245cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET:
246cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST:
247cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_PROTOCOL:
248cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_PORT:
249cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_SRCFAIL:
2504eb65aff715faafd9040c6fc85a5d59e22343978vanjeff      IcmpErr = (ICMP_ERROR) (ICMP_ERR_UNREACH_NET + Code);
251cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
252cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
253cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
254cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NEEDFRAG:
255cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_MSGSIZE;
256cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
257cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
258cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
259cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET_UNKNOWN:
260cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET_PROHIB:
261cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_TOSNET:
262cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_UNREACH_NET;
263cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
264cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
265cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
266cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST_UNKNOWN:
267cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_ISOLATED:
268cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST_PROHIB:
269cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_TOSHOST:
270cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_UNREACH_HOST;
271cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
272cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
273cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
274cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    default:
275cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
276cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
277cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
278cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
279cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
280cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_TIMXCEED:
281cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code > 1) {
282cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
283cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
284cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2854eb65aff715faafd9040c6fc85a5d59e22343978vanjeff    IcmpErr = (ICMP_ERROR) (Code + ICMP_ERR_TIMXCEED_INTRANS);
286cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
287cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
288cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
289cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_PARAMPROB:
290cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code > 1) {
291cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
292cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
293cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
294cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IcmpErr = ICMP_ERR_PARAMPROB;
295cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
296cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
297cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
298cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_SOURCEQUENCH:
299cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code != 0) {
300cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
301cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
302cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
303cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IcmpErr = ICMP_ERR_QUENCH;
304cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
305cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
306cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
307cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  default:
308cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ABORTED;
309cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
310cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
311cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
312cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Notify user the ICMP pkt only containing payload except
313cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // IP and ICMP header
314cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
315cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  PayLoadHdr = (UINT8 *) ((UINT8 *) IpHdr + EFI_IP4_HEADER_LEN (IpHdr));
316cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TrimBytes  = (UINT32) (PayLoadHdr - (UINT8 *) IcmpHdr);
317cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
318cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetbufTrim (Pkt, TrimBytes, TRUE);
319cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
320cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);
321cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
322cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
323cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
324cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
325cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
326cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
327e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  Free function for receive token of IP_IO. It is used to
328cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  signal the recycle event to notify IP to recycle the
329cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  data buffer.
330cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
3316aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event to be signaled.
332cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
333cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
334cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
335cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoExtFree (
336cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID  *Event
337cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
338cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
339cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->SignalEvent ((EFI_EVENT) Event);
340cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
341cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
342cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
343cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
344cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Create a send entry to wrap a packet before sending
345cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  out it through IP.
346cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
3476aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo                 Pointer to the IP_IO instance.
3486aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  Pkt                  Pointer to the packet.
3496aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Sender               Pointer to the IP sender.
3506aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Context              Pointer to the context.
3516aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       NotifyData           Pointer to the notify data.
3526aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Dest                 Pointer to the destination IP address.
3536aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Override             Pointer to the overriden IP_IO data.
354cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
355cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return Pointer to the data structure created to wrap the packet. If NULL,
3566aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @return resource limit occurred.
357cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
358cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
359cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_SEND_ENTRY *
360cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreateSndEntry (
3616aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO             *IpIo,
3626aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT NET_BUF           *Pkt,
3636aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     EFI_IP4_PROTOCOL  *Sender,
3646aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID              *Context    OPTIONAL,
3656aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID              *NotifyData OPTIONAL,
3666aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP4_ADDR          Dest,
3676aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_OVERRIDE    *Override
368cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
369cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
370cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY          *SndEntry;
371cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_COMPLETION_TOKEN  *SndToken;
372cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_TRANSMIT_DATA     *TxData;
373cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS                Status;
374cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_OVERRIDE_DATA     *OverrideData;
37534edf2ae729941a6203e4e7f614db32204a9c47dvanjeff  volatile UINT32           Index;
376cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
377cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
378cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for SndEntry
379cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
380e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  SndEntry = AllocatePool (sizeof (IP_IO_SEND_ENTRY));
381cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndEntry) {
382cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return NULL;
383cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
384cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
385cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
386cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for SndToken
387cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
388e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  SndToken = AllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN));
389cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndToken) {
390cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseSndEntry;
391cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
392cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
393cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
394cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
395e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
396cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoTransmitHandler,
397cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  SndEntry,
398cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  &(SndToken->Event)
399cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
400cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
401cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseSndToken;
402cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
403cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
404cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
405cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for TxData
406cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
407e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  TxData = AllocatePool (
408cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    sizeof (EFI_IP4_TRANSMIT_DATA) +
409cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    sizeof (EFI_IP4_FRAGMENT_DATA) * (Pkt->BlockOpNum - 1)
410cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    );
411cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
412cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == TxData) {
413cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseEvent;
414cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
415cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
416cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
417cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for OverrideData if needed
418cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
419cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  OverrideData = NULL;
420cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL != Override) {
421cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
422e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    OverrideData = AllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA));
423cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (NULL == OverrideData) {
424cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      goto ReleaseResource;
425cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
426cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
427cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // Set the fields of OverrideData
428cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
42936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    CopyMem (OverrideData, Override, sizeof (*OverrideData));
430cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
431cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
432cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
433cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Set the fields of TxData
434cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
435e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  CopyMem (&TxData->DestinationAddress, &Dest, sizeof (EFI_IPv4_ADDRESS));
436cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->OverrideData                  = OverrideData;
437cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->OptionsLength                 = 0;
438cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->OptionsBuffer                 = NULL;
439cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->TotalDataLength               = Pkt->TotalSize;
440cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->FragmentCount                 = Pkt->BlockOpNum;
441cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
442cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
44334edf2ae729941a6203e4e7f614db32204a9c47dvanjeff  for (Index = 0; Index < Pkt->BlockOpNum; Index++) {
444cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    TxData->FragmentTable[Index].FragmentBuffer = Pkt->BlockOp[Index].Head;
445cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    TxData->FragmentTable[Index].FragmentLength = Pkt->BlockOp[Index].Size;
446cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
447cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
448cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
449cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Set the fields of SndToken
450cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
451cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndToken->Packet.TxData = TxData;
452cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
453cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
454cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Set the fields of SndEntry
455cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
456cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->IpIo        = IpIo;
4576aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  SndEntry->Ip          = Sender;
458cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->Context     = Context;
459cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->NotifyData  = NotifyData;
460cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
461cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->Pkt         = Pkt;
462cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_GET_REF (Pkt);
463cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
464cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->SndToken = SndToken;
465cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
466e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertTailList (&IpIo->PendingSndList, &SndEntry->Entry);
467cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
468cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return SndEntry;
469cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
470cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseResource:
471e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (TxData);
472cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
473cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseEvent:
474cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseEvent (SndToken->Event);
475cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
476cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseSndToken:
477e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (SndToken);
478cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
479cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseSndEntry:
480e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (SndEntry);
481cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
482cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
483cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
484cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
485cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
486cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
487cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy the SndEntry.
488e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
489e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function pairs with IpIoCreateSndEntry().
490cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
4916aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  SndEntry              Pointer to the send entry to be destroyed.
492cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
493cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
494cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
495cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoDestroySndEntry (
496cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO_SEND_ENTRY  *SndEntry
497cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
498cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
499cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_TRANSMIT_DATA  *TxData;
500cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
501cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData = SndEntry->SndToken->Packet.TxData;
502cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
503cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL != TxData->OverrideData) {
504e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    gBS->FreePool (TxData->OverrideData);
505cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
506cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
507e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (TxData);
508cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetbufFree (SndEntry->Pkt);
509cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseEvent (SndEntry->SndToken->Event);
510cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
511e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (SndEntry->SndToken);
512e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RemoveEntryList (&SndEntry->Entry);
513cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
514e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (SndEntry);
515cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
516cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
517cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
518cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
519cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Notify function for IP transmit token.
520cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
5216aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
522cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
523cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
524cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
525cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
52636ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoTransmitHandlerDpc (
527cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
528cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
529cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
530cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO             *IpIo;
531cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
532cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
533cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry  = (IP_IO_SEND_ENTRY *) Context;
534cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
535cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo      = SndEntry->IpIo;
536cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
5378de75da28bbd9a4d3c54fba99d943f9019b52193niry  if ((IpIo->PktSentNotify != NULL) && (SndEntry->NotifyData != NULL)) {
538cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->PktSentNotify (
539cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->SndToken->Status,
540cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->Context,
541cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->Ip,
542cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->NotifyData
543cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            );
544cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
545cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
546cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoDestroySndEntry (SndEntry);
547cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
548cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
5496aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
55036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff/**
55136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  Notify function for IP transmit token.
55236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
5536aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event signaled.
5546aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
55536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
55636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff**/
55736ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
55836ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
55936ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoTransmitHandler (
56036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN EFI_EVENT Event,
56136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
56236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  )
56336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff{
56436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
56536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK
56636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
56736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  NetLibQueueDpc (TPL_CALLBACK, IpIoTransmitHandlerDpc, Context);
56836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff}
56936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
570cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
571cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
572cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  The dummy handler for the dummy IP receive token.
573cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
5746aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
575cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
576cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
577cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
578cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
57936ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoDummyHandlerDpc (
580cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
581cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
582cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
583cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO             *IpInfo;
584cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_COMPLETION_TOKEN  *DummyToken;
585cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
586cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo      = (IP_IO_IP_INFO *) Context;
587cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  DummyToken  = &(IpInfo->DummyRcvToken);
588cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
58936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  if (EFI_ABORTED == DummyToken->Status) {
59036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
59136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    // The reception is actively aborted by the consumer, directly return.
59236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
59336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    return;
59436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  } else if (EFI_SUCCESS == DummyToken->Status) {
5956aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    ASSERT ((DummyToken->Packet.RxData)!= NULL);
596cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
597cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    gBS->SignalEvent (DummyToken->Packet.RxData->RecycleSignal);
598cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
599cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
600cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->Ip->Receive (IpInfo->Ip, DummyToken);
601cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
602cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
603cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
604cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
6056aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  This function add IpIoDummyHandlerDpc to the end of the DPC queue.
606cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
6076aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event signaled.
6086aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
609cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
610cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
611cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
612cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
61336ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoDummyHandler (
614cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_EVENT Event,
615cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
616cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
617cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
61836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
61936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK
62036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
62136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  NetLibQueueDpc (TPL_CALLBACK, IpIoDummyHandlerDpc, Context);
62236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff}
62336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
62436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
62536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff/**
62636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  Notify function for the IP receive token, used to process
62736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  the received IP packets.
62836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
6296aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
63036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
63136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff**/
63236ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
63336ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
63436ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoListenHandlerDpc (
63536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
63636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  )
63736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff{
638cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO                 *IpIo;
639cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS            Status;
640cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_RECEIVE_DATA  *RxData;
641cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL      *Ip;
642cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_NET_SESSION_DATA  Session;
643cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_BUF               *Pkt;
644cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
645cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo    = (IP_IO *) Context;
646cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
647cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip      = IpIo->Ip;
648cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status  = IpIo->RcvToken.Status;
649cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  RxData  = IpIo->RcvToken.Packet.RxData;
650cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
65136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  if (EFI_ABORTED == Status) {
65236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
65336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    // The reception is actively aborted by the consumer, directly return.
65436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
65536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    return;
65636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  }
65736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
658cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (((EFI_SUCCESS != Status) && (EFI_ICMP_ERROR != Status)) || (NULL == RxData)) {
659cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
6606aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // @bug Only process the normal packets and the icmp error packets, if RxData is NULL
6616aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // @bug with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
6626aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // @bug this should be a bug of the low layer (IP).
663cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
664cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto Resume;
665cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
666cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
667cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == IpIo->PktRcvdNotify) {
668cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
669cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
670cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
671cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if ((EFI_IP4 (RxData->Header->SourceAddress) != 0) &&
672cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    !Ip4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), 0)) {
673cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
674cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // The source address is not zero and it's not a unicast IP address, discard it.
675cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
676cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
677cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
678cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
679cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
680cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create a netbuffer representing packet
681cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
682cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Pkt = NetbufFromExt (
683cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          (NET_FRAGMENT *) RxData->FragmentTable,
684cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          RxData->FragmentCount,
685cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          0,
686cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          0,
687cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          IpIoExtFree,
688cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          RxData->RecycleSignal
689cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          );
690cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == Pkt) {
691cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
692cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
693cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
694cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
695cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create a net session
696cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
697cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Session.Source = EFI_IP4 (RxData->Header->SourceAddress);
698cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Session.Dest   = EFI_IP4 (RxData->Header->DestinationAddress);
699cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Session.IpHdr  = RxData->Header;
700cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
701cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_SUCCESS == Status) {
702cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
7034eb65aff715faafd9040c6fc85a5d59e22343978vanjeff    IpIo->PktRcvdNotify (EFI_SUCCESS, (ICMP_ERROR) 0, &Session, Pkt, IpIo->RcvdContext);
704cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  } else {
705cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
706cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // Status is EFI_ICMP_ERROR
707cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
708cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    Status = IpIoIcmpHandler (IpIo, Pkt, &Session);
709cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (EFI_ERROR (Status)) {
710cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      NetbufFree (Pkt);
711cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
712cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
713cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
714cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  goto Resume;
715cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
716cbf316f20726bb31b7c37424601643790dbd02d9vanjeffCleanUp:
717cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->SignalEvent (RxData->RecycleSignal);
718cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
719cbf316f20726bb31b7c37424601643790dbd02d9vanjeffResume:
720cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip->Receive (Ip, &(IpIo->RcvToken));
721cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
722cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
723cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
724cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
7256aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  This function add IpIoListenHandlerDpc to the end of the DPC queue.
72636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
7276aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                The event signaled.
7286aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context              The context passed in by the event notifier.
72936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
73036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff**/
73136ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
73236ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
73336ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoListenHandler (
73436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN EFI_EVENT Event,
73536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
73636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  )
73736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff{
73836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
73936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
74036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
74136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  NetLibQueueDpc (TPL_CALLBACK, IpIoListenHandlerDpc, Context);
74236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff}
74336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
74436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
74536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff/**
746cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Create a new IP_IO instance.
747e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
748e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function uses IP4 service binding protocol in Controller to create an IP4
749e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  child (aka IP4 instance).
750cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
7516aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Image             The image handle of the driver or application that
752e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong                                consumes IP_IO.
7536aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Controller        The controller handle that has IP4 service binding
754e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong                                protocol installed.
755cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
756e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  @return Pointer to a newly created IP_IO instance, or NULL if failed.
757cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
758cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
759cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO *
7607b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
761cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreate (
762cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE Image,
763cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE Controller
764cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
765cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
766cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
767cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO       *IpIo;
768cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
769e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  IpIo = AllocateZeroPool (sizeof (IP_IO));
770cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == IpIo) {
771cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return NULL;
772cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
773cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
774e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&(IpIo->PendingSndList));
775e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&(IpIo->IpList));
776cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Controller  = Controller;
777cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Image       = Image;
778cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
779cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
780cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
781e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
782cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoListenHandler,
783cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIo,
784cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  &(IpIo->RcvToken.Event)
785cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
786cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
787cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpIo;
788cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
789cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
790cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
791cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create an IP child and open IP protocol
792cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
793cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = IpIoCreateIpChildOpenProtocol (
794cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             Controller,
795cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             Image,
796cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &IpIo->ChildHandle,
797cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             (VOID **)&(IpIo->Ip)
798cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
799cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
800cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpIo;
801cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
802cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
803cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return IpIo;
804cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
805cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpIo:
806cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
807cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL != IpIo->RcvToken.Event) {
808cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    gBS->CloseEvent (IpIo->RcvToken.Event);
809cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
810cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
811e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpIo);
812cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
813cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
814cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
815cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
816cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
817cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
818cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Open an IP_IO instance for use.
819e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
820e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is called after IpIoCreate(). It is used for configuring the IP
821e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  instance and register the callbacks and their context data for sending and
822e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  receiving IP packets.
823cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
8246aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo               Pointer to an IP_IO instance that needs
8256aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      to open.
8266aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       OpenData           The configuration data and callbacks for
8276aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      the IP_IO instance.
828cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
8296aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS        The IP_IO instance opened with OpenData
8306aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      successfully.
8316aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_ACCESS_DENIED  The IP_IO instance is configured, avoid to
8326aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      reopen it.
8336aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others             Error condition occurred.
834cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
835cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
836cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
8377b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
838cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoOpen (
8396aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO           *IpIo,
8406aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_OPEN_DATA *OpenData
841cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
842cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
843cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
844cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL  *Ip;
845cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
846cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpIo->IsConfigured) {
847cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ACCESS_DENIED;
848cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
849cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
850cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpIo->Ip;
851cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
852cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
853cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // configure ip
854cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
855cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Configure (Ip, &OpenData->IpConfigData);
856cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
857cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
858cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
859cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
860cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
8616aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // @bug To delete the default route entry in this Ip, if it is:
8626aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // @bug (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified
8636aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // @bug its code
864cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
865b61439a709bb961f2f9dff1d1a4112e30a063f51vanjeff  Status = Ip->Routes (Ip, TRUE, &mZeroIp4Addr, &mZeroIp4Addr, &mZeroIp4Addr);
866cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
867cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status) && (EFI_NOT_FOUND != Status)) {
868cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
869cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
870cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
871cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktRcvdNotify = OpenData->PktRcvdNotify;
872cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktSentNotify = OpenData->PktSentNotify;
873cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
874cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->RcvdContext   = OpenData->RcvdContext;
875cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->SndContext    = OpenData->SndContext;
876cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
877cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Protocol      = OpenData->IpConfigData.DefaultProtocol;
878cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
879cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
880cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // start to listen incoming packet
881cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
882cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Receive (Ip, &(IpIo->RcvToken));
883cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
884cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    Ip->Configure (Ip, NULL);
885cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ErrorExit;
886cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
887cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
888cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->IsConfigured = TRUE;
889e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertTailList (&mActiveIpIoList, &IpIo->Entry);
890cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
891cbf316f20726bb31b7c37424601643790dbd02d9vanjeffErrorExit:
892cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
893cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
894cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
895cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
896cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
897cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
898cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Stop an IP_IO instance.
899e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
900e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is paired with IpIoOpen(). The IP_IO will be unconfigured and all
901e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  the pending send/receive tokens will be canceled.
902cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
9036aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo            Pointer to the IP_IO instance that needs to stop.
904cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
9056aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS     The IP_IO instance stopped successfully.
9066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others          Error condition occurred.
907cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
908cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
909cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
910e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgongEFIAPI
911cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoStop (
9126aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO *IpIo
913cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
914cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
915cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
916cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL  *Ip;
917cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO     *IpInfo;
918cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
919cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (!IpIo->IsConfigured) {
920cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_SUCCESS;
921cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
922cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
923cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
924cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Remove the IpIo from the active IpIo list.
925cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
926e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RemoveEntryList (&IpIo->Entry);
927cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
928cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpIo->Ip;
929cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
930cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
931cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Configure NULL Ip
932cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
933cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Configure (Ip, NULL);
934cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
935cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
936cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
937cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
938cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->IsConfigured = FALSE;
939cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
940cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
941cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Detroy the Ip List used by IpIo
942cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
94334edf2ae729941a6203e4e7f614db32204a9c47dvanjeff
944e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  while (!IsListEmpty (&(IpIo->IpList))) {
945cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo = NET_LIST_HEAD (&(IpIo->IpList), IP_IO_IP_INFO, Entry);
946cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
947cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoRemoveIp (IpIo, IpInfo);
948cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
949cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
950cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
9516aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // All pending send tokens should be flushed by reseting the IP instances.
952cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
953e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  ASSERT (IsListEmpty (&IpIo->PendingSndList));
954cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
955cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
956cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Close the receive event.
957cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
958cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseEvent (IpIo->RcvToken.Event);
959cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
960cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
961cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
962cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
963cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
964cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
965cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy an IP_IO instance.
966e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
967e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is paired with IpIoCreate(). The IP_IO will be closed first.
9688f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  Resource will be freed afterwards. See IpIoCloseProtocolDestroyIpChild().
969cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
9706aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo         Pointer to the IP_IO instance that needs to be
971e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong                                destroyed.
972cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
9736aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS  The IP_IO instance destroyed successfully.
9746aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others       Error condition occurred.
975cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
976cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
977cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
9787b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
979cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoDestroy (
9806aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO *IpIo
981cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
982cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
983cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
984cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Stop the IpIo.
985cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
986cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoStop (IpIo);
987cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
988cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
989cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Close the IP protocol and destroy the child.
990cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
991cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpIo->ChildHandle);
992cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
993e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpIo);
994cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
995cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
996cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
997cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
998cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
999cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1000cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Send out an IP packet.
1001e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1002e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is called after IpIoOpen(). The data to be sent are wrapped in
1003e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  Pkt. The IP instance wrapped in IpIo is used for sending by default but can be
1004e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  overriden by Sender. Other sending configs, like source address and gateway
1005e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  address etc., are specified in OverrideData.
1006cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
10076aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo                  Pointer to an IP_IO instance used for sending IP
10086aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                         packet.
10096aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  Pkt                   Pointer to the IP packet to be sent.
10106aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Sender                The IP protocol instance used for sending.
10118f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[in]       Context               Optional context data.
10128f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[in]       NotifyData            Optional notify data.
10136aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Dest                  The destination IP address to send this packet to.
10146aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       OverrideData          The data to override some configuration of the IP
10156aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                         instance used for sending.
1016cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
10176aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS           The operation is completed successfully.
10186aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_NOT_STARTED       The IpIo is not configured.
10196aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_OUT_OF_RESOURCES  Failed due to resource limit.
1020cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1021cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1022cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
10237b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1024cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoSend (
10256aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO          *IpIo,
10266aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT NET_BUF        *Pkt,
10276aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_IP_INFO  *Sender        OPTIONAL,
10286aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID           *Context       OPTIONAL,
10296aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID           *NotifyData    OPTIONAL,
10306aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP4_ADDR       Dest,
10316aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_OVERRIDE *OverrideData  OPTIONAL
1032cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1033cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1034cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
1035cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL  *Ip;
1036cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
1037cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1038cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (!IpIo->IsConfigured) {
1039cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_NOT_STARTED;
1040cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1041cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1042cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = (NULL == Sender) ? IpIo->Ip : Sender->Ip;
1043cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1044cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1045cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // create a new SndEntry
1046cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1047cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry = IpIoCreateSndEntry (IpIo, Pkt, Ip, Context, NotifyData, Dest, OverrideData);
1048cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndEntry) {
1049cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_OUT_OF_RESOURCES;
1050cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1051cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1052cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1053cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Send this Packet
1054cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1055cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Transmit (Ip, SndEntry->SndToken);
1056cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1057cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoDestroySndEntry (SndEntry);
1058cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1059cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1060cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
1061cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1062cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1063cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1064cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1065cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Cancel the IP transmit token which wraps this Packet.
1066cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
10676aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  IpIo                  Pointer to the IP_IO instance.
10686aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Packet                Pointer to the packet of NET_BUF to cancel.
1069cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1070cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1071cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
10727b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1073cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCancelTxToken (
1074cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO  *IpIo,
1075cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID   *Packet
1076cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1077cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1078e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  LIST_ENTRY        *Node;
1079cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
1080cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL  *Ip;
1081cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
10826aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  ASSERT ((IpIo)!= NULL && (Packet)!= NULL);
1083cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1084cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_FOR_EACH (Node, &IpIo->PendingSndList) {
1085cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1086cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    SndEntry = NET_LIST_USER_STRUCT (Node, IP_IO_SEND_ENTRY, Entry);
1087cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1088cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (SndEntry->Pkt == Packet) {
1089cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1090cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip = SndEntry->Ip;
1091cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip->Cancel (Ip, SndEntry->SndToken);
1092cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1093cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
1094cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1095cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1096cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1097cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1098cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1099cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1100cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1101cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Add a new IP instance for sending data.
1102e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1103e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  The function is used to add the IP_IO to the IP_IO sending list. The caller
1104e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send
1105e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  data.
1106cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
11076aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo               Pointer to a IP_IO instance to add a new IP
11086aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      instance for sending purpose.
1109cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1110e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  @return Pointer to the created IP_IO_IP_INFO structure, NULL if failed.
1111cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1112cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1113cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_IP_INFO *
11147b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1115cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoAddIp (
11166aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO  *IpIo
1117cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1118cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1119cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS     Status;
1120cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO  *IpInfo;
1121cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
11226aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  ASSERT (IpIo != NULL);
1123cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1124e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  IpInfo = AllocatePool (sizeof (IP_IO_IP_INFO));
1125cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo == NULL) {
1126cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return IpInfo;
1127cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1128cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1129cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1130cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP
1131cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // instance.
1132cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1133e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&IpInfo->Entry);
1134cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->ChildHandle = NULL;
1135cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->Addr        = 0;
1136cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->SubnetMask  = 0;
1137cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->RefCnt      = 1;
1138cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1139cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1140cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create the IP instance and open the Ip4 protocol.
1141cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1142cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = IpIoCreateIpChildOpenProtocol (
1143cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             IpIo->Controller,
1144cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             IpIo->Image,
1145cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &IpInfo->ChildHandle,
11464eb65aff715faafd9040c6fc85a5d59e22343978vanjeff             (VOID **) &IpInfo->Ip
1147cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
1148cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1149cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpInfo;
1150cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1151cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1152cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1153cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create the event for the DummyRcvToken.
1154cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1155cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
1156cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
1157e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
1158cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoDummyHandler,
1159cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpInfo,
1160cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  &IpInfo->DummyRcvToken.Event
1161cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
1162cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1163cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpChild;
1164cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1165cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1166cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1167cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Link this IpInfo into the IpIo.
1168cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1169e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertTailList (&IpIo->IpList, &IpInfo->Entry);
1170cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1171cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return IpInfo;
1172cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1173cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpChild:
1174cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1175cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoCloseProtocolDestroyIpChild (
1176cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->Controller,
1177cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->Image,
1178cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo->ChildHandle
1179cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    );
1180cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1181cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpInfo:
1182cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1183e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpInfo);
1184cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1185cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
1186cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1187cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1188cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1189cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1190cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Configure the IP instance of this IpInfo and start the receiving if Ip4ConfigData
1191cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  is not NULL.
1192cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
11936aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpInfo          Pointer to the IP_IO_IP_INFO instance.
11946aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  Ip4ConfigData   The IP4 configure data used to configure the IP
11956aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   instance, if NULL the IP instance is reset. If
11966aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   UseDefaultAddress is set to TRUE, and the configure
11976aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   operation succeeds, the default address information
11986aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   is written back in this Ip4ConfigData.
1199cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
12006aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS     The IP instance of this IpInfo is configured successfully
12016aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   or no need to reconfigure it.
12026aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others          Configuration fails.
1203cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1204cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1205cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
12067b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1207cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoConfigIp (
12086aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO_IP_INFO        *IpInfo,
1209cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN OUT EFI_IP4_CONFIG_DATA  *Ip4ConfigData OPTIONAL
1210cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1211cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1212cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS         Status;
1213cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL   *Ip;
1214cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_MODE_DATA  Ip4ModeData;
1215cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
12166aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  ASSERT (IpInfo != NULL);
1217cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1218cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo->RefCnt > 1) {
1219cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1220cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // This IP instance is shared, don't reconfigure it until it has only one
1221cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // consumer. Currently, only the tcp children cloned from their passive parent
1222cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,
1223cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // let the last consumer clean the IP instance.
1224cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1225cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_SUCCESS;
1226cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1227cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1228cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpInfo->Ip;
1229cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1230cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Configure (Ip, Ip4ConfigData);
1231cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1232cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto OnExit;
1233cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1234cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1235cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (Ip4ConfigData != NULL) {
1236cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1237cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Ip4ConfigData->UseDefaultAddress) {
1238cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip->GetModeData (Ip, &Ip4ModeData, NULL, NULL);
1239cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1240cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip4ConfigData->StationAddress = Ip4ModeData.ConfigData.StationAddress;
1241cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip4ConfigData->SubnetMask     = Ip4ModeData.ConfigData.SubnetMask;
1242cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1243cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1244e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (&IpInfo->Addr, &Ip4ConfigData->StationAddress, sizeof (IP4_ADDR));
1245e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (&IpInfo->SubnetMask, &Ip4ConfigData->SubnetMask, sizeof (IP4_ADDR));
1246cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1247cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    Status = Ip->Receive (Ip, &IpInfo->DummyRcvToken);
1248cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (EFI_ERROR (Status)) {
1249cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip->Configure (Ip, NULL);
1250cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1251cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  } else {
1252cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1253cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1254cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // The IP instance is reseted, set the stored Addr and SubnetMask to zero.
1255cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1256cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo->Addr       = 0;
1257cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo->SubnetMask =0;
1258cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1259cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1260cbf316f20726bb31b7c37424601643790dbd02d9vanjeffOnExit:
1261cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1262cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
1263cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1264cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1265cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1266cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1267cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy an IP instance maintained in IpIo->IpList for
1268cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  sending purpose.
1269e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1270e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function pairs with IpIoAddIp(). The IpInfo is previously created by
1271e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance
1272e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  will be dstroyed if the RefCnt is zero.
1273cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
12746aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  IpIo                  Pointer to the IP_IO instance.
12756aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  IpInfo                Pointer to the IpInfo to be removed.
1276cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1277cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1278cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
12797b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1280cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoRemoveIp (
1281e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IN IP_IO            *IpIo,
1282e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IN IP_IO_IP_INFO    *IpInfo
1283cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1284cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1285cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ASSERT (IpInfo->RefCnt > 0);
1286cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1287cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_PUT_REF (IpInfo);
1288cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1289cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo->RefCnt > 0) {
1290cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1291cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return;
1292cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1293cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1294e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RemoveEntryList (&IpInfo->Entry);
1295cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1296cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->Ip->Configure (IpInfo->Ip, NULL);
1297cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1298cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpInfo->ChildHandle);
1299cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1300cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseEvent (IpInfo->DummyRcvToken.Event);
1301cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1302e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpInfo);
1303cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1304cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1305cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1306cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1307cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Find the first IP protocol maintained in IpIo whose local
1308cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  address is the same with Src.
1309e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1310e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is called when the caller needs the IpIo to send data to the
1311e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  specified Src. The IpIo was added previously by IpIoAddIp().
1312cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
13136aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo              Pointer to the pointer of the IP_IO instance.
13146aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Src               The local IP address.
1315cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1316cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return Pointer to the IP protocol can be used for sending purpose and its local
13176aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @return address is the same with Src.
1318cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1319cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1320cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_IP_INFO *
13217b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1322cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoFindSender (
1323cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN OUT IP_IO     **IpIo,
1324cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN     IP4_ADDR  Src
1325cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1326cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1327e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  LIST_ENTRY      *IpIoEntry;
1328cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO           *IpIoPtr;
1329e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  LIST_ENTRY      *IpInfoEntry;
1330cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO   *IpInfo;
1331cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1332cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_FOR_EACH (IpIoEntry, &mActiveIpIoList) {
1333cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoPtr = NET_LIST_USER_STRUCT (IpIoEntry, IP_IO, Entry);
1334cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1335cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if ((*IpIo != NULL) && (*IpIo != IpIoPtr)) {
1336cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      continue;
1337cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1338cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1339cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    NET_LIST_FOR_EACH (IpInfoEntry, &IpIoPtr->IpList) {
1340cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IpInfo = NET_LIST_USER_STRUCT (IpInfoEntry, IP_IO_IP_INFO, Entry);
1341cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1342cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      if (IpInfo->Addr == Src) {
1343cbf316f20726bb31b7c37424601643790dbd02d9vanjeff        *IpIo = IpIoPtr;
1344cbf316f20726bb31b7c37424601643790dbd02d9vanjeff        return IpInfo;
1345cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      }
1346cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1347cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1348cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1349cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1350cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // No match.
1351cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1352cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
1353cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1354cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1355cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1356cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1357e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  Get the ICMP error map information.
1358e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1359e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  The ErrorStatus will be returned. The IsHard and Notify are optional. If they
1360e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  are not NULL, this routine will fill them.
1361cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
13628f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[in]   IcmpError             IcmpError Type.
13638f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[out]  IsHard                Whether it is a hard error.
13648f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[out]  Notify                Whether it need to notify SockError.
1365cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
13666aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @return ICMP Error Status, such as EFI_NETWORK_UNREACHABLE.
1367cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1368cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1369cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
13707b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1371cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoGetIcmpErrStatus (
1372cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  ICMP_ERROR  IcmpError,
1373e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  OUT BOOLEAN     *IsHard  OPTIONAL,
1374e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  OUT BOOLEAN     *Notify  OPTIONAL
1375cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1376cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
137701750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  ASSERT ((IcmpError >= ICMP_ERR_UNREACH_NET) && (IcmpError <= ICMP_ERR_PARAMPROB));
1378687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
137901750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  if (IsHard != NULL) {
138001750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    *IsHard = mIcmpErrMap[IcmpError].IsHard;
138101750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  }
1382687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
138301750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  if (Notify != NULL) {
138401750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    *Notify = mIcmpErrMap[IcmpError].Notify;
138501750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  }
1386687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
138701750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  switch (IcmpError) {
138801750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_UNREACH_NET:
138901750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    return  EFI_NETWORK_UNREACHABLE;
1390687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
139101750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_TIMXCEED_INTRANS:
139201750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_TIMXCEED_REASS:
139301750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_UNREACH_HOST:
139401750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    return  EFI_HOST_UNREACHABLE;
1395cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
139601750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_UNREACH_PROTOCOL:
139701750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    return  EFI_PROTOCOL_UNREACHABLE;
1398cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
139901750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_UNREACH_PORT:
140001750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    return  EFI_PORT_UNREACHABLE;
1401cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
140201750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_MSGSIZE:
140301750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_UNREACH_SRCFAIL:
140401750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_QUENCH:
140501750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_PARAMPROB:
140601750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    return  EFI_ICMP_ERROR;
1407cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1408cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
140901750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  //
141001750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  // will never run here!
141101750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  //
141201750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  ASSERT (FALSE);
141301750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  return EFI_UNSUPPORTED;
1414cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1415cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1416