1a88c31639bb24c73383a4528a5b77066e805148blpleahy/** @file
2a88c31639bb24c73383a4528a5b77066e805148blpleahy  Implement the IP4 driver support for the socket layer.
3a88c31639bb24c73383a4528a5b77066e805148blpleahy
4c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu  Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
50e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin  This program and the accompanying materials are licensed and made available
60e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin  under the terms and conditions of the BSD License which accompanies this
70e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin  distribution.  The full text of the license may be found at
80e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin  http://opensource.org/licenses/bsd-license.php.
9a88c31639bb24c73383a4528a5b77066e805148blpleahy
10a88c31639bb24c73383a4528a5b77066e805148blpleahy  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11a88c31639bb24c73383a4528a5b77066e805148blpleahy  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
13a88c31639bb24c73383a4528a5b77066e805148blpleahy#include "Socket.h"
14a88c31639bb24c73383a4528a5b77066e805148blpleahy
15a88c31639bb24c73383a4528a5b77066e805148blpleahy
16beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Get the local socket address.
17a88c31639bb24c73383a4528a5b77066e805148blpleahy
18a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine returns the IPv4 address associated with the local
19a88c31639bb24c73383a4528a5b77066e805148blpleahy  socket.
20a88c31639bb24c73383a4528a5b77066e805148blpleahy
21a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by ::EslSocketGetLocalAddress to determine the
22a88c31639bb24c73383a4528a5b77066e805148blpleahy  network address for the SOCK_RAW socket.
23a88c31639bb24c73383a4528a5b77066e805148blpleahy
24a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pPort       Address of an ::ESL_PORT structure.
25a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [out] pAddress   Network address to receive the local system address
26a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
27a88c31639bb24c73383a4528a5b77066e805148blpleahyVOID
28a88c31639bb24c73383a4528a5b77066e805148blpleahyEslIp4LocalAddressGet (
29a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort,
30a88c31639bb24c73383a4528a5b77066e805148blpleahy  OUT struct sockaddr * pAddress
31a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
32a88c31639bb24c73383a4528a5b77066e805148blpleahy{
33a88c31639bb24c73383a4528a5b77066e805148blpleahy  struct sockaddr_in * pLocalAddress;
34a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IP4_CONTEXT * pIp4;
35a88c31639bb24c73383a4528a5b77066e805148blpleahy
36a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
37a88c31639bb24c73383a4528a5b77066e805148blpleahy
38a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the local address
39a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIp4 = &pPort->Context.Ip4;
40a88c31639bb24c73383a4528a5b77066e805148blpleahy  pLocalAddress = (struct sockaddr_in *)pAddress;
41a88c31639bb24c73383a4528a5b77066e805148blpleahy  pLocalAddress->sin_family = AF_INET;
42a88c31639bb24c73383a4528a5b77066e805148blpleahy  CopyMem ( &pLocalAddress->sin_addr,
43a88c31639bb24c73383a4528a5b77066e805148blpleahy            &pIp4->ModeData.ConfigData.StationAddress.Addr[0],
44a88c31639bb24c73383a4528a5b77066e805148blpleahy            sizeof ( pLocalAddress->sin_addr ));
45a88c31639bb24c73383a4528a5b77066e805148blpleahy
46a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT ( );
47a88c31639bb24c73383a4528a5b77066e805148blpleahy}
48a88c31639bb24c73383a4528a5b77066e805148blpleahy
49a88c31639bb24c73383a4528a5b77066e805148blpleahy
50beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Set the local port address.
51a88c31639bb24c73383a4528a5b77066e805148blpleahy
52a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine sets the local port address.
53a88c31639bb24c73383a4528a5b77066e805148blpleahy
54a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support routine is called by ::EslSocketPortAllocate.
55a88c31639bb24c73383a4528a5b77066e805148blpleahy
56a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pPort       Address of an ESL_PORT structure
57a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pSockAddr   Address of a sockaddr structure that contains the
58a88c31639bb24c73383a4528a5b77066e805148blpleahy                          connection point on the local machine.  An IPv4 address
59a88c31639bb24c73383a4528a5b77066e805148blpleahy                          of INADDR_ANY specifies that the connection is made to
60a88c31639bb24c73383a4528a5b77066e805148blpleahy                          all of the network stacks on the platform.  Specifying a
61a88c31639bb24c73383a4528a5b77066e805148blpleahy                          specific IPv4 address restricts the connection to the
62a88c31639bb24c73383a4528a5b77066e805148blpleahy                          network stack supporting that address.  Specifying zero
63a88c31639bb24c73383a4528a5b77066e805148blpleahy                          for the port causes the network layer to assign a port
64a88c31639bb24c73383a4528a5b77066e805148blpleahy                          number from the dynamic range.  Specifying a specific
65a88c31639bb24c73383a4528a5b77066e805148blpleahy                          port number causes the network layer to use that port.
66a88c31639bb24c73383a4528a5b77066e805148blpleahy
67a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] bBindTest   TRUE = run bind testing
68a88c31639bb24c73383a4528a5b77066e805148blpleahy
69a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS     The operation was successful
70a88c31639bb24c73383a4528a5b77066e805148blpleahy **/
71a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
72a88c31639bb24c73383a4528a5b77066e805148blpleahyEslIp4LocalAddressSet (
73a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort,
74a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN CONST struct sockaddr * pSockAddr,
75a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN BOOLEAN bBindTest
76a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
77a88c31639bb24c73383a4528a5b77066e805148blpleahy{
78a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_IP4_CONFIG_DATA * pConfig;
79a88c31639bb24c73383a4528a5b77066e805148blpleahy  CONST struct sockaddr_in * pIpAddress;
80a88c31639bb24c73383a4528a5b77066e805148blpleahy  CONST UINT8 * pIpv4Address;
81a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
82a88c31639bb24c73383a4528a5b77066e805148blpleahy
83a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
84a88c31639bb24c73383a4528a5b77066e805148blpleahy
85a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Validate the address
86a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIpAddress = (struct sockaddr_in *)pSockAddr;
87a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) {
88a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  The local address must not be the broadcast address
89a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = EFI_INVALID_PARAMETER;
90a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->pSocket->errno = EADDRNOTAVAIL;
91a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
92a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
93a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = EFI_SUCCESS;
94a88c31639bb24c73383a4528a5b77066e805148blpleahy
95a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Set the local address
96a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIpAddress = (struct sockaddr_in *)pSockAddr;
97a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr;
98a88c31639bb24c73383a4528a5b77066e805148blpleahy    pConfig = &pPort->Context.Ip4.ModeData.ConfigData;
99a88c31639bb24c73383a4528a5b77066e805148blpleahy    pConfig->StationAddress.Addr[0] = pIpv4Address[0];
100a88c31639bb24c73383a4528a5b77066e805148blpleahy    pConfig->StationAddress.Addr[1] = pIpv4Address[1];
101a88c31639bb24c73383a4528a5b77066e805148blpleahy    pConfig->StationAddress.Addr[2] = pIpv4Address[2];
102a88c31639bb24c73383a4528a5b77066e805148blpleahy    pConfig->StationAddress.Addr[3] = pIpv4Address[3];
103a88c31639bb24c73383a4528a5b77066e805148blpleahy
104a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Determine if the default address is used
105a88c31639bb24c73383a4528a5b77066e805148blpleahy    pConfig->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr );
106a88c31639bb24c73383a4528a5b77066e805148blpleahy
107a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Display the local address
108a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_BIND,
109a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Port, Local IP4 Address: %d.%d.%d.%d\r\n",
110a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort,
111a88c31639bb24c73383a4528a5b77066e805148blpleahy              pConfig->StationAddress.Addr[0],
112a88c31639bb24c73383a4528a5b77066e805148blpleahy              pConfig->StationAddress.Addr[1],
113a88c31639bb24c73383a4528a5b77066e805148blpleahy              pConfig->StationAddress.Addr[2],
114a88c31639bb24c73383a4528a5b77066e805148blpleahy              pConfig->StationAddress.Addr[3]));
115a88c31639bb24c73383a4528a5b77066e805148blpleahy
116a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Set the subnet mask
117a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( pConfig->UseDefaultAddress ) {
118a88c31639bb24c73383a4528a5b77066e805148blpleahy      pConfig->SubnetMask.Addr[0] = 0;
119a88c31639bb24c73383a4528a5b77066e805148blpleahy      pConfig->SubnetMask.Addr[1] = 0;
120a88c31639bb24c73383a4528a5b77066e805148blpleahy      pConfig->SubnetMask.Addr[2] = 0;
121a88c31639bb24c73383a4528a5b77066e805148blpleahy      pConfig->SubnetMask.Addr[3] = 0;
122a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
123a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
124a88c31639bb24c73383a4528a5b77066e805148blpleahy      pConfig->SubnetMask.Addr[0] = 0xff;
1256e1450f3095c90cf7119a4dbc8e6710daf988444lpleahy      pConfig->SubnetMask.Addr[1] = ( 128 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;
1266e1450f3095c90cf7119a4dbc8e6710daf988444lpleahy      pConfig->SubnetMask.Addr[2] = ( 192 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;
1276e1450f3095c90cf7119a4dbc8e6710daf988444lpleahy      pConfig->SubnetMask.Addr[3] = ( 224 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;
128a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
129a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
130a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
131a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
132a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
133a88c31639bb24c73383a4528a5b77066e805148blpleahy}
134a88c31639bb24c73383a4528a5b77066e805148blpleahy
135a88c31639bb24c73383a4528a5b77066e805148blpleahy
136beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Get the option value.
137a88c31639bb24c73383a4528a5b77066e805148blpleahy
138a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine handles the IPv4 level options.
139a88c31639bb24c73383a4528a5b77066e805148blpleahy
140a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::EslSocketOptionGet routine calls this routine to retrieve
141a88c31639bb24c73383a4528a5b77066e805148blpleahy  the IPv4 options one at a time by name.
142a88c31639bb24c73383a4528a5b77066e805148blpleahy
143a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pSocket           Address of an ::ESL_SOCKET structure
144a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] OptionName        Name of the option
145a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [out] ppOptionData     Buffer to receive address of option value
146a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [out] pOptionLength    Buffer to receive the option length
147a88c31639bb24c73383a4528a5b77066e805148blpleahy
148a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - Socket data successfully received
149a88c31639bb24c73383a4528a5b77066e805148blpleahy **/
150a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
151a88c31639bb24c73383a4528a5b77066e805148blpleahyEslIp4OptionGet (
152a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_SOCKET * pSocket,
153a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN int OptionName,
154a88c31639bb24c73383a4528a5b77066e805148blpleahy  OUT CONST void ** __restrict ppOptionData,
155a88c31639bb24c73383a4528a5b77066e805148blpleahy  OUT socklen_t * __restrict pOptionLength
156a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
157a88c31639bb24c73383a4528a5b77066e805148blpleahy{
158a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
159a88c31639bb24c73383a4528a5b77066e805148blpleahy
160a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
161a88c31639bb24c73383a4528a5b77066e805148blpleahy
162a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Assume success
163a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket->errno = 0;
164a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
165a88c31639bb24c73383a4528a5b77066e805148blpleahy
166a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Attempt to get the option
167a88c31639bb24c73383a4528a5b77066e805148blpleahy  switch ( OptionName ) {
168a88c31639bb24c73383a4528a5b77066e805148blpleahy  default:
169a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Option not supported
170a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->errno = ENOPROTOOPT;
171a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = EFI_INVALID_PARAMETER;
172a88c31639bb24c73383a4528a5b77066e805148blpleahy    break;
173a88c31639bb24c73383a4528a5b77066e805148blpleahy
174a88c31639bb24c73383a4528a5b77066e805148blpleahy  case IP_HDRINCL:
17558081f2c64fbc2f89ac5a9b47b2643c280bc8f99lpleahy    *ppOptionData = (void *)&pSocket->bIncludeHeader;
176a88c31639bb24c73383a4528a5b77066e805148blpleahy    *pOptionLength = sizeof ( pSocket->bIncludeHeader );
177a88c31639bb24c73383a4528a5b77066e805148blpleahy    break;
178a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
179a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
180a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
181a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
182a88c31639bb24c73383a4528a5b77066e805148blpleahy}
183a88c31639bb24c73383a4528a5b77066e805148blpleahy
184a88c31639bb24c73383a4528a5b77066e805148blpleahy
185beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Set the option value.
186a88c31639bb24c73383a4528a5b77066e805148blpleahy
187a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine handles the IPv4 level options.
188a88c31639bb24c73383a4528a5b77066e805148blpleahy
189a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::EslSocketOptionSet routine calls this routine to adjust
190a88c31639bb24c73383a4528a5b77066e805148blpleahy  the IPv4 options one at a time by name.
191a88c31639bb24c73383a4528a5b77066e805148blpleahy
192a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pSocket         Address of an ::ESL_SOCKET structure
193a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] OptionName      Name of the option
194a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pOptionValue    Buffer containing the option value
195a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] OptionLength    Length of the buffer in bytes
196a88c31639bb24c73383a4528a5b77066e805148blpleahy
197a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - Option successfully set
198a88c31639bb24c73383a4528a5b77066e805148blpleahy **/
199a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
200a88c31639bb24c73383a4528a5b77066e805148blpleahyEslIp4OptionSet (
201a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_SOCKET * pSocket,
202a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN int OptionName,
203a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN CONST void * pOptionValue,
204a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN socklen_t OptionLength
205a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
206a88c31639bb24c73383a4528a5b77066e805148blpleahy{
207a88c31639bb24c73383a4528a5b77066e805148blpleahy  BOOLEAN bTrueFalse;
208beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  //socklen_t LengthInBytes;
209beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  //UINT8 * pOptionData;
210a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
211a88c31639bb24c73383a4528a5b77066e805148blpleahy
212a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
213a88c31639bb24c73383a4528a5b77066e805148blpleahy
214a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Assume success
215a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket->errno = 0;
216a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
217a88c31639bb24c73383a4528a5b77066e805148blpleahy
218a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Determine if the option protocol matches
219beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  //LengthInBytes = 0;
220beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  //pOptionData = NULL;
221a88c31639bb24c73383a4528a5b77066e805148blpleahy  switch ( OptionName ) {
222a88c31639bb24c73383a4528a5b77066e805148blpleahy  default:
223a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Protocol level not supported
224a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_INFO | DEBUG_OPTION, "ERROR - Invalid protocol option\r\n" ));
225a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->errno = ENOTSUP;
226a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = EFI_UNSUPPORTED;
227a88c31639bb24c73383a4528a5b77066e805148blpleahy    break;
228a88c31639bb24c73383a4528a5b77066e805148blpleahy
229a88c31639bb24c73383a4528a5b77066e805148blpleahy  case IP_HDRINCL:
230a88c31639bb24c73383a4528a5b77066e805148blpleahy
231a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Validate the option length
232a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( sizeof ( UINT32 ) == OptionLength ) {
233a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Restrict the input to TRUE or FALSE
234a88c31639bb24c73383a4528a5b77066e805148blpleahy      bTrueFalse = TRUE;
235a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( 0 == *(UINT32 *)pOptionValue ) {
236a88c31639bb24c73383a4528a5b77066e805148blpleahy        bTrueFalse = FALSE;
237a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
238a88c31639bb24c73383a4528a5b77066e805148blpleahy      pOptionValue = &bTrueFalse;
239a88c31639bb24c73383a4528a5b77066e805148blpleahy
240a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Set the option value
241beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin      //pOptionData = (UINT8 *)&pSocket->bIncludeHeader;
242beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin      //LengthInBytes = sizeof ( pSocket->bIncludeHeader );
243a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
244a88c31639bb24c73383a4528a5b77066e805148blpleahy    break;
245a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
246a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
247a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
248a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
249a88c31639bb24c73383a4528a5b77066e805148blpleahy}
250a88c31639bb24c73383a4528a5b77066e805148blpleahy
251a88c31639bb24c73383a4528a5b77066e805148blpleahy
252a88c31639bb24c73383a4528a5b77066e805148blpleahy/**
253a88c31639bb24c73383a4528a5b77066e805148blpleahy  Free a receive packet
254a88c31639bb24c73383a4528a5b77066e805148blpleahy
255a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine performs the network specific operations necessary
256a88c31639bb24c73383a4528a5b77066e805148blpleahy  to free a receive packet.
257a88c31639bb24c73383a4528a5b77066e805148blpleahy
258a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by ::EslSocketPortCloseTxDone to free a
259a88c31639bb24c73383a4528a5b77066e805148blpleahy  receive packet.
260a88c31639bb24c73383a4528a5b77066e805148blpleahy
261a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pPacket         Address of an ::ESL_PACKET structure.
262a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in, out] pRxBytes   Address of the count of RX bytes
263a88c31639bb24c73383a4528a5b77066e805148blpleahy
264a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
265a88c31639bb24c73383a4528a5b77066e805148blpleahyVOID
266a88c31639bb24c73383a4528a5b77066e805148blpleahyEslIp4PacketFree (
267a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PACKET * pPacket,
268a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN OUT size_t * pRxBytes
269a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
270a88c31639bb24c73383a4528a5b77066e805148blpleahy{
271a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_IP4_RECEIVE_DATA * pRxData;
272a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
273a88c31639bb24c73383a4528a5b77066e805148blpleahy
274a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
275a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Account for the receive bytes
276a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
277a88c31639bb24c73383a4528a5b77066e805148blpleahy  pRxData = pPacket->Op.Ip4Rx.pRxData;
278a88c31639bb24c73383a4528a5b77066e805148blpleahy  *pRxBytes -= pRxData->HeaderLength + pRxData->DataLength;
279a88c31639bb24c73383a4528a5b77066e805148blpleahy
280a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
281a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Disconnect the buffer from the packet
282a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
283a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPacket->Op.Ip4Rx.pRxData = NULL;
284a88c31639bb24c73383a4528a5b77066e805148blpleahy
285a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
286a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the buffer to the IP4 driver
287a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
288a88c31639bb24c73383a4528a5b77066e805148blpleahy  gBS->SignalEvent ( pRxData->RecycleSignal );
289a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT ( );
290a88c31639bb24c73383a4528a5b77066e805148blpleahy}
291a88c31639bb24c73383a4528a5b77066e805148blpleahy
292a88c31639bb24c73383a4528a5b77066e805148blpleahy
293a88c31639bb24c73383a4528a5b77066e805148blpleahy/**
294a88c31639bb24c73383a4528a5b77066e805148blpleahy  Initialize the network specific portions of an ::ESL_PORT structure.
295a88c31639bb24c73383a4528a5b77066e805148blpleahy
296a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine initializes the network specific portions of an
297a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::ESL_PORT structure for use by the socket.
298a88c31639bb24c73383a4528a5b77066e805148blpleahy
299a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support routine is called by ::EslSocketPortAllocate
300a88c31639bb24c73383a4528a5b77066e805148blpleahy  to connect the socket with the underlying network adapter
301a88c31639bb24c73383a4528a5b77066e805148blpleahy  running the IPv4 protocol.
302a88c31639bb24c73383a4528a5b77066e805148blpleahy
303a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pPort       Address of an ESL_PORT structure
304a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] DebugFlags  Flags for debug messages
305a88c31639bb24c73383a4528a5b77066e805148blpleahy
306a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - Socket successfully created
307a88c31639bb24c73383a4528a5b77066e805148blpleahy
308a88c31639bb24c73383a4528a5b77066e805148blpleahy **/
309a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
310a88c31639bb24c73383a4528a5b77066e805148blpleahyEslIp4PortAllocate (
311a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort,
312a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN UINTN DebugFlags
313a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
314a88c31639bb24c73383a4528a5b77066e805148blpleahy{
315a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_IP4_CONFIG_DATA * pConfig;
316a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
317a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
318a88c31639bb24c73383a4528a5b77066e805148blpleahy
319a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
320a88c31639bb24c73383a4528a5b77066e805148blpleahy
321a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
322a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Initialize the port
323a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
324a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = pPort->pSocket;
325a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Ip4Tx.TxData );
326a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Tx.Event );
327a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket->TxTokenOffset = OFFSET_OF ( EFI_IP4_COMPLETION_TOKEN, Packet.TxData );
328a88c31639bb24c73383a4528a5b77066e805148blpleahy
329a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
330a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Save the cancel, receive and transmit addresses
331a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
332a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.IPv4->Configure;
333a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Cancel;
3343bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.IPv4->Poll;
335a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Receive;
336a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Transmit;
337a88c31639bb24c73383a4528a5b77066e805148blpleahy
338a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
339a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Set the configuration flags
340a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
341a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfig = &pPort->Context.Ip4.ModeData.ConfigData;
342a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfig->AcceptIcmpErrors = FALSE;
343a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfig->AcceptBroadcast = FALSE;
344a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfig->AcceptPromiscuous = FALSE;
345a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfig->TypeOfService = 0;
346a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfig->TimeToLive = 255;
347a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfig->DoNotFragment = FALSE;
348a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfig->RawData = FALSE;
349a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfig->ReceiveTimeout = 0;
350a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfig->TransmitTimeout = 0;
351a88c31639bb24c73383a4528a5b77066e805148blpleahy
352a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
353a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Set the default protocol
354a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
355a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfig->DefaultProtocol = (UINT8)pSocket->Protocol;
356a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfig->AcceptAnyProtocol = (BOOLEAN)( 0 == pConfig->DefaultProtocol );
357a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
358a88c31639bb24c73383a4528a5b77066e805148blpleahy
359a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
360a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
361a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
362a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
363a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
364a88c31639bb24c73383a4528a5b77066e805148blpleahy}
365a88c31639bb24c73383a4528a5b77066e805148blpleahy
366a88c31639bb24c73383a4528a5b77066e805148blpleahy
367a88c31639bb24c73383a4528a5b77066e805148blpleahy/**
368a88c31639bb24c73383a4528a5b77066e805148blpleahy  Receive data from a network connection.
369a88c31639bb24c73383a4528a5b77066e805148blpleahy
370a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine attempts to return buffered data to the caller.  The
371a88c31639bb24c73383a4528a5b77066e805148blpleahy  data is removed from the urgent queue if the message flag MSG_OOB
372a88c31639bb24c73383a4528a5b77066e805148blpleahy  is specified, otherwise data is removed from the normal queue.
373a88c31639bb24c73383a4528a5b77066e805148blpleahy  See the \ref ReceiveEngine section.
374a88c31639bb24c73383a4528a5b77066e805148blpleahy
375a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by ::EslSocketReceive to handle the network
376a88c31639bb24c73383a4528a5b77066e805148blpleahy  specific receive operation to support SOCK_RAW sockets.
377a88c31639bb24c73383a4528a5b77066e805148blpleahy
378a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pPort           Address of an ::ESL_PORT structure.
379a88c31639bb24c73383a4528a5b77066e805148blpleahy
380a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pPacket         Address of an ::ESL_PACKET structure.
3810e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin
382a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
3830e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin
384a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] BufferLength    Length of the the buffer
3850e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin
386a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pBuffer         Address of a buffer to receive the data.
3870e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin
388a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pDataLength     Number of received data bytes in the buffer.
389a88c31639bb24c73383a4528a5b77066e805148blpleahy
390a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [out] pAddress       Network address to receive the remote system address
391a88c31639bb24c73383a4528a5b77066e805148blpleahy
392a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [out] pSkipBytes     Address to receive the number of bytes skipped
393a88c31639bb24c73383a4528a5b77066e805148blpleahy
394a88c31639bb24c73383a4528a5b77066e805148blpleahy  @return   Returns the address of the next free byte in the buffer.
395a88c31639bb24c73383a4528a5b77066e805148blpleahy
396a88c31639bb24c73383a4528a5b77066e805148blpleahy **/
397a88c31639bb24c73383a4528a5b77066e805148blpleahyUINT8 *
398a88c31639bb24c73383a4528a5b77066e805148blpleahyEslIp4Receive (
399a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort,
400a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PACKET * pPacket,
401a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN BOOLEAN * pbConsumePacket,
402a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN size_t BufferLength,
403a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN UINT8 * pBuffer,
404a88c31639bb24c73383a4528a5b77066e805148blpleahy  OUT size_t * pDataLength,
405a88c31639bb24c73383a4528a5b77066e805148blpleahy  OUT struct sockaddr * pAddress,
406a88c31639bb24c73383a4528a5b77066e805148blpleahy  OUT size_t * pSkipBytes
407a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
408a88c31639bb24c73383a4528a5b77066e805148blpleahy{
409a88c31639bb24c73383a4528a5b77066e805148blpleahy  size_t DataBytes;
410a88c31639bb24c73383a4528a5b77066e805148blpleahy  size_t HeaderBytes;
411a88c31639bb24c73383a4528a5b77066e805148blpleahy  size_t LengthInBytes;
412a88c31639bb24c73383a4528a5b77066e805148blpleahy  struct sockaddr_in * pRemoteAddress;
413a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_IP4_RECEIVE_DATA * pRxData;
414a88c31639bb24c73383a4528a5b77066e805148blpleahy
415a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
416a88c31639bb24c73383a4528a5b77066e805148blpleahy
417a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
418a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the remote system address if requested
419a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
420a88c31639bb24c73383a4528a5b77066e805148blpleahy  pRxData = pPacket->Op.Ip4Rx.pRxData;
421a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL != pAddress ) {
422a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
423a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Build the remote address
424a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
425a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_RX,
426a88c31639bb24c73383a4528a5b77066e805148blpleahy              "Getting packet remote address: %d.%d.%d.%d\r\n",
427a88c31639bb24c73383a4528a5b77066e805148blpleahy              pRxData->Header->SourceAddress.Addr[0],
428a88c31639bb24c73383a4528a5b77066e805148blpleahy              pRxData->Header->SourceAddress.Addr[1],
429a88c31639bb24c73383a4528a5b77066e805148blpleahy              pRxData->Header->SourceAddress.Addr[2],
430a88c31639bb24c73383a4528a5b77066e805148blpleahy              pRxData->Header->SourceAddress.Addr[3]));
431a88c31639bb24c73383a4528a5b77066e805148blpleahy    pRemoteAddress = (struct sockaddr_in *)pAddress;
432a88c31639bb24c73383a4528a5b77066e805148blpleahy    CopyMem ( &pRemoteAddress->sin_addr,
433a88c31639bb24c73383a4528a5b77066e805148blpleahy              &pRxData->Header->SourceAddress.Addr[0],
434a88c31639bb24c73383a4528a5b77066e805148blpleahy              sizeof ( pRemoteAddress->sin_addr ));
435a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
436a88c31639bb24c73383a4528a5b77066e805148blpleahy
437a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
438a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Copy the IP header
439a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
440a88c31639bb24c73383a4528a5b77066e805148blpleahy  HeaderBytes = pRxData->HeaderLength;
441a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( HeaderBytes > BufferLength ) {
442a88c31639bb24c73383a4528a5b77066e805148blpleahy    HeaderBytes = BufferLength;
443a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
444a88c31639bb24c73383a4528a5b77066e805148blpleahy  DEBUG (( DEBUG_RX,
445a88c31639bb24c73383a4528a5b77066e805148blpleahy            "0x%08x --> 0x%08x: Copy header 0x%08x bytes\r\n",
446a88c31639bb24c73383a4528a5b77066e805148blpleahy            pRxData->Header,
447a88c31639bb24c73383a4528a5b77066e805148blpleahy            pBuffer,
448a88c31639bb24c73383a4528a5b77066e805148blpleahy            HeaderBytes ));
449a88c31639bb24c73383a4528a5b77066e805148blpleahy  CopyMem ( pBuffer, pRxData->Header, HeaderBytes );
450a88c31639bb24c73383a4528a5b77066e805148blpleahy  pBuffer += HeaderBytes;
451a88c31639bb24c73383a4528a5b77066e805148blpleahy  LengthInBytes = HeaderBytes;
452a88c31639bb24c73383a4528a5b77066e805148blpleahy
453a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
454a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Copy the received data
455a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
456a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( 0 < ( BufferLength - LengthInBytes )) {
457a88c31639bb24c73383a4528a5b77066e805148blpleahy    pBuffer = EslSocketCopyFragmentedBuffer ( pRxData->FragmentCount,
458a88c31639bb24c73383a4528a5b77066e805148blpleahy                                              &pRxData->FragmentTable[0],
459a88c31639bb24c73383a4528a5b77066e805148blpleahy                                              BufferLength - LengthInBytes,
460a88c31639bb24c73383a4528a5b77066e805148blpleahy                                              pBuffer,
461a88c31639bb24c73383a4528a5b77066e805148blpleahy                                              &DataBytes );
462a88c31639bb24c73383a4528a5b77066e805148blpleahy    LengthInBytes += DataBytes;
463a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
464a88c31639bb24c73383a4528a5b77066e805148blpleahy
465a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
466a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Determine if the data is being read
467a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
468a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( *pbConsumePacket ) {
469a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
470a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Display for the bytes consumed
471a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
472a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_RX,
473a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Port account for 0x%08x bytes\r\n",
474a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort,
475a88c31639bb24c73383a4528a5b77066e805148blpleahy              LengthInBytes ));
476a88c31639bb24c73383a4528a5b77066e805148blpleahy
477a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
478a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Account for any discarded data
479a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
480a88c31639bb24c73383a4528a5b77066e805148blpleahy    *pSkipBytes = pRxData->HeaderLength + pRxData->DataLength - LengthInBytes;
481a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
482a88c31639bb24c73383a4528a5b77066e805148blpleahy
483a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
484a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the data length and the buffer address
485a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
486a88c31639bb24c73383a4528a5b77066e805148blpleahy  *pDataLength = LengthInBytes;
487a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_HEX ( pBuffer );
488a88c31639bb24c73383a4528a5b77066e805148blpleahy  return pBuffer;
489a88c31639bb24c73383a4528a5b77066e805148blpleahy}
490a88c31639bb24c73383a4528a5b77066e805148blpleahy
491a88c31639bb24c73383a4528a5b77066e805148blpleahy
492a88c31639bb24c73383a4528a5b77066e805148blpleahy/**
493a88c31639bb24c73383a4528a5b77066e805148blpleahy  Get the remote socket address
494a88c31639bb24c73383a4528a5b77066e805148blpleahy
495a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine returns the address of the remote connection point
496a88c31639bb24c73383a4528a5b77066e805148blpleahy  associated with the SOCK_RAW socket.
497a88c31639bb24c73383a4528a5b77066e805148blpleahy
498a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by ::EslSocketGetPeerAddress to detemine
499a88c31639bb24c73383a4528a5b77066e805148blpleahy  the IPv4 address associated with the network adapter.
500a88c31639bb24c73383a4528a5b77066e805148blpleahy
501a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pPort       Address of an ::ESL_PORT structure.
502a88c31639bb24c73383a4528a5b77066e805148blpleahy
503a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [out] pAddress   Network address to receive the remote system address
504a88c31639bb24c73383a4528a5b77066e805148blpleahy
505a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
506a88c31639bb24c73383a4528a5b77066e805148blpleahyVOID
507a88c31639bb24c73383a4528a5b77066e805148blpleahyEslIp4RemoteAddressGet (
508a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort,
509a88c31639bb24c73383a4528a5b77066e805148blpleahy  OUT struct sockaddr * pAddress
510a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
511a88c31639bb24c73383a4528a5b77066e805148blpleahy{
512a88c31639bb24c73383a4528a5b77066e805148blpleahy  struct sockaddr_in * pRemoteAddress;
513a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IP4_CONTEXT * pIp4;
514a88c31639bb24c73383a4528a5b77066e805148blpleahy
515a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
516a88c31639bb24c73383a4528a5b77066e805148blpleahy
517a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
518a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the remote address
519a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
520a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIp4 = &pPort->Context.Ip4;
521a88c31639bb24c73383a4528a5b77066e805148blpleahy  pRemoteAddress = (struct sockaddr_in *)pAddress;
522a88c31639bb24c73383a4528a5b77066e805148blpleahy  pRemoteAddress->sin_family = AF_INET;
523a88c31639bb24c73383a4528a5b77066e805148blpleahy  CopyMem ( &pRemoteAddress->sin_addr,
524a88c31639bb24c73383a4528a5b77066e805148blpleahy            &pIp4->DestinationAddress.Addr[0],
525a88c31639bb24c73383a4528a5b77066e805148blpleahy            sizeof ( pRemoteAddress->sin_addr ));
526a88c31639bb24c73383a4528a5b77066e805148blpleahy
527a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT ( );
528a88c31639bb24c73383a4528a5b77066e805148blpleahy}
529a88c31639bb24c73383a4528a5b77066e805148blpleahy
530a88c31639bb24c73383a4528a5b77066e805148blpleahy
531a88c31639bb24c73383a4528a5b77066e805148blpleahy/**
532a88c31639bb24c73383a4528a5b77066e805148blpleahy  Set the remote address
533a88c31639bb24c73383a4528a5b77066e805148blpleahy
534a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine sets the remote address in the port.
535a88c31639bb24c73383a4528a5b77066e805148blpleahy
536a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by ::EslSocketConnect to specify the
537a88c31639bb24c73383a4528a5b77066e805148blpleahy  remote network address.
538a88c31639bb24c73383a4528a5b77066e805148blpleahy
539a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pPort           Address of an ::ESL_PORT structure.
540a88c31639bb24c73383a4528a5b77066e805148blpleahy
541a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pSockAddr       Network address of the remote system.
542a88c31639bb24c73383a4528a5b77066e805148blpleahy
543a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] SockAddrLength  Length in bytes of the network address.
544a88c31639bb24c73383a4528a5b77066e805148blpleahy
545a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS     The operation was successful
546a88c31639bb24c73383a4528a5b77066e805148blpleahy
547a88c31639bb24c73383a4528a5b77066e805148blpleahy **/
548a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
549a88c31639bb24c73383a4528a5b77066e805148blpleahyEslIp4RemoteAddressSet (
550a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort,
551a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN CONST struct sockaddr * pSockAddr,
552a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN socklen_t SockAddrLength
553a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
554a88c31639bb24c73383a4528a5b77066e805148blpleahy{
555a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IP4_CONTEXT * pIp4;
556a88c31639bb24c73383a4528a5b77066e805148blpleahy  CONST struct sockaddr_in * pRemoteAddress;
557a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
558a88c31639bb24c73383a4528a5b77066e805148blpleahy
559a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
560a88c31639bb24c73383a4528a5b77066e805148blpleahy
561a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
562a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Set the remote address
563a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
564a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIp4 = &pPort->Context.Ip4;
565a88c31639bb24c73383a4528a5b77066e805148blpleahy  pRemoteAddress = (struct sockaddr_in *)pSockAddr;
566a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIp4->DestinationAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );
567a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIp4->DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
568a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIp4->DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );
569a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIp4->DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );
570f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy  pPort->pSocket->bAddressSet = TRUE;
571a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
572a88c31639bb24c73383a4528a5b77066e805148blpleahy
573a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
574a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
575a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
576a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
577a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
578a88c31639bb24c73383a4528a5b77066e805148blpleahy}
579a88c31639bb24c73383a4528a5b77066e805148blpleahy
580a88c31639bb24c73383a4528a5b77066e805148blpleahy
581a88c31639bb24c73383a4528a5b77066e805148blpleahy/**
582a88c31639bb24c73383a4528a5b77066e805148blpleahy  Process the receive completion
583a88c31639bb24c73383a4528a5b77066e805148blpleahy
584a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine keeps the IPv4 driver's buffer and queues it in
585a88c31639bb24c73383a4528a5b77066e805148blpleahy  in FIFO order to the data queue.  The IP4 driver's buffer will
586a88c31639bb24c73383a4528a5b77066e805148blpleahy  be returned by either ::EslIp4Receive or ::EslSocketPortCloseTxDone.
587a88c31639bb24c73383a4528a5b77066e805148blpleahy  See the \ref ReceiveEngine section.
588a88c31639bb24c73383a4528a5b77066e805148blpleahy
589a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by the IPv4 driver when data is
590a88c31639bb24c73383a4528a5b77066e805148blpleahy  received.
591a88c31639bb24c73383a4528a5b77066e805148blpleahy
592a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] Event     The receive completion event
593a88c31639bb24c73383a4528a5b77066e805148blpleahy
594a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pIo       The address of an ::ESL_IO_MGMT structure
595a88c31639bb24c73383a4528a5b77066e805148blpleahy
596a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
597a88c31639bb24c73383a4528a5b77066e805148blpleahyVOID
598a88c31639bb24c73383a4528a5b77066e805148blpleahyEslIp4RxComplete (
599a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN EFI_EVENT Event,
600a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_IO_MGMT * pIo
601a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
602a88c31639bb24c73383a4528a5b77066e805148blpleahy{
603a88c31639bb24c73383a4528a5b77066e805148blpleahy  size_t LengthInBytes;
604a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pPacket;
605a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_IP4_RECEIVE_DATA * pRxData;
606a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
6070e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin
608a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
6090e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin
610a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
611a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Get the operation status.
612a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
613a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = pIo->Token.Ip4Rx.Status;
614a88c31639bb24c73383a4528a5b77066e805148blpleahy
615a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
616a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Get the packet length
617a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
618a88c31639bb24c73383a4528a5b77066e805148blpleahy  pRxData = pIo->Token.Ip4Rx.Packet.RxData;
619a88c31639bb24c73383a4528a5b77066e805148blpleahy  LengthInBytes = pRxData->HeaderLength + pRxData->DataLength;
620a88c31639bb24c73383a4528a5b77066e805148blpleahy
6210e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin  //{{
622a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      +--------------------+   +----------------------+
623a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      | ESL_IO_MGMT        |   |      Data Buffer     |
624a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      |                    |   |     (Driver owned)   |
625a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      |    +---------------+   +----------------------+
626a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      |    | Token         |               ^
627a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      |    |      Rx Event |               |
628a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      |    |               |   +----------------------+
629a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      |    |        RxData --> | EFI_IP4_RECEIVE_DATA |
630a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      +----+---------------+   |    (Driver owned)    |
631a88c31639bb24c73383a4528a5b77066e805148blpleahy  //                               +----------------------+
632a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      +--------------------+               ^
633a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      | ESL_PACKET         |               .
634a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      |                    |               .
635a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      |    +---------------+               .
636a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      |    |       pRxData --> NULL  .......
637a88c31639bb24c73383a4528a5b77066e805148blpleahy  //      +----+---------------+
638a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
639a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
640a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Save the data in the packet
6410e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin  //}}
642a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPacket = pIo->pPacket;
643a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPacket->Op.Ip4Rx.pRxData = pRxData;
644a88c31639bb24c73383a4528a5b77066e805148blpleahy
645a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
646a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Complete this request
647a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
648a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslSocketRxComplete ( pIo, Status, LengthInBytes, FALSE );
649a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT ( );
650a88c31639bb24c73383a4528a5b77066e805148blpleahy}
651a88c31639bb24c73383a4528a5b77066e805148blpleahy
652a88c31639bb24c73383a4528a5b77066e805148blpleahy
653a88c31639bb24c73383a4528a5b77066e805148blpleahy/**
654a88c31639bb24c73383a4528a5b77066e805148blpleahy  Determine if the socket is configured.
655a88c31639bb24c73383a4528a5b77066e805148blpleahy
656a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine uses the flag ESL_SOCKET::bConfigured to determine
657a88c31639bb24c73383a4528a5b77066e805148blpleahy  if the network layer's configuration routine has been called.
658a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine calls the ::EslSocketBind and configuration routines
659a88c31639bb24c73383a4528a5b77066e805148blpleahy  if they were not already called.  After the port is configured,
660a88c31639bb24c73383a4528a5b77066e805148blpleahy  the \ref ReceiveEngine is started.
661a88c31639bb24c73383a4528a5b77066e805148blpleahy
662a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by EslSocketIsConfigured to verify
663a88c31639bb24c73383a4528a5b77066e805148blpleahy  that the socket is configured.
664a88c31639bb24c73383a4528a5b77066e805148blpleahy
665a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pSocket         Address of an ::ESL_SOCKET structure
6660e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin
667a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - The port is connected
668a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_NOT_STARTED - The port is not connected
669a88c31639bb24c73383a4528a5b77066e805148blpleahy
670a88c31639bb24c73383a4528a5b77066e805148blpleahy **/
671a88c31639bb24c73383a4528a5b77066e805148blpleahy EFI_STATUS
672a88c31639bb24c73383a4528a5b77066e805148blpleahy EslIp4SocketIsConfigured (
673a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_SOCKET * pSocket
674a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
675a88c31639bb24c73383a4528a5b77066e805148blpleahy{
676a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINTN Index;
677a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
678a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pNextPort;
679a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IP4_CONTEXT * pIp4;
680a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_IP4_PROTOCOL * pIp4Protocol;
681a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
682a88c31639bb24c73383a4528a5b77066e805148blpleahy  struct sockaddr_in LocalAddress;
683a88c31639bb24c73383a4528a5b77066e805148blpleahy
684a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
685a88c31639bb24c73383a4528a5b77066e805148blpleahy
686a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
687a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Assume success
688a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
689a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
690a88c31639bb24c73383a4528a5b77066e805148blpleahy
691a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
692a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Configure the port if necessary
693a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
694a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( !pSocket->bConfigured ) {
695a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
696a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Fill in the port list if necessary
697a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
698bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy    pSocket->errno = ENETDOWN;
699a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( NULL == pSocket->pPortList ) {
700a88c31639bb24c73383a4528a5b77066e805148blpleahy      LocalAddress.sin_len = sizeof ( LocalAddress );
701a88c31639bb24c73383a4528a5b77066e805148blpleahy      LocalAddress.sin_family = AF_INET;
702a88c31639bb24c73383a4528a5b77066e805148blpleahy      LocalAddress.sin_addr.s_addr = 0;
703a88c31639bb24c73383a4528a5b77066e805148blpleahy      LocalAddress.sin_port = 0;
704a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EslSocketBind ( &pSocket->SocketProtocol,
705a88c31639bb24c73383a4528a5b77066e805148blpleahy                               (struct sockaddr *)&LocalAddress,
706a88c31639bb24c73383a4528a5b77066e805148blpleahy                               LocalAddress.sin_len,
707a88c31639bb24c73383a4528a5b77066e805148blpleahy                               &pSocket->errno );
708a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
709a88c31639bb24c73383a4528a5b77066e805148blpleahy
710a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
711a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Walk the port list
712a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
713a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort = pSocket->pPortList;
714a88c31639bb24c73383a4528a5b77066e805148blpleahy    while ( NULL != pPort ) {
715a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
716a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Update the raw setting
717a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
718a88c31639bb24c73383a4528a5b77066e805148blpleahy      pIp4 = &pPort->Context.Ip4;
719a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( pSocket->bIncludeHeader ) {
720a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
721a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  IP header will be included with the data on transmit
722a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
723a88c31639bb24c73383a4528a5b77066e805148blpleahy        pIp4->ModeData.ConfigData.RawData = TRUE;
724a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
725a88c31639bb24c73383a4528a5b77066e805148blpleahy
726a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
727a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Attempt to configure the port
728a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
729a88c31639bb24c73383a4528a5b77066e805148blpleahy      pNextPort = pPort->pLinkSocket;
730a88c31639bb24c73383a4528a5b77066e805148blpleahy      pIp4Protocol = pPort->pProtocol.IPv4;
731a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_TX,
732a88c31639bb24c73383a4528a5b77066e805148blpleahy                "0x%08x: pPort Configuring for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
733a88c31639bb24c73383a4528a5b77066e805148blpleahy                          pPort,
734a88c31639bb24c73383a4528a5b77066e805148blpleahy                          pIp4->ModeData.ConfigData.StationAddress.Addr[0],
735a88c31639bb24c73383a4528a5b77066e805148blpleahy                          pIp4->ModeData.ConfigData.StationAddress.Addr[1],
736a88c31639bb24c73383a4528a5b77066e805148blpleahy                          pIp4->ModeData.ConfigData.StationAddress.Addr[2],
737a88c31639bb24c73383a4528a5b77066e805148blpleahy                          pIp4->ModeData.ConfigData.StationAddress.Addr[3],
738a88c31639bb24c73383a4528a5b77066e805148blpleahy                          pIp4->DestinationAddress.Addr[0],
739a88c31639bb24c73383a4528a5b77066e805148blpleahy                          pIp4->DestinationAddress.Addr[1],
740a88c31639bb24c73383a4528a5b77066e805148blpleahy                          pIp4->DestinationAddress.Addr[2],
741a88c31639bb24c73383a4528a5b77066e805148blpleahy                          pIp4->DestinationAddress.Addr[3]));
742a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = pIp4Protocol->Configure ( pIp4Protocol,
743a88c31639bb24c73383a4528a5b77066e805148blpleahy                                          &pIp4->ModeData.ConfigData );
744a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( !EFI_ERROR ( Status )) {
745a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
746a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Update the configuration data
747a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
748a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = pIp4Protocol->GetModeData ( pIp4Protocol,
749a88c31639bb24c73383a4528a5b77066e805148blpleahy                                             &pIp4->ModeData,
750a88c31639bb24c73383a4528a5b77066e805148blpleahy                                             NULL,
751a88c31639bb24c73383a4528a5b77066e805148blpleahy                                             NULL );
752a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
753a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( EFI_ERROR ( Status )) {
754bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy        if ( !pSocket->bConfigured ) {
755bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy          DEBUG (( DEBUG_LISTEN,
756bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy                    "ERROR - Failed to configure the Ip4 port, Status: %r\r\n",
757bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy                    Status ));
758bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy          switch ( Status ) {
759bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy          case EFI_ACCESS_DENIED:
760bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy            pSocket->errno = EACCES;
761bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy            break;
762bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy
763bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy          default:
764bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy          case EFI_DEVICE_ERROR:
765bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy            pSocket->errno = EIO;
766bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy            break;
767bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy
768bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy          case EFI_INVALID_PARAMETER:
769bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy            pSocket->errno = EADDRNOTAVAIL;
770bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy            break;
771bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy
772bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy          case EFI_NO_MAPPING:
773bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy            pSocket->errno = EAFNOSUPPORT;
774bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy            break;
775bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy
776bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy          case EFI_OUT_OF_RESOURCES:
777bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy            pSocket->errno = ENOBUFS;
778bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy            break;
779bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy
780bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy          case EFI_UNSUPPORTED:
781bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy            pSocket->errno = EOPNOTSUPP;
782bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy            break;
783bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy          }
784a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
785a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
786a88c31639bb24c73383a4528a5b77066e805148blpleahy      else {
787a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_TX,
788a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "0x%08x: pPort Configured for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
789a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pPort,
790a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->ModeData.ConfigData.StationAddress.Addr[0],
791a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->ModeData.ConfigData.StationAddress.Addr[1],
792a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->ModeData.ConfigData.StationAddress.Addr[2],
793a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->ModeData.ConfigData.StationAddress.Addr[3],
794a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->DestinationAddress.Addr[0],
795a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->DestinationAddress.Addr[1],
796a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->DestinationAddress.Addr[2],
797a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->DestinationAddress.Addr[3]));
798a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_TX,
799a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "Subnet Mask: %d.%d.%d.%d\r\n",
800a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->ModeData.ConfigData.SubnetMask.Addr[0],
801a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->ModeData.ConfigData.SubnetMask.Addr[1],
802a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->ModeData.ConfigData.SubnetMask.Addr[2],
803a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->ModeData.ConfigData.SubnetMask.Addr[3]));
804a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_TX,
805a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "Route Count: %d\r\n",
806a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pIp4->ModeData.RouteCount ));
807a88c31639bb24c73383a4528a5b77066e805148blpleahy        for ( Index = 0; pIp4->ModeData.RouteCount > Index; Index++ ) {
808a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( 0 == Index ) {
809a88c31639bb24c73383a4528a5b77066e805148blpleahy            DEBUG (( DEBUG_TX, "Route Table:\r\n" ));
810a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
811a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_TX,
812a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "%5d: %d.%d.%d.%d, %d.%d.%d.%d ==> %d.%d.%d.%d\r\n",
813a88c31639bb24c73383a4528a5b77066e805148blpleahy                    Index,
814a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[0],
815a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[1],
816a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[2],
817a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[3],
818a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[0],
819a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[1],
820a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[2],
821a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[3],
822a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[0],
823a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[1],
824a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[2],
825a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[3]));
826a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
827a88c31639bb24c73383a4528a5b77066e805148blpleahy        pPort->bConfigured = TRUE;
828bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy        pSocket->bConfigured = TRUE;
829a88c31639bb24c73383a4528a5b77066e805148blpleahy
830a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
831a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Start the first read on the port
832a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
833a88c31639bb24c73383a4528a5b77066e805148blpleahy        EslSocketRxStart ( pPort );
834a88c31639bb24c73383a4528a5b77066e805148blpleahy
835a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
836a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  The socket is connected
837a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
838a88c31639bb24c73383a4528a5b77066e805148blpleahy        pSocket->State = SOCKET_STATE_CONNECTED;
839bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy        pSocket->errno = 0;
840a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
841a88c31639bb24c73383a4528a5b77066e805148blpleahy
842a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
843a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Set the next port
844a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
845a88c31639bb24c73383a4528a5b77066e805148blpleahy      pPort = pNextPort;
846a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
847a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
848a88c31639bb24c73383a4528a5b77066e805148blpleahy
849a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
850a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Determine the socket configuration status
851a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
852bb3aa953b3c724ae575881283d4b6e18bfad5433lpleahy  Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED;
8530e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin
854a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
855a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the port connected state.
856a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
857a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
858a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
859a88c31639bb24c73383a4528a5b77066e805148blpleahy}
860a88c31639bb24c73383a4528a5b77066e805148blpleahy
861a88c31639bb24c73383a4528a5b77066e805148blpleahy
862a88c31639bb24c73383a4528a5b77066e805148blpleahy/**
863a88c31639bb24c73383a4528a5b77066e805148blpleahy  Buffer data for transmission over a network connection.
864a88c31639bb24c73383a4528a5b77066e805148blpleahy
865a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine buffers data for the transmit engine in the normal
866a88c31639bb24c73383a4528a5b77066e805148blpleahy  data queue.  When the \ref TransmitEngine has resources, this
867a88c31639bb24c73383a4528a5b77066e805148blpleahy  routine will start the transmission of the next buffer on the
868a88c31639bb24c73383a4528a5b77066e805148blpleahy  network connection.
869a88c31639bb24c73383a4528a5b77066e805148blpleahy
870a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by ::EslSocketTransmit to buffer
871a88c31639bb24c73383a4528a5b77066e805148blpleahy  data for transmission.  The data is copied into a local buffer
872a88c31639bb24c73383a4528a5b77066e805148blpleahy  freeing the application buffer for reuse upon return.  When
873a88c31639bb24c73383a4528a5b77066e805148blpleahy  necessary, this routine starts the transmit engine that
874a88c31639bb24c73383a4528a5b77066e805148blpleahy  performs the data transmission on the network connection.  The
875a88c31639bb24c73383a4528a5b77066e805148blpleahy  transmit engine transmits the data a packet at a time over the
876a88c31639bb24c73383a4528a5b77066e805148blpleahy  network connection.
877a88c31639bb24c73383a4528a5b77066e805148blpleahy
878a88c31639bb24c73383a4528a5b77066e805148blpleahy  Transmission errors are returned during the next transmission or
879a88c31639bb24c73383a4528a5b77066e805148blpleahy  during the close operation.  Only buffering errors are returned
880a88c31639bb24c73383a4528a5b77066e805148blpleahy  during the current transmission attempt.
881a88c31639bb24c73383a4528a5b77066e805148blpleahy
882a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pSocket         Address of an ::ESL_SOCKET structure
883a88c31639bb24c73383a4528a5b77066e805148blpleahy
884a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] Flags           Message control flags
885a88c31639bb24c73383a4528a5b77066e805148blpleahy
886a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] BufferLength    Length of the the buffer
887a88c31639bb24c73383a4528a5b77066e805148blpleahy
888a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pBuffer         Address of a buffer to receive the data.
889a88c31639bb24c73383a4528a5b77066e805148blpleahy
890a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pDataLength     Number of received data bytes in the buffer.
891a88c31639bb24c73383a4528a5b77066e805148blpleahy
892a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pAddress        Network address of the remote system address
893a88c31639bb24c73383a4528a5b77066e805148blpleahy
894a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] AddressLength   Length of the remote network address structure
895a88c31639bb24c73383a4528a5b77066e805148blpleahy
896a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - Socket data successfully buffered
897a88c31639bb24c73383a4528a5b77066e805148blpleahy
898a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
899a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
900a88c31639bb24c73383a4528a5b77066e805148blpleahyEslIp4TxBuffer (
901a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_SOCKET * pSocket,
902a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN int Flags,
903a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN size_t BufferLength,
904a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN CONST UINT8 * pBuffer,
905a88c31639bb24c73383a4528a5b77066e805148blpleahy  OUT size_t * pDataLength,
906a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN const struct sockaddr * pAddress,
907a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN socklen_t AddressLength
908a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
909a88c31639bb24c73383a4528a5b77066e805148blpleahy{
910a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pPacket;
911a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pPreviousPacket;
912a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
913a88c31639bb24c73383a4528a5b77066e805148blpleahy  const struct sockaddr_in * pRemoteAddress;
914a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IP4_CONTEXT * pIp4;
915a88c31639bb24c73383a4528a5b77066e805148blpleahy  size_t * pTxBytes;
916a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IP4_TX_DATA * pTxData;
917a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
918a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_TPL TplPrevious;
919a88c31639bb24c73383a4528a5b77066e805148blpleahy
920a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
921a88c31639bb24c73383a4528a5b77066e805148blpleahy
922a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
923a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Assume failure
924a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
925a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_UNSUPPORTED;
926a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket->errno = ENOTCONN;
927a88c31639bb24c73383a4528a5b77066e805148blpleahy  *pDataLength = 0;
928a88c31639bb24c73383a4528a5b77066e805148blpleahy
929a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
930a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Verify that the socket is connected
931a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
932a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
933a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
934884ed923564f35084c45a8f3f132c076b26f2423lpleahy    //  Verify that there is enough room to buffer another
935884ed923564f35084c45a8f3f132c076b26f2423lpleahy    //  transmit operation
936a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
937884ed923564f35084c45a8f3f132c076b26f2423lpleahy    pTxBytes = &pSocket->TxBytes;
938884ed923564f35084c45a8f3f132c076b26f2423lpleahy    if ( pSocket->MaxTxBuf > *pTxBytes ) {
939a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
940884ed923564f35084c45a8f3f132c076b26f2423lpleahy      //  Locate the port
941a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
942884ed923564f35084c45a8f3f132c076b26f2423lpleahy      pPort = pSocket->pPortList;
943884ed923564f35084c45a8f3f132c076b26f2423lpleahy      while ( NULL != pPort ) {
944884ed923564f35084c45a8f3f132c076b26f2423lpleahy        //
945884ed923564f35084c45a8f3f132c076b26f2423lpleahy        //  Determine the queue head
946884ed923564f35084c45a8f3f132c076b26f2423lpleahy        //
947884ed923564f35084c45a8f3f132c076b26f2423lpleahy        pIp4 = &pPort->Context.Ip4;
948a88c31639bb24c73383a4528a5b77066e805148blpleahy
949a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
950a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Attempt to allocate the packet
951a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
952a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = EslSocketPacketAllocate ( &pPacket,
953a88c31639bb24c73383a4528a5b77066e805148blpleahy                                           sizeof ( pPacket->Op.Ip4Tx )
954a88c31639bb24c73383a4528a5b77066e805148blpleahy                                           - sizeof ( pPacket->Op.Ip4Tx.Buffer )
955a88c31639bb24c73383a4528a5b77066e805148blpleahy                                           + BufferLength,
956a88c31639bb24c73383a4528a5b77066e805148blpleahy                                           0,
957a88c31639bb24c73383a4528a5b77066e805148blpleahy                                           DEBUG_TX );
958a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( !EFI_ERROR ( Status )) {
959a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
960a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Initialize the transmit operation
961a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
962a88c31639bb24c73383a4528a5b77066e805148blpleahy          pTxData = &pPacket->Op.Ip4Tx;
963a88c31639bb24c73383a4528a5b77066e805148blpleahy          pTxData->TxData.DestinationAddress.Addr[0] = pIp4->DestinationAddress.Addr[0];
964a88c31639bb24c73383a4528a5b77066e805148blpleahy          pTxData->TxData.DestinationAddress.Addr[1] = pIp4->DestinationAddress.Addr[1];
965a88c31639bb24c73383a4528a5b77066e805148blpleahy          pTxData->TxData.DestinationAddress.Addr[2] = pIp4->DestinationAddress.Addr[2];
966a88c31639bb24c73383a4528a5b77066e805148blpleahy          pTxData->TxData.DestinationAddress.Addr[3] = pIp4->DestinationAddress.Addr[3];
967a88c31639bb24c73383a4528a5b77066e805148blpleahy          pTxData->TxData.OverrideData = NULL;
968a88c31639bb24c73383a4528a5b77066e805148blpleahy          pTxData->TxData.OptionsLength = 0;
969a88c31639bb24c73383a4528a5b77066e805148blpleahy          pTxData->TxData.OptionsBuffer = NULL;
970a88c31639bb24c73383a4528a5b77066e805148blpleahy          pTxData->TxData.TotalDataLength = (UINT32) BufferLength;
971a88c31639bb24c73383a4528a5b77066e805148blpleahy          pTxData->TxData.FragmentCount = 1;
972a88c31639bb24c73383a4528a5b77066e805148blpleahy          pTxData->TxData.FragmentTable[0].FragmentLength = (UINT32) BufferLength;
973a88c31639bb24c73383a4528a5b77066e805148blpleahy          pTxData->TxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Ip4Tx.Buffer[0];
974a88c31639bb24c73383a4528a5b77066e805148blpleahy
975a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
976a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Set the remote system address if necessary
977a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
978a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( NULL != pAddress ) {
979a88c31639bb24c73383a4528a5b77066e805148blpleahy            pRemoteAddress = (const struct sockaddr_in *)pAddress;
980a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->Override.SourceAddress.Addr[0] = pIp4->ModeData.ConfigData.StationAddress.Addr[0];
981a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->Override.SourceAddress.Addr[1] = pIp4->ModeData.ConfigData.StationAddress.Addr[1];
982a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->Override.SourceAddress.Addr[2] = pIp4->ModeData.ConfigData.StationAddress.Addr[2];
983a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->Override.SourceAddress.Addr[3] = pIp4->ModeData.ConfigData.StationAddress.Addr[3];
984a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->TxData.DestinationAddress.Addr[0] = (UINT8)pRemoteAddress->sin_addr.s_addr;
985a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->TxData.DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
986a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->TxData.DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );
987a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->TxData.DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );
988a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->Override.GatewayAddress.Addr[0] = 0;
989a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->Override.GatewayAddress.Addr[1] = 0;
990a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->Override.GatewayAddress.Addr[2] = 0;
991a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->Override.GatewayAddress.Addr[3] = 0;
992a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->Override.Protocol = (UINT8)pSocket->Protocol;
993a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->Override.TypeOfService = 0;
994a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->Override.TimeToLive = 255;
995a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->Override.DoNotFragment = FALSE;
996a88c31639bb24c73383a4528a5b77066e805148blpleahy
997a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
998a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Use the remote system address when sending this packet
999a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
1000a88c31639bb24c73383a4528a5b77066e805148blpleahy            pTxData->TxData.OverrideData = &pTxData->Override;
1001a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
1002a88c31639bb24c73383a4528a5b77066e805148blpleahy
1003a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
1004a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Copy the data into the buffer
1005a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
1006a88c31639bb24c73383a4528a5b77066e805148blpleahy          CopyMem ( &pPacket->Op.Ip4Tx.Buffer[0],
1007a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pBuffer,
1008a88c31639bb24c73383a4528a5b77066e805148blpleahy                    BufferLength );
1009a88c31639bb24c73383a4528a5b77066e805148blpleahy
1010a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
1011a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Synchronize with the socket layer
1012a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
1013a88c31639bb24c73383a4528a5b77066e805148blpleahy          RAISE_TPL ( TplPrevious, TPL_SOCKETS );
1014a88c31639bb24c73383a4528a5b77066e805148blpleahy
1015a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
10162dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          //  Display the request
1017a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
10182dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          DEBUG (( DEBUG_TX,
10192dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
10202dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    BufferLength,
10212dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    pBuffer,
10222dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    pIp4->ModeData.ConfigData.StationAddress.Addr[0],
10232dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    pIp4->ModeData.ConfigData.StationAddress.Addr[1],
10242dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    pIp4->ModeData.ConfigData.StationAddress.Addr[2],
10252dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    pIp4->ModeData.ConfigData.StationAddress.Addr[3],
10262dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    pTxData->TxData.DestinationAddress.Addr[0],
10272dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    pTxData->TxData.DestinationAddress.Addr[1],
10282dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    pTxData->TxData.DestinationAddress.Addr[2],
10292dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    pTxData->TxData.DestinationAddress.Addr[3]));
1030a88c31639bb24c73383a4528a5b77066e805148blpleahy
10312dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          //
10322dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          //  Queue the data for transmission
10332dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          //
10342dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          pPacket->pNext = NULL;
10352dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          pPreviousPacket = pSocket->pTxPacketListTail;
10362dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          if ( NULL == pPreviousPacket ) {
10372dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy            pSocket->pTxPacketListHead = pPacket;
1038a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
1039a88c31639bb24c73383a4528a5b77066e805148blpleahy          else {
10402dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy            pPreviousPacket->pNext = pPacket;
10412dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          }
10422dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          pSocket->pTxPacketListTail = pPacket;
10432dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          DEBUG (( DEBUG_TX,
10442dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    "0x%08x: Packet on transmit list\r\n",
10452dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                    pPacket ));
10462dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
10472dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          //
10482dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          //  Account for the buffered data
10492dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          //
10502dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          *pTxBytes += BufferLength;
10512dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          *pDataLength = BufferLength;
10522dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
10532dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          //
10542dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          //  Start the transmit engine if it is idle
10552dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          //
10562dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy          if ( NULL != pPort->pTxFree ) {
10572dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy            EslSocketTxStart ( pPort,
10582dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                               &pSocket->pTxPacketListHead,
10592dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                               &pSocket->pTxPacketListTail,
10602dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                               &pPort->pTxActive,
10612dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                               &pPort->pTxFree );
1062a88c31639bb24c73383a4528a5b77066e805148blpleahy
1063a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
10642dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy            //  Ignore any transmit error
1065a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
10662dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy            if ( EFI_ERROR ( pSocket->TxError )) {
10672dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy              DEBUG (( DEBUG_TX,
10682dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                       "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",
10692dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                       pPort,
10702dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                       pPacket,
10712dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                       pSocket->TxError ));
10722dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy            }
10732dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy            pSocket->TxError = EFI_SUCCESS;
1074a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
1075a88c31639bb24c73383a4528a5b77066e805148blpleahy
1076a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
1077a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Release the socket layer synchronization
1078a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
1079a88c31639bb24c73383a4528a5b77066e805148blpleahy          RESTORE_TPL ( TplPrevious );
1080a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
1081a88c31639bb24c73383a4528a5b77066e805148blpleahy        else {
1082a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
1083a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Packet allocation failed
1084a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
1085a88c31639bb24c73383a4528a5b77066e805148blpleahy          pSocket->errno = ENOMEM;
1086884ed923564f35084c45a8f3f132c076b26f2423lpleahy          break;
1087a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
1088884ed923564f35084c45a8f3f132c076b26f2423lpleahy
1089a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
1090884ed923564f35084c45a8f3f132c076b26f2423lpleahy        //  Set the next port
1091a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
1092884ed923564f35084c45a8f3f132c076b26f2423lpleahy        pPort = pPort->pLinkSocket;
1093a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
1094a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
1095884ed923564f35084c45a8f3f132c076b26f2423lpleahy    else {
1096884ed923564f35084c45a8f3f132c076b26f2423lpleahy      //
1097884ed923564f35084c45a8f3f132c076b26f2423lpleahy      //  Not enough buffer space available
1098884ed923564f35084c45a8f3f132c076b26f2423lpleahy      //
1099884ed923564f35084c45a8f3f132c076b26f2423lpleahy      pSocket->errno = EAGAIN;
1100884ed923564f35084c45a8f3f132c076b26f2423lpleahy      Status = EFI_NOT_READY;
1101884ed923564f35084c45a8f3f132c076b26f2423lpleahy    }
1102a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
1103a88c31639bb24c73383a4528a5b77066e805148blpleahy
1104a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1105a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
1106a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1107a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
1108a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
1109a88c31639bb24c73383a4528a5b77066e805148blpleahy}
1110a88c31639bb24c73383a4528a5b77066e805148blpleahy
1111a88c31639bb24c73383a4528a5b77066e805148blpleahy
1112a88c31639bb24c73383a4528a5b77066e805148blpleahy/**
1113a88c31639bb24c73383a4528a5b77066e805148blpleahy  Process the transmit completion
1114a88c31639bb24c73383a4528a5b77066e805148blpleahy
1115a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine use ::EslSocketTxComplete to perform the transmit
1116a88c31639bb24c73383a4528a5b77066e805148blpleahy  completion processing for data packets.
1117a88c31639bb24c73383a4528a5b77066e805148blpleahy
1118a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by the IPv4 network layer when a data
1119a88c31639bb24c73383a4528a5b77066e805148blpleahy  transmit request completes.
1120a88c31639bb24c73383a4528a5b77066e805148blpleahy
1121a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] Event     The normal transmit completion event
1122a88c31639bb24c73383a4528a5b77066e805148blpleahy
1123a88c31639bb24c73383a4528a5b77066e805148blpleahy  @param [in] pIo       The address of an ::ESL_IO_MGMT structure
1124a88c31639bb24c73383a4528a5b77066e805148blpleahy
1125a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
1126a88c31639bb24c73383a4528a5b77066e805148blpleahyVOID
1127a88c31639bb24c73383a4528a5b77066e805148blpleahyEslIp4TxComplete (
1128a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN EFI_EVENT Event,
1129a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_IO_MGMT * pIo
1130a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
1131a88c31639bb24c73383a4528a5b77066e805148blpleahy{
1132a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINT32 LengthInBytes;
1133a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
1134a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pPacket;
1135a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
1136a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
11370e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin
1138a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
11390e565888ee40264bfad5a700e0d62f4824d81c18Olivier Martin
1140a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1141a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Locate the active transmit packet
1142a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1143a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPacket = pIo->pPacket;
1144a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPort = pIo->pPort;
1145a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = pPort->pSocket;
1146a88c31639bb24c73383a4528a5b77066e805148blpleahy
1147a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1148a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Get the transmit length and status
1149a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1150a88c31639bb24c73383a4528a5b77066e805148blpleahy  LengthInBytes = pPacket->Op.Ip4Tx.TxData.TotalDataLength;
1151a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket->TxBytes -= LengthInBytes;
1152a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = pIo->Token.Ip4Tx.Status;
1153a88c31639bb24c73383a4528a5b77066e805148blpleahy
1154a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
11552dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //  Ignore the transmit error
11562dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //
11572dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  if ( EFI_ERROR ( Status )) {
11582dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    DEBUG (( DEBUG_TX,
11592dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy             "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",
11602dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy             pPort,
11612dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy             pPacket,
11622dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy             Status ));
11632dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    Status = EFI_SUCCESS;
11642dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  }
11652dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
11662dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //
1167a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Complete the transmit operation
1168a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1169a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslSocketTxComplete ( pIo,
1170a88c31639bb24c73383a4528a5b77066e805148blpleahy                        LengthInBytes,
1171a88c31639bb24c73383a4528a5b77066e805148blpleahy                        Status,
1172a88c31639bb24c73383a4528a5b77066e805148blpleahy                        "Raw ",
1173a88c31639bb24c73383a4528a5b77066e805148blpleahy                        &pSocket->pTxPacketListHead,
1174a88c31639bb24c73383a4528a5b77066e805148blpleahy                        &pSocket->pTxPacketListTail,
1175a88c31639bb24c73383a4528a5b77066e805148blpleahy                        &pPort->pTxActive,
1176a88c31639bb24c73383a4528a5b77066e805148blpleahy                        &pPort->pTxFree );
1177a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT ( );
1178a88c31639bb24c73383a4528a5b77066e805148blpleahy}
1179a88c31639bb24c73383a4528a5b77066e805148blpleahy
1180a88c31639bb24c73383a4528a5b77066e805148blpleahy
1181a88c31639bb24c73383a4528a5b77066e805148blpleahy/**
11822dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  Verify the adapter's IP address
11832dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
11842dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  This support routine is called by EslSocketBindTest.
11852dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
11862dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  @param [in] pPort       Address of an ::ESL_PORT structure.
11872dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  @param [in] pConfigData Address of the configuration data
11882dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
11892dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  @retval EFI_SUCCESS - The IP address is valid
11902dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  @retval EFI_NOT_STARTED - The IP address is invalid
11912dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
11922dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy **/
11932dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee LeahyEFI_STATUS
11942dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee LeahyEslIp4VerifyLocalIpAddress (
11952dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  IN ESL_PORT * pPort,
11962dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  IN EFI_IP4_CONFIG_DATA * pConfigData
11972dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  )
11982dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy{
11992dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  UINTN DataSize;
1200c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu  EFI_IP4_CONFIG2_INTERFACE_INFO * pIfInfo;
1201c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu  EFI_IP4_CONFIG2_PROTOCOL * pIpConfig2Protocol;
12022dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  ESL_SERVICE * pService;
12032dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  EFI_STATUS Status;
12042dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
12052dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  DBG_ENTER ( );
12062dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
12072dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //
12082dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //  Use break instead of goto
12092dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //
1210c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu  pIfInfo = NULL;
12112dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  for ( ; ; ) {
12122dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
12132dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //  Determine if the IP address is specified
12142dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
12152dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    DEBUG (( DEBUG_BIND,
12162dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy              "UseDefaultAddress: %s\r\n",
12172dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy              pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" ));
12182dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    DEBUG (( DEBUG_BIND,
12192dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy              "Requested IP address: %d.%d.%d.%d\r\n",
12202dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy              pConfigData->StationAddress.Addr [ 0 ],
12212dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy              pConfigData->StationAddress.Addr [ 1 ],
12222dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy              pConfigData->StationAddress.Addr [ 2 ],
12232dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy              pConfigData->StationAddress.Addr [ 3 ]));
12242dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    if ( pConfigData->UseDefaultAddress
12252dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      || (( 0 == pConfigData->StationAddress.Addr [ 0 ])
12262dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      && ( 0 == pConfigData->StationAddress.Addr [ 1 ])
12272dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      && ( 0 == pConfigData->StationAddress.Addr [ 2 ])
12282dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      && ( 0 == pConfigData->StationAddress.Addr [ 3 ])))
12292dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    {
12302dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      Status = EFI_SUCCESS;
12312dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      break;
12322dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    }
12332dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
12342dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
12352dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //  Open the configuration protocol
12362dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
12372dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    pService = pPort->pService;
1238c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu    Status = gBS->OpenProtocol (
1239c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                    pService->Controller,
1240c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                    &gEfiIp4Config2ProtocolGuid,
1241c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                    (VOID **)&pIpConfig2Protocol,
1242c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                    NULL,
1243c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                    NULL,
1244c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
1245c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                    );
12462dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    if ( EFI_ERROR ( Status )) {
12472dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      DEBUG (( DEBUG_ERROR,
12482dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                "ERROR - IP Configuration Protocol not available, Status: %r\r\n",
12492dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                Status ));
12502dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      break;
12512dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    }
12522dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
12532dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
1254c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu    // Get the interface information size.
12552dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
12562dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    DataSize = 0;
1257c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu    Status = pIpConfig2Protocol->GetData (
1258c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                                   pIpConfig2Protocol,
1259c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                                   Ip4Config2DataTypeInterfaceInfo,
1260c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                                   &DataSize,
1261c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                                   NULL
1262c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                                   );
12632dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    if ( EFI_BUFFER_TOO_SMALL != Status ) {
12642dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      DEBUG (( DEBUG_ERROR,
1265c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                "ERROR - Failed to get the interface information size, Status: %r\r\n",
12662dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                Status ));
12672dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      break;
12682dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    }
12692dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
12702dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
1271c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu    //  Allocate the interface information buffer
12722dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
1273c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu    pIfInfo = AllocatePool ( DataSize );
1274c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu    if ( NULL == pIfInfo ) {
12752dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      DEBUG (( DEBUG_ERROR,
1276c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                "ERROR - Not enough memory to allocate the interface information buffer!\r\n" ));
12772dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      Status = EFI_OUT_OF_RESOURCES;
12782dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      break;
12792dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    }
12802dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
12812dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
1282c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu    // Get the interface info.
12832dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
1284c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu    Status = pIpConfig2Protocol->GetData (
1285c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                                  pIpConfig2Protocol,
1286c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                                  Ip4Config2DataTypeInterfaceInfo,
1287c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                                  &DataSize,
1288c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                                  pIfInfo
1289c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                                  );
12902dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    if ( EFI_ERROR ( Status )) {
12912dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      DEBUG (( DEBUG_ERROR,
1292c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu                "ERROR - Failed to return the interface info, Status: %r\r\n",
12932dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                Status ));
12942dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      break;
12952dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    }
12962dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
12972dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
12982dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //  Display the current configuration
12992dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
13002dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    DEBUG (( DEBUG_BIND,
13012dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy              "Actual adapter IP address: %d.%d.%d.%d\r\n",
1302c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu              pIfInfo->StationAddress.Addr [ 0 ],
1303c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu              pIfInfo->StationAddress.Addr [ 1 ],
1304c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu              pIfInfo->StationAddress.Addr [ 2 ],
1305c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu              pIfInfo->StationAddress.Addr [ 3 ]));
13062dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
13072dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
13082dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //  Assume the port is not configured
13092dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
13102dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    Status = EFI_SUCCESS;
1311c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu    if (( pConfigData->StationAddress.Addr [ 0 ] == pIfInfo->StationAddress.Addr [ 0 ])
1312c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu      && ( pConfigData->StationAddress.Addr [ 1 ] == pIfInfo->StationAddress.Addr [ 1 ])
1313c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu      && ( pConfigData->StationAddress.Addr [ 2 ] == pIfInfo->StationAddress.Addr [ 2 ])
1314c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu      && ( pConfigData->StationAddress.Addr [ 3 ] == pIfInfo->StationAddress.Addr [ 3 ])) {
13152dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      break;
13162dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    }
13172dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
13182dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
13192dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //  The IP address did not match
13202dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //
13212dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    Status = EFI_NOT_STARTED;
13222dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    break;
13232dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  }
13242dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
13252dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //
13262dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //  Free the buffer if necessary
13272dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //
1328c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu  if ( NULL != pIfInfo ) {
1329c581e5037dca6e1446972aed194f13c9cdd0b01bjiaxinwu    FreePool ( pIfInfo );
13302dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  }
13312dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
13322dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //
13332dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //  Return the IP address status
13342dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //
13352dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  DBG_EXIT_STATUS ( Status );
13362dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  return Status;
13372dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy}
13382dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
13392dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
13402dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy/**
1341a88c31639bb24c73383a4528a5b77066e805148blpleahy  Interface between the socket layer and the network specific
1342a88c31639bb24c73383a4528a5b77066e805148blpleahy  code that supports SOCK_RAW sockets over IPv4.
1343a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
1344a88c31639bb24c73383a4528a5b77066e805148blpleahyCONST ESL_PROTOCOL_API cEslIp4Api = {
1345a88c31639bb24c73383a4528a5b77066e805148blpleahy  "IPv4",
1346a88c31639bb24c73383a4528a5b77066e805148blpleahy    IPPROTO_IP,
1347a88c31639bb24c73383a4528a5b77066e805148blpleahy  OFFSET_OF ( ESL_PORT, Context.Ip4.ModeData.ConfigData ),
1348a88c31639bb24c73383a4528a5b77066e805148blpleahy  OFFSET_OF ( ESL_LAYER, pIp4List ),
1349a88c31639bb24c73383a4528a5b77066e805148blpleahy  OFFSET_OF ( struct sockaddr_in, sin_zero ),
1350a88c31639bb24c73383a4528a5b77066e805148blpleahy  sizeof ( struct sockaddr_in ),
1351a88c31639bb24c73383a4528a5b77066e805148blpleahy  AF_INET,
1352a88c31639bb24c73383a4528a5b77066e805148blpleahy  sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),
1353a88c31639bb24c73383a4528a5b77066e805148blpleahy  sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),
1354a88c31639bb24c73383a4528a5b77066e805148blpleahy  OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Rx.Packet.RxData ),
1355a88c31639bb24c73383a4528a5b77066e805148blpleahy  FALSE,
1356a88c31639bb24c73383a4528a5b77066e805148blpleahy  EADDRNOTAVAIL,
1357a88c31639bb24c73383a4528a5b77066e805148blpleahy  NULL,   //  Accept
1358a88c31639bb24c73383a4528a5b77066e805148blpleahy  NULL,   //  ConnectPoll
1359a88c31639bb24c73383a4528a5b77066e805148blpleahy  NULL,   //  ConnectStart
1360a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4SocketIsConfigured,
1361a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4LocalAddressGet,
1362a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4LocalAddressSet,
1363a88c31639bb24c73383a4528a5b77066e805148blpleahy  NULL,   //  Listen
1364a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4OptionGet,
1365a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4OptionSet,
1366a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4PacketFree,
1367a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4PortAllocate,
1368a88c31639bb24c73383a4528a5b77066e805148blpleahy  NULL,   //  PortClose
1369a88c31639bb24c73383a4528a5b77066e805148blpleahy  NULL,   //  PortCloseOp
1370a88c31639bb24c73383a4528a5b77066e805148blpleahy  TRUE,
1371a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4Receive,
1372a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4RemoteAddressGet,
1373a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4RemoteAddressSet,
1374a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4RxComplete,
1375a88c31639bb24c73383a4528a5b77066e805148blpleahy  NULL,   //  RxStart
1376a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4TxBuffer,
1377a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslIp4TxComplete,
13782dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  NULL,   //  TxOobComplete
1379a93b0f45492e1d72352cbee73b6cc3819128d9d4Lee Leahy  (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslIp4VerifyLocalIpAddress
1380a88c31639bb24c73383a4528a5b77066e805148blpleahy};
1381