DxeIpIoLib.c revision 8de75da28bbd9a4d3c54fba99d943f9019b52193
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>
21cbf316f20726bb31b7c37424601643790dbd02d9vanjeff#include <Library/UefiBootServicesTableLib.h>
22cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
23cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
24e48e37fce2611df7a52aff271835ff72ee396d9bvanjeffLIST_ENTRY  mActiveIpIoList = {
25cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  &mActiveIpIoList,
26cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  &mActiveIpIoList
27cbf316f20726bb31b7c37424601643790dbd02d9vanjeff};
28cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
29cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_IP4_CONFIG_DATA  mIpIoDefaultIpConfigData = {
30cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP_PROTO_UDP,
31cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
32cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TRUE,
33cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
34cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
35cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
3684b5c78e89686879f799a4cd095eeef83ff7cf34qwang  {{0, 0, 0, 0}},
3784b5c78e89686879f799a4cd095eeef83ff7cf34qwang  {{0, 0, 0, 0}},
38cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0,
39cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  255,
40cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
41cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  FALSE,
42cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0,
43cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  0
44cbf316f20726bb31b7c37424601643790dbd02d9vanjeff};
45cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
46fe1e36e550c6ffcd2561903d434683d3939e1942jjiICMP_ERROR_INFO  mIcmpErrMap[10] = {
4701750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, TRUE},
4801750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, TRUE},
4901750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {TRUE, TRUE},
5001750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {TRUE, TRUE},
5101750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {TRUE, TRUE},
5201750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, TRUE},
5301750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, TRUE},
5401750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, TRUE},
5501750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, FALSE},
5601750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  {FALSE, TRUE}
5701750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff};
5801750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff
596aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
606aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu/**
616aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  Notify function for IP transmit token.
626aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
636aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
646aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
656aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu**/
66cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
67cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
6836ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoTransmitHandlerDpc (
6936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
7036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  );
7136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
726aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
736aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu/**
746aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  Notify function for IP transmit token.
756aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
766aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event signaled.
776aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
786aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
796aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu**/
8036ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
8136ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
82cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoTransmitHandler (
83cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_EVENT Event,
84cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
85cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  );
86cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
87cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
88cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
896aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  This function create an IP child ,open the IP protocol, and return the opened
90e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IP protocol as Interface.
91cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
926aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]    ControllerHandle   The controller handle.
936aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]    ImageHandle        The image handle.
946aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]    ChildHandle        Pointer to the buffer to save the IP child handle.
956aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[out]   Interface          Pointer used to get the IP protocol interface.
96cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
976aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval       EFI_SUCCESS        The IP child is created and the IP protocol
986aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   interface is retrieved.
996aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval       Others             The required operation failed.
100cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
101cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
102cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
103cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreateIpChildOpenProtocol (
104cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  ControllerHandle,
105cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  ImageHandle,
106cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  EFI_HANDLE  *ChildHandle,
107cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  OUT VOID        **Interface
108cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
109cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
110cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
111cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
112cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1136aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Create an IP child.
114cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
115cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = NetLibCreateServiceChild (
116cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ControllerHandle,
117cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ImageHandle,
118cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &gEfiIp4ServiceBindingProtocolGuid,
119cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ChildHandle
120cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
121cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
122cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
123cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
124cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
125cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1266aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Open the IP protocol installed on the *ChildHandle.
127cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
128cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->OpenProtocol (
129cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  *ChildHandle,
130cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  &gEfiIp4ProtocolGuid,
131cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  Interface,
132cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  ImageHandle,
133cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  ControllerHandle,
134cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EFI_OPEN_PROTOCOL_BY_DRIVER
135cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
136cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
137cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1386aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // On failure, destroy the IP child.
139cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
140cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    NetLibDestroyServiceChild (
141cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      ControllerHandle,
142cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      ImageHandle,
143cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      &gEfiIp4ServiceBindingProtocolGuid,
144cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      *ChildHandle
145cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      );
146cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
147cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
148cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
149cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
150cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
151cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
152cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
153e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function close the previously openned IP protocol and destroy the IP child.
154cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1556aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  ControllerHandle    The controller handle.
1566aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  ImageHandle         The image handle.
1576aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  ChildHandle         The child handle of the IP child.
158cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1596aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval     EFI_SUCCESS         The IP protocol is closed and the relevant IP child
1606aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                  is destroyed.
1616aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval     Others              The required operation failed.
162cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
163cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
164cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
165cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCloseProtocolDestroyIpChild (
166cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ControllerHandle,
167cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ImageHandle,
168cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE  ChildHandle
169cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
170cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
171cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
172cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
173cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1746aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Close the previously openned IP protocol.
175cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
176cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseProtocol (
177cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ChildHandle,
178cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         &gEfiIp4ProtocolGuid,
179cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ImageHandle,
180cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         ControllerHandle
181cbf316f20726bb31b7c37424601643790dbd02d9vanjeff         );
182cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
183cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1846aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // Destroy the IP child.
185cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
186cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = NetLibDestroyServiceChild (
187cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ControllerHandle,
188cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ImageHandle,
189cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &gEfiIp4ServiceBindingProtocolGuid,
190cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             ChildHandle
191cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
192cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
193cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
194cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
195cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
196cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
197cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
198e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function handles ICMP packets.
199cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2006aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       IpIo          Pointer to the IP_IO instance.
2016aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  Pkt           Pointer to the ICMP packet.
2026aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Session       Pointer to the net session of this ICMP packet.
203cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2046aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS   The ICMP packet is handled successfully.
2056aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_ABORTED   This type of ICMP packet is not supported.
206cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
207cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
208cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
209cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoIcmpHandler (
2106aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO                *IpIo,
2116aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT NET_BUF              *Pkt,
2126aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     EFI_NET_SESSION_DATA *Session
213cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
214cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
215cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP4_ICMP_ERROR_HEAD  *IcmpHdr;
216cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_HEADER       *IpHdr;
217cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ICMP_ERROR           IcmpErr;
218cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                *PayLoadHdr;
219cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                Type;
220cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT8                Code;
221cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  UINT32               TrimBytes;
222cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
223cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IcmpHdr = NET_PROTO_HDR (Pkt, IP4_ICMP_ERROR_HEAD);
224cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpHdr   = (EFI_IP4_HEADER *) (&IcmpHdr->IpHead);
225cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
226cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
227cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Check the ICMP packet length.
228cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
229cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (Pkt->TotalSize < ICMP_ERRLEN (IpHdr)) {
230cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
231cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ABORTED;
232cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
233cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
234cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Type = IcmpHdr->Head.Type;
235cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Code = IcmpHdr->Head.Code;
236cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
237cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
238cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Analyze the ICMP Error in this ICMP pkt
239cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
240cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  switch (Type) {
241cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_UNREACH:
242cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    switch (Code) {
243cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET:
244cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST:
245cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_PROTOCOL:
246cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_PORT:
247cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_SRCFAIL:
2484eb65aff715faafd9040c6fc85a5d59e22343978vanjeff      IcmpErr = (ICMP_ERROR) (ICMP_ERR_UNREACH_NET + Code);
249cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
250cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
251cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
252cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NEEDFRAG:
253cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_MSGSIZE;
254cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
255cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
256cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
257cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET_UNKNOWN:
258cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_NET_PROHIB:
259cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_TOSNET:
260cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_UNREACH_NET;
261cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
262cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
263cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
264cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST_UNKNOWN:
265cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_ISOLATED:
266cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_HOST_PROHIB:
267cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    case ICMP_CODE_UNREACH_TOSHOST:
268cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IcmpErr = ICMP_ERR_UNREACH_HOST;
269cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
270cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
271cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
272cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    default:
273cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
274cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
275cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
276cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
277cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
278cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_TIMXCEED:
279cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code > 1) {
280cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
281cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
282cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
2834eb65aff715faafd9040c6fc85a5d59e22343978vanjeff    IcmpErr = (ICMP_ERROR) (Code + ICMP_ERR_TIMXCEED_INTRANS);
284cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
285cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
286cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
287cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_PARAMPROB:
288cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code > 1) {
289cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
290cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
291cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
292cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IcmpErr = ICMP_ERR_PARAMPROB;
293cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
294cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
295cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
296cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  case ICMP_TYPE_SOURCEQUENCH:
297cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Code != 0) {
298cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      return EFI_ABORTED;
299cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
300cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
301cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IcmpErr = ICMP_ERR_QUENCH;
302cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
303cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    break;
304cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
305cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  default:
306cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ABORTED;
307cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
308cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
309cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
310cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Notify user the ICMP pkt only containing payload except
311cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // IP and ICMP header
312cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
313cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  PayLoadHdr = (UINT8 *) ((UINT8 *) IpHdr + EFI_IP4_HEADER_LEN (IpHdr));
314cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TrimBytes  = (UINT32) (PayLoadHdr - (UINT8 *) IcmpHdr);
315cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
316cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetbufTrim (Pkt, TrimBytes, TRUE);
317cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
318cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);
319cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
320cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
321cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
322cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
323cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
324cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
325e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  Free function for receive token of IP_IO. It is used to
326cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  signal the recycle event to notify IP to recycle the
327cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  data buffer.
328cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
3296aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event to be signaled.
330cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
331cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
332cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
333cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoExtFree (
334cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID  *Event
335cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
336cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
337cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->SignalEvent ((EFI_EVENT) Event);
338cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
339cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
340cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
341cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
342cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Create a send entry to wrap a packet before sending
343cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  out it through IP.
344cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
3456aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo                 Pointer to the IP_IO instance.
3466aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  Pkt                  Pointer to the packet.
3476aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Sender               Pointer to the IP sender.
3486aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Context              Pointer to the context.
3496aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       NotifyData           Pointer to the notify data.
3506aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Dest                 Pointer to the destination IP address.
3516aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Override             Pointer to the overriden IP_IO data.
352cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
353cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return Pointer to the data structure created to wrap the packet. If NULL,
3546aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @return resource limit occurred.
355cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
356cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
357cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_SEND_ENTRY *
358cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreateSndEntry (
3596aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO             *IpIo,
3606aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT NET_BUF           *Pkt,
3616aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     EFI_IP4_PROTOCOL  *Sender,
3626aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID              *Context    OPTIONAL,
3636aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID              *NotifyData OPTIONAL,
3646aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP4_ADDR          Dest,
3656aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_OVERRIDE    *Override
366cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
367cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
368cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY          *SndEntry;
369cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_COMPLETION_TOKEN  *SndToken;
370cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_TRANSMIT_DATA     *TxData;
371cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS                Status;
372cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_OVERRIDE_DATA     *OverrideData;
37334edf2ae729941a6203e4e7f614db32204a9c47dvanjeff  volatile UINT32           Index;
374cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
375cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
376cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for SndEntry
377cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
378e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  SndEntry = AllocatePool (sizeof (IP_IO_SEND_ENTRY));
379cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndEntry) {
380cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return NULL;
381cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
382cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
383cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
384cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for SndToken
385cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
386e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  SndToken = AllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN));
387cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndToken) {
388cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseSndEntry;
389cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
390cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
391cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
392cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
393e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
394cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoTransmitHandler,
395cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  SndEntry,
396cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  &(SndToken->Event)
397cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
398cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
399cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseSndToken;
400cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
401cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
402cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
403cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for TxData
404cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
405e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  TxData = AllocatePool (
406cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    sizeof (EFI_IP4_TRANSMIT_DATA) +
407cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    sizeof (EFI_IP4_FRAGMENT_DATA) * (Pkt->BlockOpNum - 1)
408cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    );
409cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
410cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == TxData) {
411cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseEvent;
412cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
413cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
414cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
415cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Allocate resource for OverrideData if needed
416cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
417cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  OverrideData = NULL;
418cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL != Override) {
419cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
420e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    OverrideData = AllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA));
421cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (NULL == OverrideData) {
422cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      goto ReleaseResource;
423cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
424cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
425cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // Set the fields of OverrideData
426cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
42736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    CopyMem (OverrideData, Override, sizeof (*OverrideData));
428cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
429cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
430cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
431cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Set the fields of TxData
432cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
433e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  CopyMem (&TxData->DestinationAddress, &Dest, sizeof (EFI_IPv4_ADDRESS));
434cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->OverrideData                  = OverrideData;
435cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->OptionsLength                 = 0;
436cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->OptionsBuffer                 = NULL;
437cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->TotalDataLength               = Pkt->TotalSize;
438cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData->FragmentCount                 = Pkt->BlockOpNum;
439cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
440cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
44134edf2ae729941a6203e4e7f614db32204a9c47dvanjeff  for (Index = 0; Index < Pkt->BlockOpNum; Index++) {
442cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    TxData->FragmentTable[Index].FragmentBuffer = Pkt->BlockOp[Index].Head;
443cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    TxData->FragmentTable[Index].FragmentLength = Pkt->BlockOp[Index].Size;
444cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
445cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
446cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
447cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Set the fields of SndToken
448cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
449cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndToken->Packet.TxData = TxData;
450cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
451cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
452cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Set the fields of SndEntry
453cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
454cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->IpIo        = IpIo;
4556aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  SndEntry->Ip          = Sender;
456cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->Context     = Context;
457cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->NotifyData  = NotifyData;
458cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
459cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->Pkt         = Pkt;
460cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_GET_REF (Pkt);
461cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
462cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry->SndToken = SndToken;
463cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
464e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertTailList (&IpIo->PendingSndList, &SndEntry->Entry);
465cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
466cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return SndEntry;
467cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
468cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseResource:
469e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (TxData);
470cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
471cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseEvent:
472cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseEvent (SndToken->Event);
473cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
474cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseSndToken:
475e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (SndToken);
476cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
477cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseSndEntry:
478e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (SndEntry);
479cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
480cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
481cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
482cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
483cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
484cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
485cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy the SndEntry.
486e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
487e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function pairs with IpIoCreateSndEntry().
488cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
4896aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  SndEntry              Pointer to the send entry to be destroyed.
490cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
491cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
492cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
493cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoDestroySndEntry (
494cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO_SEND_ENTRY  *SndEntry
495cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
496cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
497cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_TRANSMIT_DATA  *TxData;
498cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
499cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  TxData = SndEntry->SndToken->Packet.TxData;
500cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
501cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL != TxData->OverrideData) {
502e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    gBS->FreePool (TxData->OverrideData);
503cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
504cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
505e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (TxData);
506cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NetbufFree (SndEntry->Pkt);
507cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseEvent (SndEntry->SndToken->Event);
508cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
509e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (SndEntry->SndToken);
510e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RemoveEntryList (&SndEntry->Entry);
511cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
512e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (SndEntry);
513cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
514cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
515cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
516cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
517cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Notify function for IP transmit token.
518cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
5196aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
520cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
521cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
522cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
523cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
52436ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoTransmitHandlerDpc (
525cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
526cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
527cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
528cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO             *IpIo;
529cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
530cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
531cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry  = (IP_IO_SEND_ENTRY *) Context;
532cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
533cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo      = SndEntry->IpIo;
534cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
5358de75da28bbd9a4d3c54fba99d943f9019b52193niry  if ((IpIo->PktSentNotify != NULL) && (SndEntry->NotifyData != NULL)) {
536cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->PktSentNotify (
537cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->SndToken->Status,
538cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->Context,
539cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->Ip,
540cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            SndEntry->NotifyData
541cbf316f20726bb31b7c37424601643790dbd02d9vanjeff            );
542cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
543cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
544cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoDestroySndEntry (SndEntry);
545cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
546cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
5476aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu
54836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff/**
54936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  Notify function for IP transmit token.
55036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
5516aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event signaled.
5526aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
55336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
55436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff**/
55536ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
55636ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
55736ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoTransmitHandler (
55836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN EFI_EVENT Event,
55936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
56036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  )
56136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff{
56236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
56336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK
56436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
56536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  NetLibQueueDpc (TPL_CALLBACK, IpIoTransmitHandlerDpc, Context);
56636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff}
56736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
568cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
569cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
570cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  The dummy handler for the dummy IP receive token.
571cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
5726aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
573cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
574cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
575cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
576cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
57736ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoDummyHandlerDpc (
578cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
579cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
580cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
581cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO             *IpInfo;
582cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_COMPLETION_TOKEN  *DummyToken;
583cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
584cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo      = (IP_IO_IP_INFO *) Context;
585cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  DummyToken  = &(IpInfo->DummyRcvToken);
586cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
58736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  if (EFI_ABORTED == DummyToken->Status) {
58836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
58936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    // The reception is actively aborted by the consumer, directly return.
59036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
59136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    return;
59236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  } else if (EFI_SUCCESS == DummyToken->Status) {
5936aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    ASSERT ((DummyToken->Packet.RxData)!= NULL);
594cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
595cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    gBS->SignalEvent (DummyToken->Packet.RxData->RecycleSignal);
596cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
597cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
598cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->Ip->Receive (IpInfo->Ip, DummyToken);
599cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
600cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
601cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
602cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
6036aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  This function add IpIoDummyHandlerDpc to the end of the DPC queue.
604cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
6056aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                 The event signaled.
6066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
607cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
608cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
609cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
610cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFIAPI
61136ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoDummyHandler (
612cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_EVENT Event,
613cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID      *Context
614cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
615cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
61636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
61736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK
61836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
61936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  NetLibQueueDpc (TPL_CALLBACK, IpIoDummyHandlerDpc, Context);
62036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff}
62136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
62236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
62336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff/**
62436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  Notify function for the IP receive token, used to process
62536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  the received IP packets.
62636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
6276aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context               The context passed in by the event notifier.
62836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
62936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff**/
63036ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
63136ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
63236ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoListenHandlerDpc (
63336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
63436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  )
63536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff{
636cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO                 *IpIo;
637cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS            Status;
638cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_RECEIVE_DATA  *RxData;
639cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL      *Ip;
640cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_NET_SESSION_DATA  Session;
641cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_BUF               *Pkt;
642cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
643cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo    = (IP_IO *) Context;
644cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
645cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip      = IpIo->Ip;
646cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status  = IpIo->RcvToken.Status;
647cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  RxData  = IpIo->RcvToken.Packet.RxData;
648cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
64936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  if (EFI_ABORTED == Status) {
65036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
65136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    // The reception is actively aborted by the consumer, directly return.
65236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
65336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    return;
65436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  }
65536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
656cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (((EFI_SUCCESS != Status) && (EFI_ICMP_ERROR != Status)) || (NULL == RxData)) {
657cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
6586aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // @bug Only process the normal packets and the icmp error packets, if RxData is NULL
6596aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // @bug with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
6606aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu    // @bug this should be a bug of the low layer (IP).
661cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
662cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto Resume;
663cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
664cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
665cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == IpIo->PktRcvdNotify) {
666cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
667cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
668cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
669cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if ((EFI_IP4 (RxData->Header->SourceAddress) != 0) &&
670cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    !Ip4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), 0)) {
671cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
672cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // The source address is not zero and it's not a unicast IP address, discard it.
673cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
674cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
675cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
676cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
677cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
678cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create a netbuffer representing packet
679cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
680cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Pkt = NetbufFromExt (
681cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          (NET_FRAGMENT *) RxData->FragmentTable,
682cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          RxData->FragmentCount,
683cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          0,
684cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          0,
685cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          IpIoExtFree,
686cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          RxData->RecycleSignal
687cbf316f20726bb31b7c37424601643790dbd02d9vanjeff          );
688cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == Pkt) {
689cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto CleanUp;
690cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
691cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
692cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
693cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create a net session
694cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
695cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Session.Source = EFI_IP4 (RxData->Header->SourceAddress);
696cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Session.Dest   = EFI_IP4 (RxData->Header->DestinationAddress);
697cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Session.IpHdr  = RxData->Header;
698cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
699cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_SUCCESS == Status) {
700cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
7014eb65aff715faafd9040c6fc85a5d59e22343978vanjeff    IpIo->PktRcvdNotify (EFI_SUCCESS, (ICMP_ERROR) 0, &Session, Pkt, IpIo->RcvdContext);
702cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  } else {
703cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
704cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // Status is EFI_ICMP_ERROR
705cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
706cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    Status = IpIoIcmpHandler (IpIo, Pkt, &Session);
707cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (EFI_ERROR (Status)) {
708cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      NetbufFree (Pkt);
709cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
710cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
711cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
712cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  goto Resume;
713cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
714cbf316f20726bb31b7c37424601643790dbd02d9vanjeffCleanUp:
715cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->SignalEvent (RxData->RecycleSignal);
716cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
717cbf316f20726bb31b7c37424601643790dbd02d9vanjeffResume:
718cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip->Receive (Ip, &(IpIo->RcvToken));
719cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
720cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
721cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
722cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
7236aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  This function add IpIoListenHandlerDpc to the end of the DPC queue.
72436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
7256aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Event                The event signaled.
7266aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Context              The context passed in by the event notifier.
72736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
72836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff**/
72936ee91ca3661d3d020a7841aacbf858d885c4728vanjeffVOID
73036ee91ca3661d3d020a7841aacbf858d885c4728vanjeffEFIAPI
73136ee91ca3661d3d020a7841aacbf858d885c4728vanjeffIpIoListenHandler (
73236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN EFI_EVENT Event,
73336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  IN VOID      *Context
73436ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  )
73536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff{
73636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
73736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
73836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
73936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  NetLibQueueDpc (TPL_CALLBACK, IpIoListenHandlerDpc, Context);
74036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff}
74136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
74236ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
74336ee91ca3661d3d020a7841aacbf858d885c4728vanjeff/**
744cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Create a new IP_IO instance.
745e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
746e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function uses IP4 service binding protocol in Controller to create an IP4
747e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  child (aka IP4 instance).
748cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
7496aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Image             The image handle of the driver or application that
750e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong                                consumes IP_IO.
7516aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Controller        The controller handle that has IP4 service binding
752e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong                                protocol installed.
753cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
754e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  @return Pointer to a newly created IP_IO instance, or NULL if failed.
755cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
756cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
757cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO *
7587b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
759cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCreate (
760cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE Image,
761cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN EFI_HANDLE Controller
762cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
763cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
764cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS  Status;
765cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO       *IpIo;
766cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
767e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  IpIo = AllocateZeroPool (sizeof (IP_IO));
768cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == IpIo) {
769cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return NULL;
770cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
771cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
772e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&(IpIo->PendingSndList));
773e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&(IpIo->IpList));
774cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Controller  = Controller;
775cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Image       = Image;
776cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
777cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
778cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
779e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
780cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoListenHandler,
781cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIo,
782cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  &(IpIo->RcvToken.Event)
783cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
784cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
785cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpIo;
786cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
787cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
788cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
789cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create an IP child and open IP protocol
790cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
791cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = IpIoCreateIpChildOpenProtocol (
792cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             Controller,
793cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             Image,
794cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &IpIo->ChildHandle,
795cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             (VOID **)&(IpIo->Ip)
796cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
797cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
798cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpIo;
799cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
800cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
801cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return IpIo;
802cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
803cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpIo:
804cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
805cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL != IpIo->RcvToken.Event) {
806cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    gBS->CloseEvent (IpIo->RcvToken.Event);
807cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
808cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
809e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpIo);
810cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
811cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
812cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
813cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
814cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
815cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
816cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Open an IP_IO instance for use.
817e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
818e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is called after IpIoCreate(). It is used for configuring the IP
819e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  instance and register the callbacks and their context data for sending and
820e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  receiving IP packets.
821cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
8226aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo               Pointer to an IP_IO instance that needs
8236aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      to open.
8246aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       OpenData           The configuration data and callbacks for
8256aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      the IP_IO instance.
826cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
8276aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS        The IP_IO instance opened with OpenData
8286aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      successfully.
8296aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_ACCESS_DENIED  The IP_IO instance is configured, avoid to
8306aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      reopen it.
8316aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others             Error condition occurred.
832cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
833cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
834cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
8357b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
836cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoOpen (
8376aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO           *IpIo,
8386aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_OPEN_DATA *OpenData
839cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
840cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
841cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
842cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL  *Ip;
843cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
844cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpIo->IsConfigured) {
845cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_ACCESS_DENIED;
846cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
847cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
848cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpIo->Ip;
849cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
850cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
851cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // configure ip
852cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
853cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Configure (Ip, &OpenData->IpConfigData);
854cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
855cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
856cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
857cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
858cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
8596aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // @bug To delete the default route entry in this Ip, if it is:
8606aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // @bug (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified
8616aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // @bug its code
862cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
863b61439a709bb961f2f9dff1d1a4112e30a063f51vanjeff  Status = Ip->Routes (Ip, TRUE, &mZeroIp4Addr, &mZeroIp4Addr, &mZeroIp4Addr);
864cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
865cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status) && (EFI_NOT_FOUND != Status)) {
866cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
867cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
868cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
869cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktRcvdNotify = OpenData->PktRcvdNotify;
870cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->PktSentNotify = OpenData->PktSentNotify;
871cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
872cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->RcvdContext   = OpenData->RcvdContext;
873cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->SndContext    = OpenData->SndContext;
874cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
875cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->Protocol      = OpenData->IpConfigData.DefaultProtocol;
876cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
877cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
878cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // start to listen incoming packet
879cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
880cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Receive (Ip, &(IpIo->RcvToken));
881cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
882cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    Ip->Configure (Ip, NULL);
883cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ErrorExit;
884cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
885cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
886cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->IsConfigured = TRUE;
887e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertTailList (&mActiveIpIoList, &IpIo->Entry);
888cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
889cbf316f20726bb31b7c37424601643790dbd02d9vanjeffErrorExit:
890cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
891cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
892cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
893cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
894cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
895cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
896cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Stop an IP_IO instance.
897e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
898e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is paired with IpIoOpen(). The IP_IO will be unconfigured and all
899e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  the pending send/receive tokens will be canceled.
900cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
9016aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo            Pointer to the IP_IO instance that needs to stop.
902cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
9036aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS     The IP_IO instance stopped successfully.
9046aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others          Error condition occurred.
905cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
906cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
907cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
908e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgongEFIAPI
909cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoStop (
9106aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO *IpIo
911cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
912cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
913cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
914cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL  *Ip;
915cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO     *IpInfo;
916cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
917cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (!IpIo->IsConfigured) {
918cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_SUCCESS;
919cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
920cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
921cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
922cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Remove the IpIo from the active IpIo list.
923cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
924e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RemoveEntryList (&IpIo->Entry);
925cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
926cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpIo->Ip;
927cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
928cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
929cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Configure NULL Ip
930cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
931cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Configure (Ip, NULL);
932cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
933cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return Status;
934cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
935cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
936cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIo->IsConfigured = FALSE;
937cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
938cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
939cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Detroy the Ip List used by IpIo
940cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
94134edf2ae729941a6203e4e7f614db32204a9c47dvanjeff
942e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  while (!IsListEmpty (&(IpIo->IpList))) {
943cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo = NET_LIST_HEAD (&(IpIo->IpList), IP_IO_IP_INFO, Entry);
944cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
945cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoRemoveIp (IpIo, IpInfo);
946cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
947cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
948cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
9496aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  // All pending send tokens should be flushed by reseting the IP instances.
950cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
951e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  ASSERT (IsListEmpty (&IpIo->PendingSndList));
952cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
953cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
954cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Close the receive event.
955cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
956cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseEvent (IpIo->RcvToken.Event);
957cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
958cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
959cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
960cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
961cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
962cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
963cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy an IP_IO instance.
964e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
965e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is paired with IpIoCreate(). The IP_IO will be closed first.
9668f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  Resource will be freed afterwards. See IpIoCloseProtocolDestroyIpChild().
967cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
9686aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo         Pointer to the IP_IO instance that needs to be
969e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong                                destroyed.
970cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
9716aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS  The IP_IO instance destroyed successfully.
9726aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others       Error condition occurred.
973cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
974cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
975cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
9767b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
977cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoDestroy (
9786aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO *IpIo
979cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
980cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
981cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
982cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Stop the IpIo.
983cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
984cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoStop (IpIo);
985cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
986cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
987cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Close the IP protocol and destroy the child.
988cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
989cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpIo->ChildHandle);
990cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
991e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpIo);
992cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
993cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return EFI_SUCCESS;
994cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
995cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
996cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
997cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
998cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Send out an IP packet.
999e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1000e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is called after IpIoOpen(). The data to be sent are wrapped in
1001e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  Pkt. The IP instance wrapped in IpIo is used for sending by default but can be
1002e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  overriden by Sender. Other sending configs, like source address and gateway
1003e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  address etc., are specified in OverrideData.
1004cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
10056aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo                  Pointer to an IP_IO instance used for sending IP
10066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                         packet.
10076aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  Pkt                   Pointer to the IP packet to be sent.
10086aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Sender                The IP protocol instance used for sending.
10098f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[in]       Context               Optional context data.
10108f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[in]       NotifyData            Optional notify data.
10116aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Dest                  The destination IP address to send this packet to.
10126aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       OverrideData          The data to override some configuration of the IP
10136aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                         instance used for sending.
1014cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
10156aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS           The operation is completed successfully.
10166aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_NOT_STARTED       The IpIo is not configured.
10176aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_OUT_OF_RESOURCES  Failed due to resource limit.
1018cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1019cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1020cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
10217b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1022cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoSend (
10236aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO          *IpIo,
10246aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT NET_BUF        *Pkt,
10256aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_IP_INFO  *Sender        OPTIONAL,
10266aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID           *Context       OPTIONAL,
10276aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     VOID           *NotifyData    OPTIONAL,
10286aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP4_ADDR       Dest,
10296aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN     IP_IO_OVERRIDE *OverrideData  OPTIONAL
1030cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1031cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1032cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS        Status;
1033cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL  *Ip;
1034cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
1035cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1036cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (!IpIo->IsConfigured) {
1037cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_NOT_STARTED;
1038cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1039cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1040cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = (NULL == Sender) ? IpIo->Ip : Sender->Ip;
1041cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1042cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1043cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // create a new SndEntry
1044cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1045cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  SndEntry = IpIoCreateSndEntry (IpIo, Pkt, Ip, Context, NotifyData, Dest, OverrideData);
1046cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (NULL == SndEntry) {
1047cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_OUT_OF_RESOURCES;
1048cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1049cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1050cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1051cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Send this Packet
1052cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1053cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Transmit (Ip, SndEntry->SndToken);
1054cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1055cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoDestroySndEntry (SndEntry);
1056cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1057cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1058cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
1059cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1060cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1061cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1062cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1063cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Cancel the IP transmit token which wraps this Packet.
1064cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
10656aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  IpIo                  Pointer to the IP_IO instance.
10666aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  Packet                Pointer to the packet of NET_BUF to cancel.
1067cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1068cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1069cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
10707b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1071cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoCancelTxToken (
1072cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN IP_IO  *IpIo,
1073cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN VOID   *Packet
1074cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1075cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1076e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  LIST_ENTRY        *Node;
1077cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_SEND_ENTRY  *SndEntry;
1078cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL  *Ip;
1079cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
10806aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  ASSERT ((IpIo)!= NULL && (Packet)!= NULL);
1081cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1082cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_FOR_EACH (Node, &IpIo->PendingSndList) {
1083cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1084cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    SndEntry = NET_LIST_USER_STRUCT (Node, IP_IO_SEND_ENTRY, Entry);
1085cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1086cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (SndEntry->Pkt == Packet) {
1087cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1088cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip = SndEntry->Ip;
1089cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip->Cancel (Ip, SndEntry->SndToken);
1090cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1091cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      break;
1092cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1093cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1094cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1095cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1096cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1097cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1098cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1099cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Add a new IP instance for sending data.
1100e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1101e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  The function is used to add the IP_IO to the IP_IO sending list. The caller
1102e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send
1103e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  data.
1104cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
11056aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo               Pointer to a IP_IO instance to add a new IP
11066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                      instance for sending purpose.
1107cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1108e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  @return Pointer to the created IP_IO_IP_INFO structure, NULL if failed.
1109cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1110cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1111cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_IP_INFO *
11127b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1113cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoAddIp (
11146aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO  *IpIo
1115cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1116cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1117cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS     Status;
1118cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO  *IpInfo;
1119cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
11206aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  ASSERT (IpIo != NULL);
1121cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1122e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  IpInfo = AllocatePool (sizeof (IP_IO_IP_INFO));
1123cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo == NULL) {
1124cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return IpInfo;
1125cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1126cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1127cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1128cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP
1129cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // instance.
1130cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1131e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&IpInfo->Entry);
1132cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->ChildHandle = NULL;
1133cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->Addr        = 0;
1134cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->SubnetMask  = 0;
1135cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->RefCnt      = 1;
1136cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1137cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1138cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create the IP instance and open the Ip4 protocol.
1139cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1140cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = IpIoCreateIpChildOpenProtocol (
1141cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             IpIo->Controller,
1142cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             IpIo->Image,
1143cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             &IpInfo->ChildHandle,
11444eb65aff715faafd9040c6fc85a5d59e22343978vanjeff             (VOID **) &IpInfo->Ip
1145cbf316f20726bb31b7c37424601643790dbd02d9vanjeff             );
1146cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1147cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpInfo;
1148cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1149cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1150cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1151cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Create the event for the DummyRcvToken.
1152cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1153cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = gBS->CreateEvent (
1154cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  EVT_NOTIFY_SIGNAL,
1155e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
1156cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpIoDummyHandler,
1157cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  IpInfo,
1158cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  &IpInfo->DummyRcvToken.Event
1159cbf316f20726bb31b7c37424601643790dbd02d9vanjeff                  );
1160cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1161cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto ReleaseIpChild;
1162cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1163cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1164cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1165cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // Link this IpInfo into the IpIo.
1166cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1167e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertTailList (&IpIo->IpList, &IpInfo->Entry);
1168cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1169cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return IpInfo;
1170cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1171cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpChild:
1172cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1173cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoCloseProtocolDestroyIpChild (
1174cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->Controller,
1175cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIo->Image,
1176cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo->ChildHandle
1177cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    );
1178cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1179cbf316f20726bb31b7c37424601643790dbd02d9vanjeffReleaseIpInfo:
1180cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1181e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpInfo);
1182cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1183cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
1184cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1185cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1186cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1187cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1188cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Configure the IP instance of this IpInfo and start the receiving if Ip4ConfigData
1189cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  is not NULL.
1190cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
11916aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpInfo          Pointer to the IP_IO_IP_INFO instance.
11926aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  Ip4ConfigData   The IP4 configure data used to configure the IP
11936aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   instance, if NULL the IP instance is reset. If
11946aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   UseDefaultAddress is set to TRUE, and the configure
11956aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   operation succeeds, the default address information
11966aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   is written back in this Ip4ConfigData.
1197cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
11986aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          EFI_SUCCESS     The IP instance of this IpInfo is configured successfully
11996aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu                                   or no need to reconfigure it.
12006aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @retval          Others          Configuration fails.
1201cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1202cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1203cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
12047b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1205cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoConfigIp (
12066aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  IN OUT IP_IO_IP_INFO        *IpInfo,
1207cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN OUT EFI_IP4_CONFIG_DATA  *Ip4ConfigData OPTIONAL
1208cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1209cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1210cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_STATUS         Status;
1211cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_PROTOCOL   *Ip;
1212cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  EFI_IP4_MODE_DATA  Ip4ModeData;
1213cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
12146aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  ASSERT (IpInfo != NULL);
1215cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1216cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo->RefCnt > 1) {
1217cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1218cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // This IP instance is shared, don't reconfigure it until it has only one
1219cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // consumer. Currently, only the tcp children cloned from their passive parent
1220cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,
1221cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // let the last consumer clean the IP instance.
1222cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1223cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return EFI_SUCCESS;
1224cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1225cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1226cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Ip = IpInfo->Ip;
1227cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1228cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Status = Ip->Configure (Ip, Ip4ConfigData);
1229cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (EFI_ERROR (Status)) {
1230cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    goto OnExit;
1231cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1232cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1233cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (Ip4ConfigData != NULL) {
1234cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1235cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (Ip4ConfigData->UseDefaultAddress) {
1236cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip->GetModeData (Ip, &Ip4ModeData, NULL, NULL);
1237cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1238cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip4ConfigData->StationAddress = Ip4ModeData.ConfigData.StationAddress;
1239cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip4ConfigData->SubnetMask     = Ip4ModeData.ConfigData.SubnetMask;
1240cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1241cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1242e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (&IpInfo->Addr, &Ip4ConfigData->StationAddress, sizeof (IP4_ADDR));
1243e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (&IpInfo->SubnetMask, &Ip4ConfigData->SubnetMask, sizeof (IP4_ADDR));
1244cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1245cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    Status = Ip->Receive (Ip, &IpInfo->DummyRcvToken);
1246cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if (EFI_ERROR (Status)) {
1247cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      Ip->Configure (Ip, NULL);
1248cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1249cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  } else {
1250cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1251cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1252cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    // The IP instance is reseted, set the stored Addr and SubnetMask to zero.
1253cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    //
1254cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo->Addr       = 0;
1255cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpInfo->SubnetMask =0;
1256cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1257cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1258cbf316f20726bb31b7c37424601643790dbd02d9vanjeffOnExit:
1259cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1260cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return Status;
1261cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1262cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1263cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1264cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1265cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Destroy an IP instance maintained in IpIo->IpList for
1266cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  sending purpose.
1267e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1268e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function pairs with IpIoAddIp(). The IpInfo is previously created by
1269e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance
1270e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  will be dstroyed if the RefCnt is zero.
1271cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
12726aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  IpIo                  Pointer to the IP_IO instance.
12736aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]  IpInfo                Pointer to the IpInfo to be removed.
1274cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1275cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1276cbf316f20726bb31b7c37424601643790dbd02d9vanjeffVOID
12777b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1278cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoRemoveIp (
1279e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IN IP_IO            *IpIo,
1280e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  IN IP_IO_IP_INFO    *IpInfo
1281cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1282cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1283cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  ASSERT (IpInfo->RefCnt > 0);
1284cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1285cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_PUT_REF (IpInfo);
1286cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1287cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  if (IpInfo->RefCnt > 0) {
1288cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1289cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    return;
1290cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1291cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1292e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RemoveEntryList (&IpInfo->Entry);
1293cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1294cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpInfo->Ip->Configure (IpInfo->Ip, NULL);
1295cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1296cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpInfo->ChildHandle);
1297cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1298cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  gBS->CloseEvent (IpInfo->DummyRcvToken.Event);
1299cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1300e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->FreePool (IpInfo);
1301cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1302cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1303cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1304cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1305cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  Find the first IP protocol maintained in IpIo whose local
1306cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  address is the same with Src.
1307e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1308e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  This function is called when the caller needs the IpIo to send data to the
1309e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  specified Src. The IpIo was added previously by IpIoAddIp().
1310cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
13116aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in, out]  IpIo              Pointer to the pointer of the IP_IO instance.
13126aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @param[in]       Src               The local IP address.
1313cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1314cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  @return Pointer to the IP protocol can be used for sending purpose and its local
13156aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @return address is the same with Src.
1316cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1317cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1318cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIP_IO_IP_INFO *
13197b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1320cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoFindSender (
1321cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN OUT IP_IO     **IpIo,
1322cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN     IP4_ADDR  Src
1323cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1324cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
1325e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  LIST_ENTRY      *IpIoEntry;
1326cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO           *IpIoPtr;
1327e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  LIST_ENTRY      *IpInfoEntry;
1328cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IP_IO_IP_INFO   *IpInfo;
1329cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1330cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  NET_LIST_FOR_EACH (IpIoEntry, &mActiveIpIoList) {
1331cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    IpIoPtr = NET_LIST_USER_STRUCT (IpIoEntry, IP_IO, Entry);
1332cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1333cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    if ((*IpIo != NULL) && (*IpIo != IpIoPtr)) {
1334cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      continue;
1335cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1336cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1337cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    NET_LIST_FOR_EACH (IpInfoEntry, &IpIoPtr->IpList) {
1338cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      IpInfo = NET_LIST_USER_STRUCT (IpInfoEntry, IP_IO_IP_INFO, Entry);
1339cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1340cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      if (IpInfo->Addr == Src) {
1341cbf316f20726bb31b7c37424601643790dbd02d9vanjeff        *IpIo = IpIoPtr;
1342cbf316f20726bb31b7c37424601643790dbd02d9vanjeff        return IpInfo;
1343cbf316f20726bb31b7c37424601643790dbd02d9vanjeff      }
1344cbf316f20726bb31b7c37424601643790dbd02d9vanjeff    }
1345cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1346cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1347cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1348cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  // No match.
1349cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  //
1350cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  return NULL;
1351cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1352cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1353cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1354cbf316f20726bb31b7c37424601643790dbd02d9vanjeff/**
1355e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  Get the ICMP error map information.
1356e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong
1357e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  The ErrorStatus will be returned. The IsHard and Notify are optional. If they
1358e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  are not NULL, this routine will fill them.
1359cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
13608f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[in]   IcmpError             IcmpError Type.
13618f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[out]  IsHard                Whether it is a hard error.
13628f5e6151d506b69e4156eeb401a3bbc9f03a4a8dywu  @param[out]  Notify                Whether it need to notify SockError.
1363cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
13646aac5e5ff0dccb7e2603bb2639c0e271b30301f5ywu  @return ICMP Error Status, such as EFI_NETWORK_UNREACHABLE.
1365cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1366cbf316f20726bb31b7c37424601643790dbd02d9vanjeff**/
1367cbf316f20726bb31b7c37424601643790dbd02d9vanjeffEFI_STATUS
13687b414b4ed6ccdefce8e167ecc7d67ad64118eb94vanjeffEFIAPI
1369cbf316f20726bb31b7c37424601643790dbd02d9vanjeffIpIoGetIcmpErrStatus (
1370cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  IN  ICMP_ERROR  IcmpError,
1371e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  OUT BOOLEAN     *IsHard  OPTIONAL,
1372e6ff63a51423a3cbc26bc463ec07ad22fb60e07djgong  OUT BOOLEAN     *Notify  OPTIONAL
1373cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  )
1374cbf316f20726bb31b7c37424601643790dbd02d9vanjeff{
137501750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  ASSERT ((IcmpError >= ICMP_ERR_UNREACH_NET) && (IcmpError <= ICMP_ERR_PARAMPROB));
1376687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
137701750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  if (IsHard != NULL) {
137801750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    *IsHard = mIcmpErrMap[IcmpError].IsHard;
137901750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  }
1380687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
138101750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  if (Notify != NULL) {
138201750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    *Notify = mIcmpErrMap[IcmpError].Notify;
138301750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  }
1384687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
138501750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  switch (IcmpError) {
138601750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_UNREACH_NET:
138701750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    return  EFI_NETWORK_UNREACHABLE;
1388687a2e5f6902fa26c7a1d7a7705e0747c4095125vanjeff
138901750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_TIMXCEED_INTRANS:
139001750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_TIMXCEED_REASS:
139101750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_UNREACH_HOST:
139201750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    return  EFI_HOST_UNREACHABLE;
1393cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
139401750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_UNREACH_PROTOCOL:
139501750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    return  EFI_PROTOCOL_UNREACHABLE;
1396cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
139701750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_UNREACH_PORT:
139801750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    return  EFI_PORT_UNREACHABLE;
1399cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
140001750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_MSGSIZE:
140101750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_UNREACH_SRCFAIL:
140201750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_QUENCH:
140301750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  case ICMP_ERR_PARAMPROB:
140401750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff    return  EFI_ICMP_ERROR;
1405cbf316f20726bb31b7c37424601643790dbd02d9vanjeff  }
1406cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
140701750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  //
140801750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  // will never run here!
140901750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  //
141001750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  ASSERT (FALSE);
141101750eb0aad0510c13da7453fa0c0b64aef0bc72vanjeff  return EFI_UNSUPPORTED;
1412cbf316f20726bb31b7c37424601643790dbd02d9vanjeff}
1413cbf316f20726bb31b7c37424601643790dbd02d9vanjeff
1414