1d7ce700605e1af0e455e31ec11f19ff21d26b525darylm/** @file
2d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Implement the socket support for the socket layer.
3d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Socket States:
5d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  * Bound - pSocket->PortList is not NULL
6d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  * Listen - AcceptWait event is not NULL
7d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
80164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
90164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  This program and the accompanying materials are licensed and made available under
100164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  the terms and conditions of the BSD License that accompanies this distribution.
110164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  The full text of the license may be found at
12d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  http://opensource.org/licenses/bsd-license.php
13d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
14d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
17a88c31639bb24c73383a4528a5b77066e805148blpleahy
18a88c31639bb24c73383a4528a5b77066e805148blpleahy  \section DataStructures Data Structures
19a88c31639bb24c73383a4528a5b77066e805148blpleahy
20a88c31639bb24c73383a4528a5b77066e805148blpleahy  <code><pre>
21a88c31639bb24c73383a4528a5b77066e805148blpleahy
220164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel                +---------------+   +-------------+   +-------------+
23a88c31639bb24c73383a4528a5b77066e805148blpleahy  Service Lists | ::ESL_SERVICE |-->| ESL_SERVICE |-->| ESL_SERVICE |--> NULL (pNext)
240164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel                +---------------+   +-------------+   +-------------+
25a88c31639bb24c73383a4528a5b77066e805148blpleahy                  ^                       | (pPortList)    |
26a88c31639bb24c73383a4528a5b77066e805148blpleahy    pUdp4List ^   | pTcp4List             |                |
27a88c31639bb24c73383a4528a5b77066e805148blpleahy              |   |                       |                |
28a88c31639bb24c73383a4528a5b77066e805148blpleahy          ^   |   |                       |                |
29a88c31639bb24c73383a4528a5b77066e805148blpleahy pIp4List |   |   |                       |                |
30a88c31639bb24c73383a4528a5b77066e805148blpleahy        +---------------+                 |                |
310164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel        | ::ESL_LAYER   | ::mEslLayer     |                |
32a88c31639bb24c73383a4528a5b77066e805148blpleahy        +---------------+                 |                |
33a88c31639bb24c73383a4528a5b77066e805148blpleahy                  | (pSocketList)         |                |
34a88c31639bb24c73383a4528a5b77066e805148blpleahy    Socket List   V                       V                V
350164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel                +---------------+   +-------------+   +-------------+
360164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel                | ::ESL_SOCKET  |-->| ::ESL_PORT  |-->|   ESL_PORT  |--> NULL (pLinkSocket)
370164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel                +---------------+   +-------------+   +-------------+
38a88c31639bb24c73383a4528a5b77066e805148blpleahy                  |                       |                |
39a88c31639bb24c73383a4528a5b77066e805148blpleahy                  |                       |                V
40a88c31639bb24c73383a4528a5b77066e805148blpleahy                  V                       V               NULL
410164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel                +-------------+   +-------------+
42a88c31639bb24c73383a4528a5b77066e805148blpleahy                | ESL_SOCKET  |-->|   ESL_PORT  |--> NULL
43a88c31639bb24c73383a4528a5b77066e805148blpleahy                +-------------+   +-------------+
44a88c31639bb24c73383a4528a5b77066e805148blpleahy                  |    | | | |            |
45a88c31639bb24c73383a4528a5b77066e805148blpleahy                  V    | | | |            V
46a88c31639bb24c73383a4528a5b77066e805148blpleahy                 NULL  | | | |           NULL
47a88c31639bb24c73383a4528a5b77066e805148blpleahy               (pNext) | | | |     (pLinkService)
48a88c31639bb24c73383a4528a5b77066e805148blpleahy                       | | | |                                     pRxPacketListHead
49a88c31639bb24c73383a4528a5b77066e805148blpleahy                       | | | `-----------------------------------------------.
50a88c31639bb24c73383a4528a5b77066e805148blpleahy                       | | |                     pRxOobPacketListHead        |
51a88c31639bb24c73383a4528a5b77066e805148blpleahy                       | | `--------------------------------.                |
52a88c31639bb24c73383a4528a5b77066e805148blpleahy                       | |      pTxPacketListHead           |                |
53a88c31639bb24c73383a4528a5b77066e805148blpleahy                       | `---------------.                  |                |
54a88c31639bb24c73383a4528a5b77066e805148blpleahy  pTxOobPacketListHead |                 |                  |                |
55a88c31639bb24c73383a4528a5b77066e805148blpleahy                       V                 V                  V                V
560164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel                  +--------------+    +------------+    +------------+    +------------+
57a88c31639bb24c73383a4528a5b77066e805148blpleahy                  | ::ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |
580164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel                  +--------------+    +------------+    +------------+    +------------+
59a88c31639bb24c73383a4528a5b77066e805148blpleahy                         |                 |                |                |
60a88c31639bb24c73383a4528a5b77066e805148blpleahy                         V                 V                V                V
61a88c31639bb24c73383a4528a5b77066e805148blpleahy                  +------------+    +------------+    +------------+    +------------+
62a88c31639bb24c73383a4528a5b77066e805148blpleahy                  | ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |
63a88c31639bb24c73383a4528a5b77066e805148blpleahy                  +------------+    +------------+    +------------+    +------------+
64a88c31639bb24c73383a4528a5b77066e805148blpleahy                         |                 |                |                |
65a88c31639bb24c73383a4528a5b77066e805148blpleahy                         V                 V                V                V
66a88c31639bb24c73383a4528a5b77066e805148blpleahy                        NULL              NULL             NULL             NULL
67a88c31639bb24c73383a4528a5b77066e805148blpleahy                       (pNext)
68a88c31639bb24c73383a4528a5b77066e805148blpleahy
69a88c31639bb24c73383a4528a5b77066e805148blpleahy  </pre></code>
70a88c31639bb24c73383a4528a5b77066e805148blpleahy
71a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::mEslLayer is the one and only ::ESL_LAYER structure.  It connects directly or
72a88c31639bb24c73383a4528a5b77066e805148blpleahy  indirectly to the other data structures.  The ESL_LAYER structure has a unique
73a88c31639bb24c73383a4528a5b77066e805148blpleahy  service list for each of the network protocol interfaces.
74a88c31639bb24c73383a4528a5b77066e805148blpleahy
75a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::ESL_SERVICE manages the network interfaces for a given transport type (IP4, TCP4, UDP4, etc.)
76a88c31639bb24c73383a4528a5b77066e805148blpleahy
77a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::ESL_SOCKET manages the activity for a single socket instance.  As such, it contains
78a88c31639bb24c73383a4528a5b77066e805148blpleahy  the ::EFI_SOCKET_PROTOCOL structure which the BSD socket library uses as the object
79a88c31639bb24c73383a4528a5b77066e805148blpleahy  reference and the API into the EFI socket library.
80a88c31639bb24c73383a4528a5b77066e805148blpleahy
81a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::ESL_PORT manages the connection with a single instance of the lower layer network.
82a88c31639bb24c73383a4528a5b77066e805148blpleahy  This structure is the socket equivalent of an IP connection or a TCP or UDP port.
83a88c31639bb24c73383a4528a5b77066e805148blpleahy
84a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::ESL_PACKET buffers data for transmit and receive.  There are four queues connected
85a88c31639bb24c73383a4528a5b77066e805148blpleahy  to the ::ESL_SOCKET that manage the data:
86a88c31639bb24c73383a4528a5b77066e805148blpleahy  <ul>
87a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>ESL_SOCKET::pRxPacketListHead - Normal (low) priority receive data</li>
88a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>ESL_SOCKET::pRxOobPacketListHead - High (out-of-band or urgent) priority receive data</li>
89a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>ESL_SOCKET::pTxPacketListHead - Normal (low) priority transmit data</li>
90a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>ESL_SOCKET::pTxOobPacketListHead - High (out-of-band or urgent) priority transmit data</li>
91a88c31639bb24c73383a4528a5b77066e805148blpleahy  </ul>
92a88c31639bb24c73383a4528a5b77066e805148blpleahy  The selection of the transmit queue is controlled by the MSG_OOB flag on the transmit
93a88c31639bb24c73383a4528a5b77066e805148blpleahy  request as well as the socket option SO_OOBINLINE.  The receive queue is selected by
94a88c31639bb24c73383a4528a5b77066e805148blpleahy  the URGENT data flag for TCP and the setting of the socket option SO_OOBINLINE.
95a88c31639bb24c73383a4528a5b77066e805148blpleahy
96a88c31639bb24c73383a4528a5b77066e805148blpleahy  Data structure synchronization is done by raising TPL to TPL_SOCKET.  Modifying
97a88c31639bb24c73383a4528a5b77066e805148blpleahy  critical elements within the data structures must be done at this TPL.  TPL is then
98a88c31639bb24c73383a4528a5b77066e805148blpleahy  restored to the previous level.  Note that the code verifies that all callbacks are
99a88c31639bb24c73383a4528a5b77066e805148blpleahy  entering at TPL_SOCKETS for proper data structure synchronization.
100a88c31639bb24c73383a4528a5b77066e805148blpleahy
101a88c31639bb24c73383a4528a5b77066e805148blpleahy  \section PortCloseStateMachine Port Close State Machine
102a88c31639bb24c73383a4528a5b77066e805148blpleahy
103a88c31639bb24c73383a4528a5b77066e805148blpleahy  The port close state machine walks the port through the necessary
104a88c31639bb24c73383a4528a5b77066e805148blpleahy  states to stop activity on the port and get it into a state where
105a88c31639bb24c73383a4528a5b77066e805148blpleahy  the resources may be released.  The state machine consists of the
106a88c31639bb24c73383a4528a5b77066e805148blpleahy  following arcs and states:
107a88c31639bb24c73383a4528a5b77066e805148blpleahy
108a88c31639bb24c73383a4528a5b77066e805148blpleahy  <code><pre>
109a88c31639bb24c73383a4528a5b77066e805148blpleahy
110a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------------+
111a88c31639bb24c73383a4528a5b77066e805148blpleahy      |          Open            |
112a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------------+
113a88c31639bb24c73383a4528a5b77066e805148blpleahy                   |
114a88c31639bb24c73383a4528a5b77066e805148blpleahy                   |  ::EslSocketPortCloseStart
115a88c31639bb24c73383a4528a5b77066e805148blpleahy                   V
116a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------------+
117a88c31639bb24c73383a4528a5b77066e805148blpleahy      | PORT_STATE_CLOSE_STARTED |
118a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------------+
119a88c31639bb24c73383a4528a5b77066e805148blpleahy                   |
120a88c31639bb24c73383a4528a5b77066e805148blpleahy                   |  ::EslSocketPortCloseTxDone
121a88c31639bb24c73383a4528a5b77066e805148blpleahy                   V
122a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------------+
123a88c31639bb24c73383a4528a5b77066e805148blpleahy      | PORT_STATE_CLOSE_TX_DONE |
124a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------------+
125a88c31639bb24c73383a4528a5b77066e805148blpleahy                   |
126a88c31639bb24c73383a4528a5b77066e805148blpleahy                   |  ::EslSocketPortCloseComplete
127a88c31639bb24c73383a4528a5b77066e805148blpleahy                   V
128a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------------+
129a88c31639bb24c73383a4528a5b77066e805148blpleahy      |  PORT_STATE_CLOSE_DONE   |
130a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------------+
131a88c31639bb24c73383a4528a5b77066e805148blpleahy                   |
132a88c31639bb24c73383a4528a5b77066e805148blpleahy                   |  ::EslSocketPortCloseRxDone
133a88c31639bb24c73383a4528a5b77066e805148blpleahy                   V
134a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------------+
135a88c31639bb24c73383a4528a5b77066e805148blpleahy      | PORT_STATE_CLOSE_RX_DONE |
136a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------------+
137a88c31639bb24c73383a4528a5b77066e805148blpleahy                   |
138a88c31639bb24c73383a4528a5b77066e805148blpleahy                   |  ::EslSocketPortClose
139a88c31639bb24c73383a4528a5b77066e805148blpleahy                   V
140a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------------+
141a88c31639bb24c73383a4528a5b77066e805148blpleahy      |          Closed          |
142a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------------+
143a88c31639bb24c73383a4528a5b77066e805148blpleahy
144a88c31639bb24c73383a4528a5b77066e805148blpleahy  </pre></code>
145a88c31639bb24c73383a4528a5b77066e805148blpleahy
146a88c31639bb24c73383a4528a5b77066e805148blpleahy  <ul>
147a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>Arc: ::EslSocketPortCloseStart - Marks the port as closing and
148a88c31639bb24c73383a4528a5b77066e805148blpleahy      initiates the port close operation</li>
149a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>State: PORT_STATE_CLOSE_STARTED</li>
150a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>Arc: ::EslSocketPortCloseTxDone - Waits until all of the transmit
151a88c31639bb24c73383a4528a5b77066e805148blpleahy      operations to complete.  After all of the transmits are complete,
152a88c31639bb24c73383a4528a5b77066e805148blpleahy      this routine initiates the network specific close operation by calling
153a88c31639bb24c73383a4528a5b77066e805148blpleahy      through ESL_PROTOCOL_API::pfnPortCloseOp.  One such routine is
154a88c31639bb24c73383a4528a5b77066e805148blpleahy      ::EslTcp4PortCloseOp.
155a88c31639bb24c73383a4528a5b77066e805148blpleahy    </li>
156a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>State: PORT_STATE_CLOSE_TX_DONE</li>
1570164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel    <li>Arc: ::EslSocketPortCloseComplete - Called when the close operation is
158a88c31639bb24c73383a4528a5b77066e805148blpleahy      complete.  After the transition to PORT_STATE_CLOSE_DONE,
159a88c31639bb24c73383a4528a5b77066e805148blpleahy      this routine calls ::EslSocketRxCancel to abort the pending receive operations.
160a88c31639bb24c73383a4528a5b77066e805148blpleahy    </li>
161a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>State: PORT_STATE_CLOSE_DONE</li>
162a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>Arc: ::EslSocketPortCloseRxDone - Waits until all of the receive
163a88c31639bb24c73383a4528a5b77066e805148blpleahy      operation have been cancelled.  After the transition to
164a88c31639bb24c73383a4528a5b77066e805148blpleahy      PORT_STATE_CLOSE_RX_DONE, this routine calls ::EslSocketPortClose.
165a88c31639bb24c73383a4528a5b77066e805148blpleahy    </li>
166a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>State: PORT_STATE_CLOSE_RX_DONE</li>
167a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>Arc: ::EslSocketPortClose - This routine discards any receive buffers
168a88c31639bb24c73383a4528a5b77066e805148blpleahy      using a network specific support routine via ESL_PROTOCOL_API::pfnPacketFree.
169a88c31639bb24c73383a4528a5b77066e805148blpleahy      This routine then releases the port resources allocated by ::EslSocketPortAllocate
170a88c31639bb24c73383a4528a5b77066e805148blpleahy      and calls the network specific port close routine (e.g. ::EslTcp4PortClose)
171a88c31639bb24c73383a4528a5b77066e805148blpleahy      via ESL_PROTOCOL_API::pfnPortClose to release any network specific resources.
172a88c31639bb24c73383a4528a5b77066e805148blpleahy    </li>
173a88c31639bb24c73383a4528a5b77066e805148blpleahy  </ul>
174a88c31639bb24c73383a4528a5b77066e805148blpleahy
175a88c31639bb24c73383a4528a5b77066e805148blpleahy
176a88c31639bb24c73383a4528a5b77066e805148blpleahy  \section ReceiveEngine Receive Engine
177a88c31639bb24c73383a4528a5b77066e805148blpleahy
178a88c31639bb24c73383a4528a5b77066e805148blpleahy  The receive path accepts data from the network and queues (buffers) it for the
179a88c31639bb24c73383a4528a5b77066e805148blpleahy  application.  Flow control is applied once a maximum amount of buffering is reached
180a88c31639bb24c73383a4528a5b77066e805148blpleahy  and is released when the buffer usage drops below that limit.  Eventually the
181a88c31639bb24c73383a4528a5b77066e805148blpleahy  application requests data from the socket which removes entries from the queue and
182a88c31639bb24c73383a4528a5b77066e805148blpleahy  returns the data.
183a88c31639bb24c73383a4528a5b77066e805148blpleahy
184a88c31639bb24c73383a4528a5b77066e805148blpleahy  The receive engine is the state machine which reads data from the network and
185a88c31639bb24c73383a4528a5b77066e805148blpleahy  fills the queue with received packets.  The receive engine uses two data structures
186a88c31639bb24c73383a4528a5b77066e805148blpleahy  to manage the network receive opeations and the buffers.
187a88c31639bb24c73383a4528a5b77066e805148blpleahy
188a88c31639bb24c73383a4528a5b77066e805148blpleahy  At a high level, the ::ESL_IO_MGMT structures are managing the tokens and
189a88c31639bb24c73383a4528a5b77066e805148blpleahy  events for the interface to the UEFI network stack.  The ::ESL_PACKET
190a88c31639bb24c73383a4528a5b77066e805148blpleahy  structures are managing the receive data buffers.  The receive engine
191a88c31639bb24c73383a4528a5b77066e805148blpleahy  connects these two structures in the network specific receive completion
192a88c31639bb24c73383a4528a5b77066e805148blpleahy  routines.
193a88c31639bb24c73383a4528a5b77066e805148blpleahy
194a88c31639bb24c73383a4528a5b77066e805148blpleahy<code><pre>
195a88c31639bb24c73383a4528a5b77066e805148blpleahy
196a88c31639bb24c73383a4528a5b77066e805148blpleahy      +------------------+
197a88c31639bb24c73383a4528a5b77066e805148blpleahy      |     ::ESL_PORT     |
198a88c31639bb24c73383a4528a5b77066e805148blpleahy      |                  |
199a88c31639bb24c73383a4528a5b77066e805148blpleahy      +------------------+
200a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    ::ESL_IO_MGMT   |
201a88c31639bb24c73383a4528a5b77066e805148blpleahy      +------------------+
202a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    ESL_IO_MGMT   |
203a88c31639bb24c73383a4528a5b77066e805148blpleahy      +------------------+
204a88c31639bb24c73383a4528a5b77066e805148blpleahy      .                  .
205a88c31639bb24c73383a4528a5b77066e805148blpleahy      .    ESL_IO_MGMT   .
206a88c31639bb24c73383a4528a5b77066e805148blpleahy      .                  .
207a88c31639bb24c73383a4528a5b77066e805148blpleahy      +------------------+
208a88c31639bb24c73383a4528a5b77066e805148blpleahy
209a88c31639bb24c73383a4528a5b77066e805148blpleahy</pre></code>
210a88c31639bb24c73383a4528a5b77066e805148blpleahy
211a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::ESL_IO_MGMT structures are allocated as part of the ::ESL_PORT structure in
212a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::EslSocketPortAllocate.  The ESL_IO_MGMT structures are separated and placed on
213a88c31639bb24c73383a4528a5b77066e805148blpleahy  the free list by calling ::EslSocketIoInit.  The ESL_IO_MGMT structure contains
214a88c31639bb24c73383a4528a5b77066e805148blpleahy  the network layer specific receive completion token and event.  The receive engine
215a88c31639bb24c73383a4528a5b77066e805148blpleahy  is eventually shutdown by ::EslSocketPortCloseTxDone and the resources in these
216a88c31639bb24c73383a4528a5b77066e805148blpleahy  structures are released in ::EslSocketPortClose by a call to ::EslSocketIoFree.
217a88c31639bb24c73383a4528a5b77066e805148blpleahy
218a88c31639bb24c73383a4528a5b77066e805148blpleahy<code><pre>
219a88c31639bb24c73383a4528a5b77066e805148blpleahy
220a88c31639bb24c73383a4528a5b77066e805148blpleahy         pPort->pRxActive
221a88c31639bb24c73383a4528a5b77066e805148blpleahy                |
222a88c31639bb24c73383a4528a5b77066e805148blpleahy                V
2230164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel          +-------------+   +-------------+   +-------------+
224a88c31639bb24c73383a4528a5b77066e805148blpleahy  Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL
2250164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel          +-------------+   +-------------+   +-------------+
226a88c31639bb24c73383a4528a5b77066e805148blpleahy
2270164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel          +-------------+   +-------------+   +-------------+
228a88c31639bb24c73383a4528a5b77066e805148blpleahy  Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL
2290164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel          +-------------+   +-------------+   +-------------+
230a88c31639bb24c73383a4528a5b77066e805148blpleahy                ^
231a88c31639bb24c73383a4528a5b77066e805148blpleahy                |
232a88c31639bb24c73383a4528a5b77066e805148blpleahy          pPort->pRxFree
233a88c31639bb24c73383a4528a5b77066e805148blpleahy</pre></code>
234a88c31639bb24c73383a4528a5b77066e805148blpleahy
235a88c31639bb24c73383a4528a5b77066e805148blpleahy  The receive engine is started by calling ::EslSocketRxStart.  Flow control pauses
236a88c31639bb24c73383a4528a5b77066e805148blpleahy  the receive engine by stopping the calls to EslSocketRxStart when the amount of
237a88c31639bb24c73383a4528a5b77066e805148blpleahy  receive data waiting for the application meets or exceeds MAX_RX_DATA.  After
238a88c31639bb24c73383a4528a5b77066e805148blpleahy  the application reads enough data that the amount of buffering drops below this
239a88c31639bb24c73383a4528a5b77066e805148blpleahy  limit, the calls to EslSockeRxStart continue which releases the flow control.
240a88c31639bb24c73383a4528a5b77066e805148blpleahy
241a88c31639bb24c73383a4528a5b77066e805148blpleahy  Receive flow control is applied when the port is created, since no receive
242a88c31639bb24c73383a4528a5b77066e805148blpleahy  operation are pending to the low layer network driver.  The flow control gets
243a88c31639bb24c73383a4528a5b77066e805148blpleahy  released when the low layer network port is configured or the first receive
244a88c31639bb24c73383a4528a5b77066e805148blpleahy  operation is posted.  Flow control remains in the released state until the
245a88c31639bb24c73383a4528a5b77066e805148blpleahy  maximum buffer space is consumed.  During this time, ::EslSocketRxComplete
246a88c31639bb24c73383a4528a5b77066e805148blpleahy  calls ::EslSocketRxStart.  Flow control is applied in EslSocketRxComplete
247a88c31639bb24c73383a4528a5b77066e805148blpleahy  by skipping the call to EslSocketRxStart.  Flow control is eventually
248a88c31639bb24c73383a4528a5b77066e805148blpleahy  released in ::EslSocketReceive when the buffer space drops below the
249a88c31639bb24c73383a4528a5b77066e805148blpleahy  maximum amount causing EslSocketReceive to call EslSocketRxStart.
250a88c31639bb24c73383a4528a5b77066e805148blpleahy
251a88c31639bb24c73383a4528a5b77066e805148blpleahy<code><pre>
252a88c31639bb24c73383a4528a5b77066e805148blpleahy
2530164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel                    +------------+   +------------+
254a88c31639bb24c73383a4528a5b77066e805148blpleahy    High     .----->| ESL_PACKET |-->| ESL_PACKET |--> NULL (pNext)
255a88c31639bb24c73383a4528a5b77066e805148blpleahy  Priority   |      +------------+   +------------+
256a88c31639bb24c73383a4528a5b77066e805148blpleahy             |
257a88c31639bb24c73383a4528a5b77066e805148blpleahy             | pRxOobPacketListHead
258a88c31639bb24c73383a4528a5b77066e805148blpleahy       +------------+
259a88c31639bb24c73383a4528a5b77066e805148blpleahy       | ::ESL_SOCKET |
260a88c31639bb24c73383a4528a5b77066e805148blpleahy       +------------+
261a88c31639bb24c73383a4528a5b77066e805148blpleahy             | pRxPacketListHead
262a88c31639bb24c73383a4528a5b77066e805148blpleahy    Low      |
2630164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  Priority   |      +------------+   +------------+   +------------+
264a88c31639bb24c73383a4528a5b77066e805148blpleahy             `----->| ::ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL
2650164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel                    +------------+   +------------+   +------------+
266a88c31639bb24c73383a4528a5b77066e805148blpleahy
267a88c31639bb24c73383a4528a5b77066e805148blpleahy</pre></code>
268a88c31639bb24c73383a4528a5b77066e805148blpleahy
269a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::EslSocketRxStart connects an ::ESL_PACKET structure to the ::ESL_IO_MGMT structure
2700164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  and then calls the network layer to start the receive operation.  Upon
271a88c31639bb24c73383a4528a5b77066e805148blpleahy  receive completion, ::EslSocketRxComplete breaks the connection between these
272a88c31639bb24c73383a4528a5b77066e805148blpleahy  structrues and places the ESL_IO_MGMT structure onto the ESL_PORT::pRxFree list to
273a88c31639bb24c73383a4528a5b77066e805148blpleahy  make token and event available for another receive operation.  EslSocketRxComplete
274a88c31639bb24c73383a4528a5b77066e805148blpleahy  then queues the ESL_PACKET structure (data packet) to either the
275a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET::pRxOobPacketListTail or ESL_SOCKET::pRxPacketListTail depending on
276a88c31639bb24c73383a4528a5b77066e805148blpleahy  whether urgent or normal data was received.  Finally ::EslSocketRxComplete attempts
277a88c31639bb24c73383a4528a5b77066e805148blpleahy  to start another receive operation.
278a88c31639bb24c73383a4528a5b77066e805148blpleahy
279a88c31639bb24c73383a4528a5b77066e805148blpleahy<code><pre>
280a88c31639bb24c73383a4528a5b77066e805148blpleahy
281a88c31639bb24c73383a4528a5b77066e805148blpleahy  Setup for IP4 and UDP4
282a88c31639bb24c73383a4528a5b77066e805148blpleahy
283a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------+
284a88c31639bb24c73383a4528a5b77066e805148blpleahy      | ESL_IO_MGMT        |
285a88c31639bb24c73383a4528a5b77066e805148blpleahy      |                    |
286a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    +---------------+
287a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    | Token         |
288a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    |        RxData --> NULL
289a88c31639bb24c73383a4528a5b77066e805148blpleahy      +----+---------------+
290a88c31639bb24c73383a4528a5b77066e805148blpleahy         |
291a88c31639bb24c73383a4528a5b77066e805148blpleahy         V
292a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------+
293a88c31639bb24c73383a4528a5b77066e805148blpleahy      | ESL_PACKET         |
294a88c31639bb24c73383a4528a5b77066e805148blpleahy      |                    |
295a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    +---------------+
296a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    |       pRxData --> NULL
297a88c31639bb24c73383a4528a5b77066e805148blpleahy      +----+---------------+
298a88c31639bb24c73383a4528a5b77066e805148blpleahy
299a88c31639bb24c73383a4528a5b77066e805148blpleahy  Completion for IP4 and UDP4
300a88c31639bb24c73383a4528a5b77066e805148blpleahy
301a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------+   +----------------------+
302a88c31639bb24c73383a4528a5b77066e805148blpleahy      | ESL_IO_MGMT        |   |      Data Buffer     |
303a88c31639bb24c73383a4528a5b77066e805148blpleahy      |                    |   |     (Driver owned)   |
304a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    +---------------+   +----------------------+
305a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    | Token         |               ^
306a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    |      Rx Event |               |
307a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    |               |   +----------------------+
308a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    |        RxData --> | EFI_IP4_RECEIVE_DATA |
309a88c31639bb24c73383a4528a5b77066e805148blpleahy      +----+---------------+   |    (Driver owned)    |
310a88c31639bb24c73383a4528a5b77066e805148blpleahy         |                     +----------------------+
311a88c31639bb24c73383a4528a5b77066e805148blpleahy         V                                 ^
312a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------+               .
313a88c31639bb24c73383a4528a5b77066e805148blpleahy      | ESL_PACKET         |               .
314a88c31639bb24c73383a4528a5b77066e805148blpleahy      |                    |               .
315a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    +---------------+               .
316a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    |       pRxData --> NULL  .......
317a88c31639bb24c73383a4528a5b77066e805148blpleahy      +----+---------------+
318a88c31639bb24c73383a4528a5b77066e805148blpleahy
319a88c31639bb24c73383a4528a5b77066e805148blpleahy
320a88c31639bb24c73383a4528a5b77066e805148blpleahy  Setup and completion for TCP4
321a88c31639bb24c73383a4528a5b77066e805148blpleahy
322a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------+   +--------------------------+
323a88c31639bb24c73383a4528a5b77066e805148blpleahy      | ESL_IO_MGMT        |-->| ESL_PACKET               |
324a88c31639bb24c73383a4528a5b77066e805148blpleahy      |                    |   |                          |
325a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    +---------------+   +----------------------+   |
326a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    | Token         |   | EFI_IP4_RECEIVE_DATA |   |
327a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    |        RxData --> |                      |   |
328a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    |               |   +----------------------+---+
329a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    |        Event  |   |       Data Buffer        |
330a88c31639bb24c73383a4528a5b77066e805148blpleahy      +----+---------------+   |                          |
331a88c31639bb24c73383a4528a5b77066e805148blpleahy                               |                          |
332a88c31639bb24c73383a4528a5b77066e805148blpleahy                               +--------------------------+
333a88c31639bb24c73383a4528a5b77066e805148blpleahy
334a88c31639bb24c73383a4528a5b77066e805148blpleahy</pre></code>
335a88c31639bb24c73383a4528a5b77066e805148blpleahy
336a88c31639bb24c73383a4528a5b77066e805148blpleahy  To minimize the number of buffer copies, the data is not copied until the
337a88c31639bb24c73383a4528a5b77066e805148blpleahy  application makes a receive call.  At this point socket performs a single copy
338a88c31639bb24c73383a4528a5b77066e805148blpleahy  in the receive path to move the data from the buffer filled by the network layer
339a88c31639bb24c73383a4528a5b77066e805148blpleahy  into the application's buffer.
340a88c31639bb24c73383a4528a5b77066e805148blpleahy
341a88c31639bb24c73383a4528a5b77066e805148blpleahy  The IP4 and UDP4 drivers go one step further to reduce buffer copies.  They
342a88c31639bb24c73383a4528a5b77066e805148blpleahy  allow the socket layer to hold on to the actual receive buffer until the
343a88c31639bb24c73383a4528a5b77066e805148blpleahy  application has performed a receive operation or closes the socket.  Both
344a88c31639bb24c73383a4528a5b77066e805148blpleahy  of theses operations return the buffer to the lower layer network driver
345a88c31639bb24c73383a4528a5b77066e805148blpleahy  by calling ESL_PROTOCOL_API::pfnPacketFree.
346a88c31639bb24c73383a4528a5b77066e805148blpleahy
347a88c31639bb24c73383a4528a5b77066e805148blpleahy  When a socket application wants to receive data it indirectly calls
348a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::EslSocketReceive to remove data from one of the receive data queues.  This routine
349a88c31639bb24c73383a4528a5b77066e805148blpleahy  removes the next available packet from ESL_SOCKET::pRxOobPacketListHead or
350a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET::pRxPacketListHead and copies the data from the packet
351a88c31639bb24c73383a4528a5b77066e805148blpleahy  into the application's buffer.  For SOCK_STREAM sockets, if the packet
352a88c31639bb24c73383a4528a5b77066e805148blpleahy  contains more data then the ESL_PACKET structures remains at the head of the
353a88c31639bb24c73383a4528a5b77066e805148blpleahy  receive queue for the next application receive
354a88c31639bb24c73383a4528a5b77066e805148blpleahy  operation.  For SOCK_DGRAM, SOCK_RAW and SOCK_SEQ_PACKET sockets, the ::ESL_PACKET
355a88c31639bb24c73383a4528a5b77066e805148blpleahy  structure is removed from the head of the receive queue and any remaining data is
356a88c31639bb24c73383a4528a5b77066e805148blpleahy  discarded as the packet is placed on the free queue.
357a88c31639bb24c73383a4528a5b77066e805148blpleahy
358a88c31639bb24c73383a4528a5b77066e805148blpleahy  During socket layer shutdown, ::EslSocketShutdown calls ::EslSocketRxCancel to
359a88c31639bb24c73383a4528a5b77066e805148blpleahy  cancel any pending receive operations.  EslSocketRxCancel calls the network specific
360a88c31639bb24c73383a4528a5b77066e805148blpleahy  cancel routine using ESL_PORT::pfnRxCancel.
361a88c31639bb24c73383a4528a5b77066e805148blpleahy
362a88c31639bb24c73383a4528a5b77066e805148blpleahy
363a88c31639bb24c73383a4528a5b77066e805148blpleahy  \section TransmitEngine Transmit Engine
364a88c31639bb24c73383a4528a5b77066e805148blpleahy
365a88c31639bb24c73383a4528a5b77066e805148blpleahy  Application calls to ::EslSocketTransmit cause data to be copied into a buffer.
366a88c31639bb24c73383a4528a5b77066e805148blpleahy  The buffer exists as an extension to an ESL_PACKET structure and the structure
367a88c31639bb24c73383a4528a5b77066e805148blpleahy  is placed at the end of the transmit queue.
368a88c31639bb24c73383a4528a5b77066e805148blpleahy
369a88c31639bb24c73383a4528a5b77066e805148blpleahy<code><pre>
370a88c31639bb24c73383a4528a5b77066e805148blpleahy
371a88c31639bb24c73383a4528a5b77066e805148blpleahy     *ppQueueHead: pSocket->pRxPacketListHead or pSocket->pRxOobPacketListHead
372a88c31639bb24c73383a4528a5b77066e805148blpleahy          |
373a88c31639bb24c73383a4528a5b77066e805148blpleahy          V
3740164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel        +------------+   +------------+   +------------+
375a88c31639bb24c73383a4528a5b77066e805148blpleahy  Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL
3760164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel        +------------+   +------------+   +------------+
377a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                     ^
378a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                     |
379a88c31639bb24c73383a4528a5b77066e805148blpleahy     *ppQueueTail: pSocket->pRxPacketListTail or pSocket->pRxOobPacketListTail
380a88c31639bb24c73383a4528a5b77066e805148blpleahy
381a88c31639bb24c73383a4528a5b77066e805148blpleahy</pre></code>
382a88c31639bb24c73383a4528a5b77066e805148blpleahy
383a88c31639bb24c73383a4528a5b77066e805148blpleahy  There are actually two transmit queues the normal or low priority queue which is
384a88c31639bb24c73383a4528a5b77066e805148blpleahy  the default and the urgent or high priority queue which is addressed by specifying
385a88c31639bb24c73383a4528a5b77066e805148blpleahy  the MSG_OOB flag during the transmit request.  Associated with each queue is a
386a88c31639bb24c73383a4528a5b77066e805148blpleahy  transmit engine which is responsible for sending the data in that queue.
387a88c31639bb24c73383a4528a5b77066e805148blpleahy
388a88c31639bb24c73383a4528a5b77066e805148blpleahy  The transmit engine is the state machine which removes entries from the head
389a88c31639bb24c73383a4528a5b77066e805148blpleahy  of the transmit queue and causes the data to be sent over the network.
390a88c31639bb24c73383a4528a5b77066e805148blpleahy
391a88c31639bb24c73383a4528a5b77066e805148blpleahy<code><pre>
392a88c31639bb24c73383a4528a5b77066e805148blpleahy
393a88c31639bb24c73383a4528a5b77066e805148blpleahy      +--------------------+   +--------------------+
394a88c31639bb24c73383a4528a5b77066e805148blpleahy      | ESL_IO_MGMT        |   | ESL_PACKET         |
395a88c31639bb24c73383a4528a5b77066e805148blpleahy      |                    |   |                    |
396a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    +---------------+   +----------------+   |
397a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    | Token         |   | Buffer Length  |   |
398a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    |        TxData --> | Buffer Address |   |
399a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    |               |   +----------------+---+
400a88c31639bb24c73383a4528a5b77066e805148blpleahy      |    |        Event  |   | Data Buffer        |
401a88c31639bb24c73383a4528a5b77066e805148blpleahy      +----+---------------+   |                    |
402a88c31639bb24c73383a4528a5b77066e805148blpleahy                               +--------------------+
403a88c31639bb24c73383a4528a5b77066e805148blpleahy</pre></code>
404a88c31639bb24c73383a4528a5b77066e805148blpleahy
405a88c31639bb24c73383a4528a5b77066e805148blpleahy  At a high level, the transmit engine uses a couple of data structures
406a88c31639bb24c73383a4528a5b77066e805148blpleahy  to manage the data flow.  The ::ESL_IO_MGMT structures manage the tokens and
407a88c31639bb24c73383a4528a5b77066e805148blpleahy  events for the interface to the UEFI network stack.  The ::ESL_PACKET
408a88c31639bb24c73383a4528a5b77066e805148blpleahy  structures manage the data buffers that get sent.  The transmit
409a88c31639bb24c73383a4528a5b77066e805148blpleahy  engine connects these two structures prior to transmission and disconnects
410a88c31639bb24c73383a4528a5b77066e805148blpleahy  them upon completion.
411a88c31639bb24c73383a4528a5b77066e805148blpleahy
412a88c31639bb24c73383a4528a5b77066e805148blpleahy<code><pre>
413a88c31639bb24c73383a4528a5b77066e805148blpleahy
414a88c31639bb24c73383a4528a5b77066e805148blpleahy         pPort->pTxActive or pTxOobActive
415a88c31639bb24c73383a4528a5b77066e805148blpleahy                |
416a88c31639bb24c73383a4528a5b77066e805148blpleahy                V
4170164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel          +-------------+   +-------------+   +-------------+
418a88c31639bb24c73383a4528a5b77066e805148blpleahy  Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL
4190164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel          +-------------+   +-------------+   +-------------+
420a88c31639bb24c73383a4528a5b77066e805148blpleahy
4210164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel          +-------------+   +-------------+   +-------------+
422a88c31639bb24c73383a4528a5b77066e805148blpleahy  Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL
4230164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel          +-------------+   +-------------+   +-------------+
424a88c31639bb24c73383a4528a5b77066e805148blpleahy                ^
425a88c31639bb24c73383a4528a5b77066e805148blpleahy                |
426a88c31639bb24c73383a4528a5b77066e805148blpleahy          pPort->pTxFree or pTxOobFree
427a88c31639bb24c73383a4528a5b77066e805148blpleahy
428a88c31639bb24c73383a4528a5b77066e805148blpleahy</pre></code>
429a88c31639bb24c73383a4528a5b77066e805148blpleahy
430a88c31639bb24c73383a4528a5b77066e805148blpleahy  The transmit engine manages multiple transmit operations using the
431a88c31639bb24c73383a4528a5b77066e805148blpleahy  active and free lists shown above.  ::EslSocketPortAllocate allocates the
432a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::ESL_IO_MGMT structures as an extension to the ::ESL_PORT structure.
433a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine places the ESL_IO_MGMT structures on the free list by calling
434a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::EslSocketIoInit.  During their lifetime, the ESL_IO_MGMT structures
435a88c31639bb24c73383a4528a5b77066e805148blpleahy  will move from the free list to the active list and back again.  The
436a88c31639bb24c73383a4528a5b77066e805148blpleahy  active list contains the packets that are actively being processed by
437a88c31639bb24c73383a4528a5b77066e805148blpleahy  the UEFI network stack.  Eventually the ESL_IO_MGMT structures will be
438a88c31639bb24c73383a4528a5b77066e805148blpleahy  removed from the free list and be deallocated by the EslSocketPortClose
439a88c31639bb24c73383a4528a5b77066e805148blpleahy  routine.
440a88c31639bb24c73383a4528a5b77066e805148blpleahy
441a88c31639bb24c73383a4528a5b77066e805148blpleahy  The network specific code calls the ::EslSocketTxStart routine
442a88c31639bb24c73383a4528a5b77066e805148blpleahy  to hand a packet to the network stack.  EslSocketTxStart connects
443a88c31639bb24c73383a4528a5b77066e805148blpleahy  the transmit packet (::ESL_PACKET) to an ::ESL_IO_MGMT structure
444a88c31639bb24c73383a4528a5b77066e805148blpleahy  and then queues the result to one of the active lists:
445a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT::pTxActive or ESL_PORT::pTxOobActive.  The routine then
446a88c31639bb24c73383a4528a5b77066e805148blpleahy  hands the packet to the network stack.
447a88c31639bb24c73383a4528a5b77066e805148blpleahy
448a88c31639bb24c73383a4528a5b77066e805148blpleahy  Upon completion, the network specific TxComplete routine calls
449a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::EslSocketTxComplete to disconnect the transmit packet from the
450a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IO_MGMT structure and frees the ::ESL_PACKET structure by calling
451a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::EslSocketPacketFree.  The routine places the ::ESL_IO_MGMT structure
452a88c31639bb24c73383a4528a5b77066e805148blpleahy  into the free list either ESL_PORT::pTxFree or ESL_PORT::pTxOobFree.
453a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslSocketTxComplete then starts the next transmit operation while
454a88c31639bb24c73383a4528a5b77066e805148blpleahy  the socket is active or calls the ::EslSocketPortCloseTxDone routine
455a88c31639bb24c73383a4528a5b77066e805148blpleahy  when the socket is shutting down.
456a88c31639bb24c73383a4528a5b77066e805148blpleahy
457d7ce700605e1af0e455e31ec11f19ff21d26b525darylm**/
458d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
459d7ce700605e1af0e455e31ec11f19ff21d26b525darylm#include "Socket.h"
460d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
461d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
462beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Socket driver connection points
463d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
464d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  List the network stack connection points for the socket driver.
465d7ce700605e1af0e455e31ec11f19ff21d26b525darylm**/
466a88c31639bb24c73383a4528a5b77066e805148blpleahyCONST ESL_SOCKET_BINDING cEslSocketBinding[] = {
467a88c31639bb24c73383a4528a5b77066e805148blpleahy  { L"Ip4",
468a88c31639bb24c73383a4528a5b77066e805148blpleahy    &gEfiIp4ServiceBindingProtocolGuid,
469a88c31639bb24c73383a4528a5b77066e805148blpleahy    &gEfiIp4ProtocolGuid,
470a88c31639bb24c73383a4528a5b77066e805148blpleahy    &mEslIp4ServiceGuid,
471a88c31639bb24c73383a4528a5b77066e805148blpleahy    OFFSET_OF ( ESL_LAYER, pIp4List ),
472a88c31639bb24c73383a4528a5b77066e805148blpleahy    4,    //  RX buffers
473a88c31639bb24c73383a4528a5b77066e805148blpleahy    4,    //  TX buffers
474a88c31639bb24c73383a4528a5b77066e805148blpleahy    0 },  //  TX Oob buffers
475d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  { L"Tcp4",
476d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    &gEfiTcp4ServiceBindingProtocolGuid,
477a88c31639bb24c73383a4528a5b77066e805148blpleahy    &gEfiTcp4ProtocolGuid,
478d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    &mEslTcp4ServiceGuid,
479a88c31639bb24c73383a4528a5b77066e805148blpleahy    OFFSET_OF ( ESL_LAYER, pTcp4List ),
480a88c31639bb24c73383a4528a5b77066e805148blpleahy    4,    //  RX buffers
481a88c31639bb24c73383a4528a5b77066e805148blpleahy    4,    //  TX buffers
482a88c31639bb24c73383a4528a5b77066e805148blpleahy    4 },  //  TX Oob buffers
4833bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  { L"Tcp6",
4843bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    &gEfiTcp6ServiceBindingProtocolGuid,
4853bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    &gEfiTcp6ProtocolGuid,
4863bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    &mEslTcp6ServiceGuid,
4873bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    OFFSET_OF ( ESL_LAYER, pTcp6List ),
4883bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    4,    //  RX buffers
4893bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    4,    //  TX buffers
4903bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    4 },  //  TX Oob buffers
491d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  { L"Udp4",
492d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    &gEfiUdp4ServiceBindingProtocolGuid,
493a88c31639bb24c73383a4528a5b77066e805148blpleahy    &gEfiUdp4ProtocolGuid,
494d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    &mEslUdp4ServiceGuid,
495a88c31639bb24c73383a4528a5b77066e805148blpleahy    OFFSET_OF ( ESL_LAYER, pUdp4List ),
496a88c31639bb24c73383a4528a5b77066e805148blpleahy    4,    //  RX buffers
497a88c31639bb24c73383a4528a5b77066e805148blpleahy    4,    //  TX buffers
4983bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    0 },  //  TX Oob buffers
4993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  { L"Udp6",
5003bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    &gEfiUdp6ServiceBindingProtocolGuid,
5013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    &gEfiUdp6ProtocolGuid,
5023bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    &mEslUdp6ServiceGuid,
5033bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    OFFSET_OF ( ESL_LAYER, pUdp6List ),
5043bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    4,    //  RX buffers
5053bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    4,    //  TX buffers
506a88c31639bb24c73383a4528a5b77066e805148blpleahy    0 }   //  TX Oob buffers
507d7ce700605e1af0e455e31ec11f19ff21d26b525darylm};
508d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
509d7ce700605e1af0e455e31ec11f19ff21d26b525darylmCONST UINTN cEslSocketBindingEntries = DIM ( cEslSocketBinding );
510d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
511beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/// APIs to support the various socket types for the v4 network stack.
512a88c31639bb24c73383a4528a5b77066e805148blpleahyCONST ESL_PROTOCOL_API * cEslAfInetApi[] = {
513a88c31639bb24c73383a4528a5b77066e805148blpleahy  NULL,             //  0
514a88c31639bb24c73383a4528a5b77066e805148blpleahy  &cEslTcp4Api,     //  SOCK_STREAM
515a88c31639bb24c73383a4528a5b77066e805148blpleahy  &cEslUdp4Api,     //  SOCK_DGRAM
516a88c31639bb24c73383a4528a5b77066e805148blpleahy  &cEslIp4Api,      //  SOCK_RAW
517a88c31639bb24c73383a4528a5b77066e805148blpleahy  NULL,             //  SOCK_RDM
518a88c31639bb24c73383a4528a5b77066e805148blpleahy  &cEslTcp4Api      //  SOCK_SEQPACKET
519a88c31639bb24c73383a4528a5b77066e805148blpleahy};
520a88c31639bb24c73383a4528a5b77066e805148blpleahy
521beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/// Number of entries in the v4 API array ::cEslAfInetApi.
522a88c31639bb24c73383a4528a5b77066e805148blpleahyCONST int cEslAfInetApiSize = DIM ( cEslAfInetApi );
523a88c31639bb24c73383a4528a5b77066e805148blpleahy
524a88c31639bb24c73383a4528a5b77066e805148blpleahy
525beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/// APIs to support the various socket types for the v6 network stack.
526a88c31639bb24c73383a4528a5b77066e805148blpleahyCONST ESL_PROTOCOL_API * cEslAfInet6Api[] = {
527a88c31639bb24c73383a4528a5b77066e805148blpleahy  NULL,             //  0
5283bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  &cEslTcp6Api,     //  SOCK_STREAM
5293bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  &cEslUdp6Api,     //  SOCK_DGRAM
530a88c31639bb24c73383a4528a5b77066e805148blpleahy  NULL,             //  SOCK_RAW
531a88c31639bb24c73383a4528a5b77066e805148blpleahy  NULL,             //  SOCK_RDM
5323bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  &cEslTcp6Api      //  SOCK_SEQPACKET
533a88c31639bb24c73383a4528a5b77066e805148blpleahy};
534a88c31639bb24c73383a4528a5b77066e805148blpleahy
535beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/// Number of entries in the v6 API array ::cEslAfInet6Api.
536a88c31639bb24c73383a4528a5b77066e805148blpleahyCONST int cEslAfInet6ApiSize = DIM ( cEslAfInet6Api );
537a88c31639bb24c73383a4528a5b77066e805148blpleahy
538a88c31639bb24c73383a4528a5b77066e805148blpleahy
539beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/// Global management structure for the socket layer.
540a88c31639bb24c73383a4528a5b77066e805148blpleahyESL_LAYER mEslLayer;
541d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
542d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
543beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Initialize an endpoint for network communication.
544d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
545a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine initializes the communication endpoint.
546a88c31639bb24c73383a4528a5b77066e805148blpleahy
547a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::socket routine calls this routine indirectly to create
548a88c31639bb24c73383a4528a5b77066e805148blpleahy  the communication endpoint.
549d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
550beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in] pSocketProtocol Address of the socket protocol structure.
551beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  domain   Select the family of protocols for the client or server
552beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                       application.  See the ::socket documentation for values.
553beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  type     Specifies how to make the network connection.
554beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                       See the ::socket documentation for values.
555beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  protocol Specifies the lower layer protocol to use.
556beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                       See the ::socket documentation for values.
557beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out] pErrno   Address to receive the errno value upon completion.
558d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
559d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_SUCCESS - Socket successfully created
560d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_INVALID_PARAMETER - Invalid domain value, errno = EAFNOSUPPORT
561d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_INVALID_PARAMETER - Invalid type value, errno = EINVAL
562d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_INVALID_PARAMETER - Invalid protocol value, errno = EINVAL
563d7ce700605e1af0e455e31ec11f19ff21d26b525darylm **/
564d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
565d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEslSocket (
566d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
567d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int domain,
568d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int type,
569d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int protocol,
570d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int * pErrno
571d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
572d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
573a88c31639bb24c73383a4528a5b77066e805148blpleahy  CONST ESL_PROTOCOL_API * pApi;
574a88c31639bb24c73383a4528a5b77066e805148blpleahy  CONST ESL_PROTOCOL_API ** ppApiArray;
575a88c31639bb24c73383a4528a5b77066e805148blpleahy  CONST ESL_PROTOCOL_API ** ppApiArrayEnd;
576a88c31639bb24c73383a4528a5b77066e805148blpleahy  int ApiArraySize;
577a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
578d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
579d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  int errno;
580d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
581d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
582d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
583d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Locate the socket
584d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
585d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
586d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Set the default domain if necessary
587d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( AF_UNSPEC == domain ) {
588d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    domain = AF_INET;
589d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
590d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
591d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Assume success
592d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  errno = 0;
593d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Status = EFI_SUCCESS;
594d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
595d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Use break instead of goto
596d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  for ( ; ; ) {
597d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Validate the domain value
598d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if (( AF_INET != domain )
5993bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      && ( AF_INET6 != domain )
600a88c31639bb24c73383a4528a5b77066e805148blpleahy      && ( AF_LOCAL != domain )) {
601d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,
602a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - Invalid domain value\r\n" ));
603d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EFI_INVALID_PARAMETER;
604d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      errno = EAFNOSUPPORT;
605d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      break;
606d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
607d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
608a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Determine the protocol APIs
609a88c31639bb24c73383a4528a5b77066e805148blpleahy    ppApiArray = NULL;
610a88c31639bb24c73383a4528a5b77066e805148blpleahy    ApiArraySize = 0;
611a88c31639bb24c73383a4528a5b77066e805148blpleahy    if (( AF_INET == domain )
612a88c31639bb24c73383a4528a5b77066e805148blpleahy      || ( AF_LOCAL == domain )) {
613a88c31639bb24c73383a4528a5b77066e805148blpleahy      ppApiArray = &cEslAfInetApi[0];
614a88c31639bb24c73383a4528a5b77066e805148blpleahy      ApiArraySize = cEslAfInetApiSize;
615a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
616a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
617a88c31639bb24c73383a4528a5b77066e805148blpleahy      ppApiArray = &cEslAfInet6Api[0];
618a88c31639bb24c73383a4528a5b77066e805148blpleahy      ApiArraySize = cEslAfInet6ApiSize;
619a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
620a88c31639bb24c73383a4528a5b77066e805148blpleahy
621d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Set the default type if necessary
622d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( 0 == type ) {
623d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      type = SOCK_STREAM;
624d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
625d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
626d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Validate the type value
627a88c31639bb24c73383a4528a5b77066e805148blpleahy    if (( type >= ApiArraySize )
628a88c31639bb24c73383a4528a5b77066e805148blpleahy      || ( NULL == ppApiArray )
629a88c31639bb24c73383a4528a5b77066e805148blpleahy      || ( NULL == ppApiArray[ type ])) {
630a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,
631a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - Invalid type value\r\n" ));
632a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  The socket type is not supported
633d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EFI_INVALID_PARAMETER;
634a88c31639bb24c73383a4528a5b77066e805148blpleahy      errno = EPROTOTYPE;
635d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      break;
636d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
637d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
638a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Set the default protocol if necessary
639a88c31639bb24c73383a4528a5b77066e805148blpleahy    pApi = ppApiArray[ type ];
640a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( 0 == protocol ) {
641a88c31639bb24c73383a4528a5b77066e805148blpleahy      protocol = pApi->DefaultProtocol;
642a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
643a88c31639bb24c73383a4528a5b77066e805148blpleahy
644d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Validate the protocol value
645a88c31639bb24c73383a4528a5b77066e805148blpleahy    if (( pApi->DefaultProtocol != protocol )
646a88c31639bb24c73383a4528a5b77066e805148blpleahy      && ( SOCK_RAW != type )) {
647d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EFI_INVALID_PARAMETER;
648a88c31639bb24c73383a4528a5b77066e805148blpleahy
649a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Assume that the driver supports this protocol
650a88c31639bb24c73383a4528a5b77066e805148blpleahy      ppApiArray = &cEslAfInetApi[0];
651a88c31639bb24c73383a4528a5b77066e805148blpleahy      ppApiArrayEnd = &ppApiArray [ cEslAfInetApiSize ];
652a88c31639bb24c73383a4528a5b77066e805148blpleahy      while ( ppApiArrayEnd > ppApiArray ) {
653a88c31639bb24c73383a4528a5b77066e805148blpleahy        pApi = *ppApiArray;
654a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( protocol == pApi->DefaultProtocol ) {
655a88c31639bb24c73383a4528a5b77066e805148blpleahy          break;
656a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
657a88c31639bb24c73383a4528a5b77066e805148blpleahy        ppApiArray += 1;
658a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
659a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( ppApiArrayEnd <= ppApiArray ) {
660a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Verify against the IPv6 table
661a88c31639bb24c73383a4528a5b77066e805148blpleahy        ppApiArray = &cEslAfInet6Api[0];
662a88c31639bb24c73383a4528a5b77066e805148blpleahy        ppApiArrayEnd = &ppApiArray [ cEslAfInet6ApiSize ];
663a88c31639bb24c73383a4528a5b77066e805148blpleahy        while ( ppApiArrayEnd > ppApiArray ) {
664a88c31639bb24c73383a4528a5b77066e805148blpleahy          pApi = *ppApiArray;
665a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( protocol == pApi->DefaultProtocol ) {
666a88c31639bb24c73383a4528a5b77066e805148blpleahy            break;
667a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
668a88c31639bb24c73383a4528a5b77066e805148blpleahy          ppApiArray += 1;
669a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
670a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
671a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( ppApiArrayEnd <= ppApiArray ) {
672a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,
673a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "ERROR - The protocol is not supported!\r\n" ));
674a88c31639bb24c73383a4528a5b77066e805148blpleahy        errno = EPROTONOSUPPORT;
675a88c31639bb24c73383a4528a5b77066e805148blpleahy        break;
676a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
677a88c31639bb24c73383a4528a5b77066e805148blpleahy
678a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  The driver does not support this protocol
679a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,
680a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - The protocol does not support this socket type!\r\n" ));
681a88c31639bb24c73383a4528a5b77066e805148blpleahy      errno = EPROTONOSUPPORT;
682a88c31639bb24c73383a4528a5b77066e805148blpleahy      errno = EPROTOTYPE;
683d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      break;
684d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
685d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Save the socket attributes
686a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->pApi = pApi;
687d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->Domain = domain;
688d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->Type = type;
689d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->Protocol = protocol;
690d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
691d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Done
692d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    break;
693d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
694d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
695d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pErrno ) {
696d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    *pErrno = errno;
697d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
698d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
699d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
700d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
701d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
702d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
703beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Accept a network connection.
704d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
705a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine calls the network specific layer to remove the next
706a88c31639bb24c73383a4528a5b77066e805148blpleahy  connection from the FIFO.
707d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
708a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::accept calls this routine to poll for a network
709a88c31639bb24c73383a4528a5b77066e805148blpleahy  connection to the socket.  When a connection is available
710a88c31639bb24c73383a4528a5b77066e805148blpleahy  this routine returns the ::EFI_SOCKET_PROTOCOL structure address
711a88c31639bb24c73383a4528a5b77066e805148blpleahy  associated with the new socket and the remote network address
712a88c31639bb24c73383a4528a5b77066e805148blpleahy  if requested.
713a88c31639bb24c73383a4528a5b77066e805148blpleahy
714beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      pSocketProtocol   Address of an ::EFI_SOCKET_PROTOCOL structure.
715beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      pSockAddr         Address of a buffer to receive the remote
716beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                                    network address.
717beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in,out]  pSockAddrLength   Length in bytes of the address buffer.
718d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                                    On output specifies the length of the
719d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                                    remote network address.
720beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out]     ppSocketProtocol  Address of a buffer to receive the
721beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                                    ::EFI_SOCKET_PROTOCOL instance
722beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                                    associated with the new socket.
723beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out]     pErrno            Address to receive the errno value upon completion.
724d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
725d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_SUCCESS   New connection successfully created
726d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_NOT_READY No connection is available
727d7ce700605e1af0e455e31ec11f19ff21d26b525darylm **/
728d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
729d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEslSocketAccept (
730d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
731d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN struct sockaddr * pSockAddr,
732d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN OUT socklen_t * pSockAddrLength,
733d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol,
734d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int * pErrno
735d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
736d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
737a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pNewSocket;
738a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
739d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
740d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_TPL TplPrevious;
741d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
742d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
743d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
744d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
745d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Assume success
746d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
747d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Status = EFI_SUCCESS;
748d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
749d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
750d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Validate the socket
751d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
752d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pSocket = NULL;
753d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pNewSocket = NULL;
754d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pSocketProtocol ) {
755d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
756d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
757d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
758a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Verify the API
759d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
760a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( NULL == pSocket->pApi->pfnAccept ) {
761a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_UNSUPPORTED;
762a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = ENOTSUP;
763d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
764d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    else {
765d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
766a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Validate the sockaddr
767d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
768a88c31639bb24c73383a4528a5b77066e805148blpleahy      if (( NULL != pSockAddr )
769a88c31639bb24c73383a4528a5b77066e805148blpleahy        && ( NULL == pSockAddrLength )) {
770d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        DEBUG (( DEBUG_ACCEPT,
771a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "ERROR - pSockAddr is NULL!\r\n" ));
772a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = EFI_INVALID_PARAMETER;
773a88c31639bb24c73383a4528a5b77066e805148blpleahy        pSocket->errno = EFAULT;
774d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
775d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      else {
776d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
777a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Synchronize with the socket layer
778d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
779a88c31639bb24c73383a4528a5b77066e805148blpleahy        RAISE_TPL ( TplPrevious, TPL_SOCKETS );
780d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
781a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
782a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Verify that the socket is in the listen state
783a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
784a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( SOCKET_STATE_LISTENING != pSocket->State ) {
785a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_ACCEPT,
786a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "ERROR - Socket is not listening!\r\n" ));
787a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( NULL == pSocket->pApi->pfnAccept ) {
788d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
789a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Socket does not support listen
790d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
791a88c31639bb24c73383a4528a5b77066e805148blpleahy            pSocket->errno = EOPNOTSUPP;
792a88c31639bb24c73383a4528a5b77066e805148blpleahy            Status = EFI_UNSUPPORTED;
793d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          }
794d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          else {
795d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
796a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Socket supports listen, but not in listen state
797d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
798a88c31639bb24c73383a4528a5b77066e805148blpleahy            pSocket->errno = EINVAL;
799a88c31639bb24c73383a4528a5b77066e805148blpleahy            Status = EFI_NOT_STARTED;
800d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          }
801d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
802d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        else {
803d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
804a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Determine if a socket is available
805d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
806a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( 0 == pSocket->FifoDepth ) {
807d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
808a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  No connections available
809a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Determine if any ports are available
810d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
811a88c31639bb24c73383a4528a5b77066e805148blpleahy            if ( NULL == pSocket->pPortList ) {
812a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
813a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  No ports available
814a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
815a88c31639bb24c73383a4528a5b77066e805148blpleahy              Status = EFI_DEVICE_ERROR;
816a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket->errno = EINVAL;
817a88c31639bb24c73383a4528a5b77066e805148blpleahy
818a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
819a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Update the socket state
820a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
821a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket->State = SOCKET_STATE_NO_PORTS;
822d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            }
823a88c31639bb24c73383a4528a5b77066e805148blpleahy            else {
824a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
825a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Ports are available
826a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  No connection requests at this time
827a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
828a88c31639bb24c73383a4528a5b77066e805148blpleahy              Status = EFI_NOT_READY;
829a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket->errno = EAGAIN;
830d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            }
831a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
832a88c31639bb24c73383a4528a5b77066e805148blpleahy          else {
833d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
834d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
835a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Attempt to accept the connection and
836a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  get the remote network address
837d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
838a88c31639bb24c73383a4528a5b77066e805148blpleahy            pNewSocket = pSocket->pFifoHead;
839a88c31639bb24c73383a4528a5b77066e805148blpleahy            ASSERT ( NULL != pNewSocket );
840a88c31639bb24c73383a4528a5b77066e805148blpleahy            Status = pSocket->pApi->pfnAccept ( pNewSocket,
841a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                pSockAddr,
842a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                pSockAddrLength );
843a88c31639bb24c73383a4528a5b77066e805148blpleahy            if ( !EFI_ERROR ( Status )) {
844a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
845a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Remove the new socket from the list
846a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
847a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket->pFifoHead = pNewSocket->pNextConnection;
848a88c31639bb24c73383a4528a5b77066e805148blpleahy              if ( NULL == pSocket->pFifoHead ) {
849a88c31639bb24c73383a4528a5b77066e805148blpleahy                pSocket->pFifoTail = NULL;
850a88c31639bb24c73383a4528a5b77066e805148blpleahy              }
851d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
852a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
853a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Account for this socket
854a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
855a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket->FifoDepth -= 1;
856a88c31639bb24c73383a4528a5b77066e805148blpleahy
857a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
858a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Update the new socket's state
859a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
860a88c31639bb24c73383a4528a5b77066e805148blpleahy              pNewSocket->State = SOCKET_STATE_CONNECTED;
861a88c31639bb24c73383a4528a5b77066e805148blpleahy              pNewSocket->bConfigured = TRUE;
862a88c31639bb24c73383a4528a5b77066e805148blpleahy              DEBUG (( DEBUG_ACCEPT,
863a88c31639bb24c73383a4528a5b77066e805148blpleahy                        "0x%08x: Socket connected\r\n",
864a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pNewSocket ));
865a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
866d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          }
867d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
868d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
869a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
870a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Release the socket layer synchronization
871a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
872a88c31639bb24c73383a4528a5b77066e805148blpleahy        RESTORE_TPL ( TplPrevious );
873a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
874d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
875d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
876d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
877d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
878d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the new socket
879d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
880d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if (( NULL != ppSocketProtocol )
881d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    && ( NULL != pNewSocket )) {
882d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    *ppSocketProtocol = &pNewSocket->SocketProtocol;
883d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
884d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
885d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
886d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
887d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
888d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pErrno ) {
889d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( NULL != pSocket ) {
890d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      *pErrno = pSocket->errno;
891d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
892a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
893d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EFI_INVALID_PARAMETER;
894a88c31639bb24c73383a4528a5b77066e805148blpleahy      *pErrno = ENOTSOCK;
895d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
896d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
897d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
898d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
899d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
900d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
901d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
902beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Allocate and initialize a ESL_SOCKET structure.
9030164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
904a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support function allocates an ::ESL_SOCKET structure
905d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  and installs a protocol on ChildHandle.  If pChildHandle is a
906d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pointer to NULL, then a new handle is created and returned in
907d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pChildHandle.  If pChildHandle is not a pointer to NULL, then
908d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  the protocol installs on the existing pChildHandle.
909d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
910beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in,out]  pChildHandle  Pointer to the handle of the child to create.
911d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                                If it is NULL, then a new handle is created.
9120164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel                                If it is a pointer to an existing UEFI handle,
913d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                                then the protocol is added to the existing UEFI
914d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                                handle.
915beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      DebugFlags    Flags for debug messages
916beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in,out]  ppSocket      The buffer to receive an ::ESL_SOCKET structure address.
917d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
918d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_SUCCESS           The protocol was added to ChildHandle.
919d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
920a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to create
921d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                                the child
922d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval other                 The child handle was not created
923d7ce700605e1af0e455e31ec11f19ff21d26b525darylm**/
924d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
925d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFIAPI
926d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEslSocketAllocate (
927d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN OUT EFI_HANDLE * pChildHandle,
928d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN     UINTN DebugFlags,
929a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN OUT ESL_SOCKET ** ppSocket
930d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
931d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
932d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  UINTN LengthInBytes;
933a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_LAYER * pLayer;
934a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
935d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
936d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_TPL TplPrevious;
937d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
938d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
939d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
940d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
941d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Create a socket structure
942d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
943d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  LengthInBytes = sizeof ( *pSocket );
944a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = (ESL_SOCKET *) AllocateZeroPool ( LengthInBytes );
945a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL != pSocket ) {
946d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,
947d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              "0x%08x: Allocate pSocket, %d bytes\r\n",
948d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              pSocket,
949d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              LengthInBytes ));
950d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
951d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
952d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Initialize the socket protocol
953d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
954d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->Signature = SOCKET_SIGNATURE;
955d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnAccept = EslSocketAccept;
956d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnBind = EslSocketBind;
957d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnClosePoll = EslSocketClosePoll;
958d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnCloseStart = EslSocketCloseStart;
959d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnConnect = EslSocketConnect;
960d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnGetLocal = EslSocketGetLocalAddress;
961d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnGetPeer = EslSocketGetPeerAddress;
962d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnListen = EslSocketListen;
963d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnOptionGet = EslSocketOptionGet;
964d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnOptionSet = EslSocketOptionSet;
965d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnPoll = EslSocketPoll;
966d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnReceive = EslSocketReceive;
967d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnShutdown = EslSocketShutdown;
968d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->SocketProtocol.pfnSocket = EslSocket;
969a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->SocketProtocol.pfnTransmit = EslSocketTransmit;
970d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
971d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->MaxRxBuf = MAX_RX_DATA;
972d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->MaxTxBuf = MAX_TX_DATA;
973d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
974d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
975d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Install the socket protocol on the specified handle
976d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
977d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    Status = gBS->InstallMultipleProtocolInterfaces (
978d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                    pChildHandle,
979d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                    &gEfiSocketProtocolGuid,
980d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                    &pSocket->SocketProtocol,
981d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                    NULL
982d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                    );
983d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( !EFI_ERROR ( Status )) {
984d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
985d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                "Installed: gEfiSocketProtocolGuid on   0x%08x\r\n",
986d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                *pChildHandle ));
987d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      pSocket->SocketProtocol.SocketHandle = *pChildHandle;
988d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
989d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
990d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Synchronize with the socket layer
991d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
992d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      RAISE_TPL ( TplPrevious, TPL_SOCKETS );
993d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
994d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
995d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Add this socket to the list
996d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
997d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      pLayer = &mEslLayer;
998d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      pSocket->pNext = pLayer->pSocketList;
999d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      pLayer->pSocketList = pSocket;
1000d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1001d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1002d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Release the socket layer synchronization
1003d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1004d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      RESTORE_TPL ( TplPrevious );
1005d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1006d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1007d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Return the socket structure address
1008d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1009d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      *ppSocket = pSocket;
1010d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1011d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    else {
1012d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,
1013d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                "ERROR - Failed to install gEfiSocketProtocolGuid on 0x%08x, Status: %r\r\n",
1014d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                *pChildHandle,
1015d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                Status ));
1016d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1017d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1018d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1019d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Release the socket if necessary
1020d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1021d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( EFI_ERROR ( Status )) {
1022d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      gBS->FreePool ( pSocket );
1023d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,
1024d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                "0x%08x: Free pSocket, %d bytes\r\n",
1025d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                pSocket,
1026d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                sizeof ( *pSocket )));
1027d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      pSocket = NULL;
1028d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1029d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1030d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  else {
1031a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = EFI_OUT_OF_RESOURCES;
1032d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1033d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1034d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1035d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
1036d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1037d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
1038d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
1039d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
1040d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1041d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1042beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Bind a name to a socket.
1043d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1044a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine calls the network specific layer to save the network
1045a88c31639bb24c73383a4528a5b77066e805148blpleahy  address of the local connection point.
1046d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1047a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::bind routine calls this routine to connect a name
1048a88c31639bb24c73383a4528a5b77066e805148blpleahy  (network address and port) to a socket on the local machine.
1049a88c31639bb24c73383a4528a5b77066e805148blpleahy
1050beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
1051beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSockAddr       Address of a sockaddr structure that contains the
1052beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                              connection point on the local machine.  An IPv4 address
1053beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                              of INADDR_ANY specifies that the connection is made to
1054beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                              all of the network stacks on the platform.  Specifying a
1055beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                              specific IPv4 address restricts the connection to the
1056beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                              network stack supporting that address.  Specifying zero
1057beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                              for the port causes the network layer to assign a port
1058beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                              number from the dynamic range.  Specifying a specific
1059beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                              port number causes the network layer to use that port.
1060beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  SockAddrLength  Specifies the length in bytes of the sockaddr structure.
1061beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out] pErrno          Address to receive the errno value upon completion.
1062d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1063d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_SUCCESS - Socket successfully created
1064beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
1065d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
1066d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEslSocketBind (
1067d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
1068a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN CONST struct sockaddr * pSockAddr,
1069d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN socklen_t SockAddrLength,
1070d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  OUT int * pErrno
1071d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
1072d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
1073a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_HANDLE ChildHandle;
1074a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINT8 * pBuffer;
1075a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
1076a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SERVICE ** ppServiceListHead;
1077a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
1078a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SERVICE * pService;
1079a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;
1080d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
1081d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_TPL TplPrevious;
1082d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1083d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
1084d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1085d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1086d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Assume success
1087d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1088d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Status = EFI_SUCCESS;
1089d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1090d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1091d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Validate the socket
1092d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1093d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pSocket = NULL;
1094d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pSocketProtocol ) {
1095d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
1096d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1097d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1098d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Validate the structure pointer
1099d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1100a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->errno = 0;
1101d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( NULL == pSockAddr ) {
1102d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      DEBUG (( DEBUG_BIND,
1103d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                "ERROR - pSockAddr is NULL!\r\n" ));
1104d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EFI_INVALID_PARAMETER;
1105d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      pSocket->errno = EFAULT;
1106d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1107a88c31639bb24c73383a4528a5b77066e805148blpleahy
1108a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
1109a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Validate the local address length
1110a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
1111a88c31639bb24c73383a4528a5b77066e805148blpleahy    else if ( SockAddrLength < pSocket->pApi->MinimumAddressLength ) {
1112a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_BIND,
1113a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - Invalid bind name length: %d\r\n",
1114a88c31639bb24c73383a4528a5b77066e805148blpleahy                SockAddrLength ));
1115a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_INVALID_PARAMETER;
1116a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = EINVAL;
1117a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
1118a88c31639bb24c73383a4528a5b77066e805148blpleahy
1119a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
1120a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Validate the shutdown state
1121a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
1122a88c31639bb24c73383a4528a5b77066e805148blpleahy    else if ( pSocket->bRxDisable || pSocket->bTxDisable ) {
1123a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_BIND,
1124a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - Shutdown has been called on socket 0x%08x\r\n",
1125a88c31639bb24c73383a4528a5b77066e805148blpleahy                pSocket ));
1126a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = EINVAL;
1127a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_INVALID_PARAMETER;
1128a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
1129a88c31639bb24c73383a4528a5b77066e805148blpleahy
1130a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
1131a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Verify the socket state
1132a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
1133a88c31639bb24c73383a4528a5b77066e805148blpleahy    else if ( SOCKET_STATE_NOT_CONFIGURED != pSocket->State ) {
1134a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_BIND,
1135a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - The socket 0x%08x is already configured!\r\n",
1136a88c31639bb24c73383a4528a5b77066e805148blpleahy                pSocket ));
1137a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = EINVAL;
1138a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_ALREADY_STARTED;
1139a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
1140a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
1141d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1142a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Synchronize with the socket layer
1143d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1144a88c31639bb24c73383a4528a5b77066e805148blpleahy      RAISE_TPL ( TplPrevious, TPL_SOCKETS );
1145d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1146a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
1147a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Assume no ports are available
1148a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
1149a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = EADDRNOTAVAIL;
1150a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_INVALID_PARAMETER;
1151d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1152a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
1153a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Walk the list of services
1154a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
1155a88c31639bb24c73383a4528a5b77066e805148blpleahy      pBuffer = (UINT8 *)&mEslLayer;
1156a88c31639bb24c73383a4528a5b77066e805148blpleahy      pBuffer = &pBuffer[ pSocket->pApi->ServiceListOffset ];
1157a88c31639bb24c73383a4528a5b77066e805148blpleahy      ppServiceListHead = (ESL_SERVICE **)pBuffer;
1158a88c31639bb24c73383a4528a5b77066e805148blpleahy      pService = *ppServiceListHead;
1159a88c31639bb24c73383a4528a5b77066e805148blpleahy      while ( NULL != pService ) {
1160d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1161a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Create the port
1162d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1163a88c31639bb24c73383a4528a5b77066e805148blpleahy        pServiceBinding = pService->pServiceBinding;
1164a88c31639bb24c73383a4528a5b77066e805148blpleahy        ChildHandle = NULL;
1165a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = pServiceBinding->CreateChild ( pServiceBinding,
1166a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                &ChildHandle );
1167a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( !EFI_ERROR ( Status )) {
1168a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_BIND | DEBUG_POOL,
1169a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "0x%08x: %s port handle created\r\n",
1170a88c31639bb24c73383a4528a5b77066e805148blpleahy                    ChildHandle,
1171a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pService->pSocketBinding->pName ));
1172d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1173d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
1174a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Open the port
1175d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
1176a88c31639bb24c73383a4528a5b77066e805148blpleahy          Status = EslSocketPortAllocate ( pSocket,
1177a88c31639bb24c73383a4528a5b77066e805148blpleahy                                           pService,
1178a88c31639bb24c73383a4528a5b77066e805148blpleahy                                           ChildHandle,
1179a88c31639bb24c73383a4528a5b77066e805148blpleahy                                           pSockAddr,
1180a88c31639bb24c73383a4528a5b77066e805148blpleahy                                           TRUE,
1181a88c31639bb24c73383a4528a5b77066e805148blpleahy                                           DEBUG_BIND,
1182a88c31639bb24c73383a4528a5b77066e805148blpleahy                                           &pPort );
1183a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
1184a88c31639bb24c73383a4528a5b77066e805148blpleahy        else {
1185a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_BIND | DEBUG_POOL,
1186a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "ERROR - Failed to open %s port handle, Status: %r\r\n",
1187a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pService->pSocketBinding->pName,
1188a88c31639bb24c73383a4528a5b77066e805148blpleahy                    Status ));
1189d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
1190d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1191d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1192a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Set the next service
1193d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1194a88c31639bb24c73383a4528a5b77066e805148blpleahy        pService = pService->pNext;
1195a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
1196a88c31639bb24c73383a4528a5b77066e805148blpleahy
1197a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
1198a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Verify that at least one network connection was found
1199a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
1200f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy      if ( NULL != pSocket->pPortList ) {
1201f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy        Status = EFI_SUCCESS;
1202f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy      }
1203f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy      else {
1204a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( EADDRNOTAVAIL == pSocket->errno ) {
1205a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,
1206a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "ERROR - Socket address is not available!\r\n" ));
1207a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
1208a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( EADDRINUSE == pSocket->errno ) {
1209a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,
1210a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "ERROR - Socket address is in use!\r\n" ));
1211d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
1212a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = EFI_INVALID_PARAMETER;
1213a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
1214d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1215a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
1216a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Mark this socket as bound if successful
1217a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
1218a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( !EFI_ERROR ( Status )) {
1219a88c31639bb24c73383a4528a5b77066e805148blpleahy        pSocket->State = SOCKET_STATE_BOUND;
1220a88c31639bb24c73383a4528a5b77066e805148blpleahy        pSocket->errno = 0;
1221d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
1222a88c31639bb24c73383a4528a5b77066e805148blpleahy
1223a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
1224a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Release the socket layer synchronization
1225a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
1226a88c31639bb24c73383a4528a5b77066e805148blpleahy      RESTORE_TPL ( TplPrevious );
1227d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1228d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1229d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1230d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1231d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
1232d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1233d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pErrno ) {
1234d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( NULL != pSocket ) {
1235d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      *pErrno = pSocket->errno;
1236d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1237a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
1238d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EFI_INVALID_PARAMETER;
1239a88c31639bb24c73383a4528a5b77066e805148blpleahy      *pErrno = ENOTSOCK;
1240d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1241d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1242d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
1243d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
1244d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
1245d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1246d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1247beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Test the bind configuration.
1248d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1249beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in] pPort        Address of the ::ESL_PORT structure.
1250beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in] ErrnoValue   errno value if test fails
1251d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1252a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS   The connection was successfully established.
1253a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval Others        The connection attempt failed.
1254beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
1255d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
1256a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketBindTest (
1257a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort,
1258a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN int ErrnoValue
1259d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
1260d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
1261a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINT8 * pBuffer;
1262a88c31639bb24c73383a4528a5b77066e805148blpleahy  VOID * pConfigData;
1263d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
1264d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1265d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
1266d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1267d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1268a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Locate the configuration data
1269d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1270a88c31639bb24c73383a4528a5b77066e805148blpleahy  pBuffer = (UINT8 *)pPort;
1271a88c31639bb24c73383a4528a5b77066e805148blpleahy  pBuffer = &pBuffer [ pPort->pSocket->pApi->ConfigDataOffset ];
1272a88c31639bb24c73383a4528a5b77066e805148blpleahy  pConfigData = (VOID *)pBuffer;
1273d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1274d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
12752dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  //  Validate that the port is connected
1276d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
12772dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy  Status = pPort->pSocket->pApi->pfnVerifyLocalIpAddress ( pPort, pBuffer );
1278a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( EFI_ERROR ( Status )) {
1279a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_WARN | DEBUG_BIND,
12802dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy              "WARNING - Port 0x%08x invalid IP address: %r\r\n",
1281a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort,
1282a88c31639bb24c73383a4528a5b77066e805148blpleahy              Status ));
1283a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->pSocket->errno = ErrnoValue;
1284a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
1285a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
1286a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
12872dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    //  Attempt to use this configuration
1288a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
12892dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    Status = pPort->pfnConfigure ( pPort->pProtocol.v, pConfigData );
1290a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( EFI_ERROR ( Status )) {
12912dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      DEBUG (( DEBUG_WARN | DEBUG_BIND,
12922dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                "WARNING - Port 0x%08x failed configuration, Status: %r\r\n",
1293a88c31639bb24c73383a4528a5b77066e805148blpleahy                pPort,
1294a88c31639bb24c73383a4528a5b77066e805148blpleahy                Status ));
12952dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      pPort->pSocket->errno = ErrnoValue;
12962dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    }
12972dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy    else {
12982dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      //
12992dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      //  Reset the port
13002dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      //
13012dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      Status = pPort->pfnConfigure ( pPort->pProtocol.v, NULL );
13022dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      if ( EFI_ERROR ( Status )) {
13032dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy        DEBUG (( DEBUG_ERROR | DEBUG_BIND,
13042dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                  "ERROR - Port 0x%08x failed configuration reset, Status: %r\r\n",
13052dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                  pPort,
13062dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                  Status ));
13072dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy        ASSERT ( EFI_SUCCESS == Status );
13082dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      }
1309a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
1310a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
1311d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1312d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1313a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
1314d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1315a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
1316a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
1317a88c31639bb24c73383a4528a5b77066e805148blpleahy}
1318a88c31639bb24c73383a4528a5b77066e805148blpleahy
1319a88c31639bb24c73383a4528a5b77066e805148blpleahy
1320beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Determine if the socket is closed.
1321a88c31639bb24c73383a4528a5b77066e805148blpleahy
1322a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine checks the state of the socket to determine if
1323a88c31639bb24c73383a4528a5b77066e805148blpleahy  the network specific layer has completed the close operation.
1324a88c31639bb24c73383a4528a5b77066e805148blpleahy
1325a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::close routine polls this routine to determine when the
1326a88c31639bb24c73383a4528a5b77066e805148blpleahy  close operation is complete.  The close operation needs to
1327a88c31639bb24c73383a4528a5b77066e805148blpleahy  reverse the operations of the ::EslSocketAllocate routine.
1328a88c31639bb24c73383a4528a5b77066e805148blpleahy
1329beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
1330beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out] pErrno          Address to receive the errno value upon completion.
1331a88c31639bb24c73383a4528a5b77066e805148blpleahy
1332a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS     Socket successfully closed
1333a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_NOT_READY   Close still in progress
1334a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_ALREADY     Close operation already in progress
1335a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval Other           Failed to close the socket
1336a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
1337a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
1338a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketClosePoll (
1339a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
1340a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN int * pErrno
1341a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
1342a88c31639bb24c73383a4528a5b77066e805148blpleahy{
1343a88c31639bb24c73383a4528a5b77066e805148blpleahy  int errno;
1344a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_LAYER * pLayer;
1345a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pNextSocket;
1346a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
1347a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
1348a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_TPL TplPrevious;
1349a88c31639bb24c73383a4528a5b77066e805148blpleahy
1350a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
1351a88c31639bb24c73383a4528a5b77066e805148blpleahy
1352a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1353a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Assume success
1354a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1355a88c31639bb24c73383a4528a5b77066e805148blpleahy  errno = 0;
1356a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
1357a88c31639bb24c73383a4528a5b77066e805148blpleahy
1358a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1359a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Synchronize with the socket layer
1360a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1361a88c31639bb24c73383a4528a5b77066e805148blpleahy  RAISE_TPL ( TplPrevious, TPL_SOCKETS );
1362a88c31639bb24c73383a4528a5b77066e805148blpleahy
1363a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1364a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Locate the socket
1365a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1366a88c31639bb24c73383a4528a5b77066e805148blpleahy  pLayer = &mEslLayer;
1367a88c31639bb24c73383a4528a5b77066e805148blpleahy  pNextSocket = pLayer->pSocketList;
1368d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
1369d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  while ( NULL != pNextSocket ) {
1370d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( pNextSocket == pSocket ) {
1371d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1372d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Determine if the socket is in the closing state
1373d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1374d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      if ( SOCKET_STATE_CLOSED == pSocket->State ) {
1375d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1376d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //  Walk the list of ports
1377d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1378d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        if ( NULL == pSocket->pPortList ) {
1379d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
1380d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //  All the ports are closed
1381d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //  Close the WaitAccept event if necessary
1382d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
1383d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          if ( NULL != pSocket->WaitAccept ) {
1384d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            Status = gBS->CloseEvent ( pSocket->WaitAccept );
1385d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            if ( !EFI_ERROR ( Status )) {
1386d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              DEBUG (( DEBUG_SOCKET | DEBUG_CLOSE | DEBUG_POOL,
1387d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                        "0x%08x: Closed WaitAccept event\r\n",
1388d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                        pSocket->WaitAccept ));
1389d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              //
1390d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              //  Return the transmit status
1391d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              //
1392d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              Status = pSocket->TxError;
1393d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              if ( EFI_ERROR ( Status )) {
1394d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                pSocket->errno = EIO;
1395d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              }
1396d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            }
1397d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            else {
1398d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              DEBUG (( DEBUG_ERROR | DEBUG_SOCKET | DEBUG_CLOSE | DEBUG_POOL,
1399d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                        "ERROR - Failed to close the WaitAccept event, Status: %r\r\n",
1400d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                        Status ));
1401d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              ASSERT ( EFI_SUCCESS == Status );
1402d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            }
1403d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          }
1404d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
1405d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        else {
1406d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
1407d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //  At least one port is still open
1408d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
1409d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          Status = EFI_NOT_READY;
1410d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          errno = EAGAIN;
1411d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
1412d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
1413d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      else {
1414d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1415d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //  SocketCloseStart was not called
1416d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1417d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        Status = EFI_NOT_STARTED;
1418d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        errno = EPERM;
1419d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
1420d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      break;
1421d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1422d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1423d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1424d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Set the next socket
1425d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1426d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pNextSocket = pNextSocket->pNext;
1427d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1428d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1429d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1430d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Handle the error case where the socket was already closed
1431d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1432d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL == pSocket ) {
1433d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1434d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Socket not found
1435d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1436d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    Status = EFI_NOT_FOUND;
1437d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    errno = ENOTSOCK;
1438d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1439d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1440d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1441d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Release the socket layer synchronization
1442d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1443d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  RESTORE_TPL ( TplPrevious );
1444d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1445d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1446d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
1447d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1448d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pErrno ) {
1449d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    *pErrno = errno;
1450d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1451d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
1452d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
1453d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
1454d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1455d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1456beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Start the close operation on the socket.
1457d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1458a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine calls the network specific layer to initiate the
1459a88c31639bb24c73383a4528a5b77066e805148blpleahy  close state machine.  This routine then calls the network
1460a88c31639bb24c73383a4528a5b77066e805148blpleahy  specific layer to determine if the close state machine has gone
1461a88c31639bb24c73383a4528a5b77066e805148blpleahy  to completion.  The result from this poll is returned to the
1462a88c31639bb24c73383a4528a5b77066e805148blpleahy  caller.
1463d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1464a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::close routine calls this routine to start the close
1465a88c31639bb24c73383a4528a5b77066e805148blpleahy  operation which reverses the operations of the
1466a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::EslSocketAllocate routine.  The close routine then polls
1467a88c31639bb24c73383a4528a5b77066e805148blpleahy  the ::EslSocketClosePoll routine to determine when the
1468a88c31639bb24c73383a4528a5b77066e805148blpleahy  socket is closed.
1469a88c31639bb24c73383a4528a5b77066e805148blpleahy
1470beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in] pSocketProtocol  Address of an ::EFI_SOCKET_PROTOCOL structure.
1471beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in] bCloseNow        Boolean to control close behavior
1472beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out] pErrno          Address to receive the errno value upon completion.
1473d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1474d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_SUCCESS     Socket successfully closed
1475d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_NOT_READY   Close still in progress
1476d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_ALREADY     Close operation already in progress
1477d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval Other           Failed to close the socket
1478d7ce700605e1af0e455e31ec11f19ff21d26b525darylm**/
1479d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
1480d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEslSocketCloseStart (
1481d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
1482d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN BOOLEAN bCloseNow,
1483d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int * pErrno
1484d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
1485d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
1486d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  int errno;
1487a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pNextPort;
1488a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
1489a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
1490d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
1491d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_TPL TplPrevious;
1492d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1493d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
1494d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1495d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1496d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Assume success
1497d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1498d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Status = EFI_SUCCESS;
1499d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  errno = 0;
1500d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1501d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1502d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Synchronize with the socket layer
1503d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1504d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  RAISE_TPL ( TplPrevious, TPL_SOCKETS );
1505d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1506d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1507d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Determine if the socket is already closed
1508d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1509d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
1510d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( SOCKET_STATE_CLOSED > pSocket->State ) {
1511d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1512d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Update the socket state
1513d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1514d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket->State = SOCKET_STATE_CLOSED;
1515d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1516d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1517d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Walk the list of ports
1518d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1519d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pPort = pSocket->pPortList;
1520d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    while ( NULL != pPort ) {
1521d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1522d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Start closing the ports
1523d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1524d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      pNextPort = pPort->pLinkSocket;
1525a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EslSocketPortCloseStart ( pPort,
1526a88c31639bb24c73383a4528a5b77066e805148blpleahy                                         bCloseNow,
1527a88c31639bb24c73383a4528a5b77066e805148blpleahy                                         DEBUG_CLOSE | DEBUG_LISTEN | DEBUG_CONNECTION );
1528d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      if (( EFI_SUCCESS != Status )
1529d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        && ( EFI_NOT_READY != Status )) {
1530d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        errno = EIO;
1531d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        break;
1532d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
1533d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1534d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1535d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Set the next port
1536d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1537d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      pPort = pNextPort;
1538d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1539d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1540d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1541d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Attempt to finish closing the socket
1542d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1543d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( NULL == pPort ) {
1544d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EslSocketClosePoll ( pSocketProtocol, &errno );
1545d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1546d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1547d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  else {
1548a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = EFI_NOT_READY;
1549a88c31639bb24c73383a4528a5b77066e805148blpleahy    errno = EAGAIN;
1550d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1551d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1552d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1553d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Release the socket layer synchronization
1554d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1555d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  RESTORE_TPL ( TplPrevious );
1556d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1557d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1558d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
1559d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1560d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pErrno ) {
1561d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    *pErrno = errno;
1562d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1563d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
1564d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
1565d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
1566d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1567d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1568beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Connect to a remote system via the network.
1569d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1570a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine calls the network specific layer to establish
1571a88c31639bb24c73383a4528a5b77066e805148blpleahy  the remote system address and establish the connection to
1572a88c31639bb24c73383a4528a5b77066e805148blpleahy  the remote system.
1573d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1574a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::connect routine calls this routine to establish a
1575a88c31639bb24c73383a4528a5b77066e805148blpleahy  connection with the specified remote system.  This routine
1576a88c31639bb24c73383a4528a5b77066e805148blpleahy  is designed to be polled by the connect routine for completion
1577a88c31639bb24c73383a4528a5b77066e805148blpleahy  of the network connection.
15780164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
1579beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
1580beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSockAddr       Network address of the remote system.
1581beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  SockAddrLength  Length in bytes of the network address.
1582beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out] pErrno          Address to receive the errno value upon completion.
1583d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1584beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @retval EFI_SUCCESS     The connection was successfully established.
1585beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @retval EFI_NOT_READY   The connection is in progress, call this routine again.
1586beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @retval Others          The connection attempt failed.
1587d7ce700605e1af0e455e31ec11f19ff21d26b525darylm **/
1588d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
1589d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEslSocketConnect (
1590d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
1591d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN const struct sockaddr * pSockAddr,
1592d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN socklen_t SockAddrLength,
1593d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int * pErrno
1594d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
1595d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
1596a88c31639bb24c73383a4528a5b77066e805148blpleahy  struct sockaddr_in6 LocalAddress;
1597a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
1598a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
1599d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
1600d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_TPL TplPrevious;
16010164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
1602d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DEBUG (( DEBUG_CONNECT, "Entering SocketConnect\r\n" ));
1603d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1604d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1605d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Assume success
1606d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1607d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Status = EFI_SUCCESS;
1608d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1609d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1610d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Validate the socket
1611d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1612d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pSocket = NULL;
1613d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pSocketProtocol ) {
1614d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
1615d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1616d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1617d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Validate the name length
1618d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1619a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( SockAddrLength < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data ))) {
1620d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      DEBUG (( DEBUG_CONNECT,
1621a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - Invalid bind name length: %d\r\n",
1622a88c31639bb24c73383a4528a5b77066e805148blpleahy                SockAddrLength ));
1623d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EFI_INVALID_PARAMETER;
1624d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      pSocket->errno = EINVAL;
1625d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1626d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    else {
1627d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1628d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Assume success
1629d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1630d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      pSocket->errno = 0;
1631d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1632d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1633d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Synchronize with the socket layer
1634d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1635d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      RAISE_TPL ( TplPrevious, TPL_SOCKETS );
1636d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1637d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1638d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Validate the socket state
1639d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1640d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      switch ( pSocket->State ) {
1641d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      default:
1642d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1643d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //  Wrong socket state
1644d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1645d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        pSocket->errno = EIO;
1646d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        Status = EFI_DEVICE_ERROR;
1647d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        break;
1648d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1649d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      case SOCKET_STATE_NOT_CONFIGURED:
1650d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      case SOCKET_STATE_BOUND:
1651d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1652a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Validate the address length
1653d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1654a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( SockAddrLength >= pSocket->pApi->MinimumAddressLength ) {
1655d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
1656a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Verify the API
1657d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
1658a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( NULL == pSocket->pApi->pfnRemoteAddrSet ) {
1659d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
1660a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Already connected
1661d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
1662a88c31639bb24c73383a4528a5b77066e805148blpleahy            pSocket->errno = ENOTSUP;
1663a88c31639bb24c73383a4528a5b77066e805148blpleahy            Status = EFI_UNSUPPORTED;
1664a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
1665a88c31639bb24c73383a4528a5b77066e805148blpleahy          else {
1666d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
1667a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Determine if BIND was already called
1668d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
1669a88c31639bb24c73383a4528a5b77066e805148blpleahy            if ( NULL == pSocket->pPortList ) {
1670a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
1671a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Allow any local port
1672a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
1673a88c31639bb24c73383a4528a5b77066e805148blpleahy              ZeroMem ( &LocalAddress, sizeof ( LocalAddress ));
1674a88c31639bb24c73383a4528a5b77066e805148blpleahy              LocalAddress.sin6_len = (uint8_t)pSocket->pApi->MinimumAddressLength;
1675a88c31639bb24c73383a4528a5b77066e805148blpleahy              LocalAddress.sin6_family = pSocket->pApi->AddressFamily;
1676a88c31639bb24c73383a4528a5b77066e805148blpleahy              Status = EslSocketBind ( &pSocket->SocketProtocol,
1677a88c31639bb24c73383a4528a5b77066e805148blpleahy                                       (struct sockaddr *)&LocalAddress,
1678a88c31639bb24c73383a4528a5b77066e805148blpleahy                                       LocalAddress.sin6_len,
1679a88c31639bb24c73383a4528a5b77066e805148blpleahy                                       &pSocket->errno );
1680d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            }
1681a88c31639bb24c73383a4528a5b77066e805148blpleahy            if ( NULL != pSocket->pPortList ) {
1682a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
1683a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Walk the list of ports
1684a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
1685a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort = pSocket->pPortList;
1686a88c31639bb24c73383a4528a5b77066e805148blpleahy              while ( NULL != pPort ) {
1687a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
1688a88c31639bb24c73383a4528a5b77066e805148blpleahy                //  Set the remote address
1689a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
1690a88c31639bb24c73383a4528a5b77066e805148blpleahy                Status = pSocket->pApi->pfnRemoteAddrSet ( pPort,
1691a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                           pSockAddr,
1692a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                           SockAddrLength );
1693a88c31639bb24c73383a4528a5b77066e805148blpleahy                if ( EFI_ERROR ( Status )) {
1694a88c31639bb24c73383a4528a5b77066e805148blpleahy                  break;
1695a88c31639bb24c73383a4528a5b77066e805148blpleahy                }
1696d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1697a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
1698a88c31639bb24c73383a4528a5b77066e805148blpleahy                //  Set the next port
1699a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
1700a88c31639bb24c73383a4528a5b77066e805148blpleahy                pPort = pPort->pLinkSocket;
1701a88c31639bb24c73383a4528a5b77066e805148blpleahy              }
1702a88c31639bb24c73383a4528a5b77066e805148blpleahy
1703a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
1704a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Verify the API
1705a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
1706a88c31639bb24c73383a4528a5b77066e805148blpleahy              if (( !EFI_ERROR ( Status ))
1707a88c31639bb24c73383a4528a5b77066e805148blpleahy                && ( NULL != pSocket->pApi->pfnConnectStart )) {
1708a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
1709a88c31639bb24c73383a4528a5b77066e805148blpleahy                //  Initiate the connection with the remote system
1710a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
1711a88c31639bb24c73383a4528a5b77066e805148blpleahy                Status = pSocket->pApi->pfnConnectStart ( pSocket );
1712a88c31639bb24c73383a4528a5b77066e805148blpleahy
1713a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
1714a88c31639bb24c73383a4528a5b77066e805148blpleahy                //  Set the next state if connecting
1715a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
1716a88c31639bb24c73383a4528a5b77066e805148blpleahy                if ( EFI_NOT_READY == Status ) {
1717a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pSocket->State = SOCKET_STATE_CONNECTING;
1718a88c31639bb24c73383a4528a5b77066e805148blpleahy                }
1719a88c31639bb24c73383a4528a5b77066e805148blpleahy              }
1720a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
1721d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          }
1722a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
1723a88c31639bb24c73383a4528a5b77066e805148blpleahy        else {
1724a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_CONNECT,
1725a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "ERROR - Invalid address length: %d\r\n",
1726a88c31639bb24c73383a4528a5b77066e805148blpleahy                    SockAddrLength ));
1727a88c31639bb24c73383a4528a5b77066e805148blpleahy          Status = EFI_INVALID_PARAMETER;
1728a88c31639bb24c73383a4528a5b77066e805148blpleahy          pSocket->errno = EINVAL;
1729d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
1730d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        break;
1731d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1732d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      case SOCKET_STATE_CONNECTING:
1733d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
173410e726cf65ea22c0097e62c4b019db6a19e06e68lpleahy        //  Poll the network adapter
173510e726cf65ea22c0097e62c4b019db6a19e06e68lpleahy        //
173610e726cf65ea22c0097e62c4b019db6a19e06e68lpleahy        EslSocketRxPoll ( pSocket );
173710e726cf65ea22c0097e62c4b019db6a19e06e68lpleahy
173810e726cf65ea22c0097e62c4b019db6a19e06e68lpleahy        //
1739a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Poll for connection completion
1740d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1741a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( NULL == pSocket->pApi->pfnConnectPoll ) {
1742d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
1743a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Already connected
1744d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
1745a88c31639bb24c73383a4528a5b77066e805148blpleahy          pSocket->errno = EISCONN;
1746a88c31639bb24c73383a4528a5b77066e805148blpleahy          Status = EFI_ALREADY_STARTED;
1747a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
1748a88c31639bb24c73383a4528a5b77066e805148blpleahy        else {
1749a88c31639bb24c73383a4528a5b77066e805148blpleahy          Status = pSocket->pApi->pfnConnectPoll ( pSocket );
1750d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1751a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
1752a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Set the next state if connected
1753a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
1754a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( EFI_NOT_READY != Status ) {
1755ceecdc62ab73e5b726630345865a512c780c134elpleahy  leroy.p.leahy <lpleahy            if ( EFI_ERROR ( Status )) {
1756a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket->State = SOCKET_STATE_BOUND;
1757d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            }
1758d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          }
1759d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
1760d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        break;
1761d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1762d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      case SOCKET_STATE_CONNECTED:
1763d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1764eb5b60155a30428c12acd0b2c49b54159a4e55e8leroy.p.leahy        //  Connected
1765d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
1766eb5b60155a30428c12acd0b2c49b54159a4e55e8leroy.p.leahy        Status = EFI_SUCCESS;
1767d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        break;
1768d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
1769d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1770d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1771d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Release the socket layer synchronization
1772d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1773d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      RESTORE_TPL ( TplPrevious );
1774d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1775d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1776d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1777d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1778d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
1779d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1780d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pErrno ) {
1781d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( NULL != pSocket ) {
1782d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      *pErrno = pSocket->errno;
1783d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1784a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
1785d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1786d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Bad socket protocol
1787d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
1788d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      DEBUG (( DEBUG_ERROR | DEBUG_CONNECT,
1789d7ce700605e1af0e455e31ec11f19ff21d26b525darylm                "ERROR - pSocketProtocol invalid!\r\n" ));
1790d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EFI_INVALID_PARAMETER;
1791a88c31639bb24c73383a4528a5b77066e805148blpleahy      *pErrno = ENOTSOCK;
1792d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1793d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1794d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1795d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1796d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
1797d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1798d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DEBUG (( DEBUG_CONNECT, "Exiting SocketConnect, Status: %r\r\n", Status ));
1799d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
1800d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
1801d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1802d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1803beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Copy a fragmented buffer into a destination buffer.
1804d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1805a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support routine copies a fragmented buffer to the caller specified buffer.
1806d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1807a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by ::EslIp4Receive and ::EslUdp4Receive.
1808d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1809beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  FragmentCount   Number of fragments in the table
1810beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pFragmentTable  Address of an EFI_IP4_FRAGMENT_DATA structure
1811beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  BufferLength    Length of the the buffer
1812beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pBuffer         Address of a buffer to receive the data.
1813beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pDataLength     Number of received data bytes in the buffer.
1814d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1815a88c31639bb24c73383a4528a5b77066e805148blpleahy  @return   Returns the address of the next free byte in the buffer.
1816d7ce700605e1af0e455e31ec11f19ff21d26b525darylm**/
1817a88c31639bb24c73383a4528a5b77066e805148blpleahyUINT8 *
1818a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketCopyFragmentedBuffer (
1819a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN UINT32 FragmentCount,
1820a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN EFI_IP4_FRAGMENT_DATA * pFragmentTable,
1821a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN size_t BufferLength,
1822a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN UINT8 * pBuffer,
1823a88c31639bb24c73383a4528a5b77066e805148blpleahy  OUT size_t * pDataLength
1824d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
1825d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
1826a88c31639bb24c73383a4528a5b77066e805148blpleahy  size_t BytesToCopy;
1827a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINT32 Fragment;
1828a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINT8 * pBufferEnd;
1829a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINT8 * pData;
1830d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1831d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
1832d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1833d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1834a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Validate the IP and UDP structures are identical
1835d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1836a88c31639bb24c73383a4528a5b77066e805148blpleahy  ASSERT ( OFFSET_OF ( EFI_IP4_FRAGMENT_DATA, FragmentLength )
1837a88c31639bb24c73383a4528a5b77066e805148blpleahy           == OFFSET_OF ( EFI_UDP4_FRAGMENT_DATA, FragmentLength ));
1838a88c31639bb24c73383a4528a5b77066e805148blpleahy  ASSERT ( OFFSET_OF ( EFI_IP4_FRAGMENT_DATA, FragmentBuffer )
1839a88c31639bb24c73383a4528a5b77066e805148blpleahy           == OFFSET_OF ( EFI_UDP4_FRAGMENT_DATA, FragmentBuffer ));
1840d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1841a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1842a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Copy the received data
1843a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
1844a88c31639bb24c73383a4528a5b77066e805148blpleahy  Fragment = 0;
1845a88c31639bb24c73383a4528a5b77066e805148blpleahy  pBufferEnd = &pBuffer [ BufferLength ];
1846a88c31639bb24c73383a4528a5b77066e805148blpleahy  while (( pBufferEnd > pBuffer ) && ( FragmentCount > Fragment )) {
1847d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1848a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Determine the amount of received data
1849d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1850a88c31639bb24c73383a4528a5b77066e805148blpleahy    pData = pFragmentTable[Fragment].FragmentBuffer;
1851a88c31639bb24c73383a4528a5b77066e805148blpleahy    BytesToCopy = pFragmentTable[Fragment].FragmentLength;
1852a88c31639bb24c73383a4528a5b77066e805148blpleahy    if (((size_t)( pBufferEnd - pBuffer )) < BytesToCopy ) {
1853a88c31639bb24c73383a4528a5b77066e805148blpleahy      BytesToCopy = pBufferEnd - pBuffer;
1854d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
1855d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1856d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1857a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Move the data into the buffer
1858d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
1859a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_RX,
1860a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x --> 0x%08x: Copy data 0x%08x bytes\r\n",
1861a88c31639bb24c73383a4528a5b77066e805148blpleahy              pData,
1862a88c31639bb24c73383a4528a5b77066e805148blpleahy              pBuffer,
1863a88c31639bb24c73383a4528a5b77066e805148blpleahy              BytesToCopy ));
1864a88c31639bb24c73383a4528a5b77066e805148blpleahy    CopyMem ( pBuffer, pData, BytesToCopy );
1865a88c31639bb24c73383a4528a5b77066e805148blpleahy    pBuffer += BytesToCopy;
1866a88c31639bb24c73383a4528a5b77066e805148blpleahy    Fragment += 1;
1867d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
1868d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1869d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1870a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the data length and the buffer address
1871d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
1872a88c31639bb24c73383a4528a5b77066e805148blpleahy  *pDataLength = BufferLength - ( pBufferEnd - pBuffer );
1873a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_HEX ( pBuffer );
1874a88c31639bb24c73383a4528a5b77066e805148blpleahy  return pBuffer;
1875d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
1876d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1877d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
1878beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Free the socket.
18794652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
18804652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  This routine frees the socket structure and handle resources.
18814652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
18824652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  The ::close routine calls EslServiceFreeProtocol which then calls
18834652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  this routine to free the socket context structure and close the
18844652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  handle.
18854652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
1886beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
1887beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out] pErrno          Address to receive the errno value upon completion.
18884652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
18894652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  @retval EFI_SUCCESS   The socket resources were returned successfully.
1890beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
18914652be0c5a106d0604c2d3274803fc0f844b0433lpleahyEFI_STATUS
18924652be0c5a106d0604c2d3274803fc0f844b0433lpleahyEslSocketFree (
18934652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
18944652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  IN int * pErrno
18954652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  )
18964652be0c5a106d0604c2d3274803fc0f844b0433lpleahy{
18974652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  EFI_HANDLE ChildHandle;
18984652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  int errno;
18994652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  ESL_LAYER * pLayer;
19004652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  ESL_SOCKET * pSocket;
19014652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  ESL_SOCKET * pSocketPrevious;
19024652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  EFI_STATUS Status;
19034652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  EFI_TPL TplPrevious;
19044652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
19054652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  DBG_ENTER ( );
19064652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
19074652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  //
19084652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  //  Assume failure
19094652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  //
19104652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  errno = EIO;
19114652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  pSocket = NULL;
19124652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  Status = EFI_INVALID_PARAMETER;
19134652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
19144652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  //
19154652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  //  Validate the socket
19164652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  //
19174652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  pLayer = &mEslLayer;
19184652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  if ( NULL != pSocketProtocol ) {
19194652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
19204652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
19214652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    //
19224652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    //  Synchronize with the socket layer
19234652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    //
19244652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    RAISE_TPL ( TplPrevious, TPL_SOCKETS );
19254652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
19264652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    //
19274652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    //  Walk the socket list
19284652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    //
19294652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    pSocketPrevious = pLayer->pSocketList;
19304652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    if ( NULL != pSocketPrevious ) {
19314652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      if ( pSocket == pSocketPrevious ) {
19324652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        //
19334652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        //  Remove the socket from the head of the list
19344652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        //
19354652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        pLayer->pSocketList = pSocket->pNext;
19364652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      }
19374652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      else {
19384652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        //
19394652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        //  Find the socket in the middle of the list
19404652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        //
19414652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        while (( NULL != pSocketPrevious )
19424652be0c5a106d0604c2d3274803fc0f844b0433lpleahy          && ( pSocket != pSocketPrevious->pNext )) {
19434652be0c5a106d0604c2d3274803fc0f844b0433lpleahy          //
19444652be0c5a106d0604c2d3274803fc0f844b0433lpleahy          //  Set the next socket
19454652be0c5a106d0604c2d3274803fc0f844b0433lpleahy          //
19464652be0c5a106d0604c2d3274803fc0f844b0433lpleahy          pSocketPrevious = pSocketPrevious->pNext;
19474652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        }
19484652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        if ( NULL != pSocketPrevious ) {
19494652be0c5a106d0604c2d3274803fc0f844b0433lpleahy          //
19504652be0c5a106d0604c2d3274803fc0f844b0433lpleahy          //  Remove the socket from the middle of the list
19514652be0c5a106d0604c2d3274803fc0f844b0433lpleahy          //
19524652be0c5a106d0604c2d3274803fc0f844b0433lpleahy          pSocketPrevious = pSocket->pNext;
19534652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        }
19544652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      }
19554652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    }
19564652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    else {
19574652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      DEBUG (( DEBUG_ERROR | DEBUG_POOL,
19584652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                "ERROR - Socket list is empty!\r\n" ));
19594652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    }
19604652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
19614652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    //
19624652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    //  Release the socket layer synchronization
19634652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    //
19644652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    RESTORE_TPL ( TplPrevious );
19654652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
19664652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    //
19674652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    //  Determine if the socket was found
19684652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    //
19694652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    if ( NULL != pSocketPrevious ) {
19704652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      pSocket->pNext = NULL;
19714652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
19724652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      //
19734652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      //  Remove the socket protocol
19744652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      //
19754652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      ChildHandle = pSocket->SocketProtocol.SocketHandle;
19764652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      Status = gBS->UninstallMultipleProtocolInterfaces (
19774652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                ChildHandle,
19784652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                &gEfiSocketProtocolGuid,
19794652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                &pSocket->SocketProtocol,
19804652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                NULL );
19814652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      if ( !EFI_ERROR ( Status )) {
19824652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        DEBUG (( DEBUG_POOL | DEBUG_INFO,
19834652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                    "Removed:   gEfiSocketProtocolGuid from 0x%08x\r\n",
19844652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                    ChildHandle ));
19854652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
19864652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        //
19874652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        //  Free the socket structure
19884652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        //
19894652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        Status = gBS->FreePool ( pSocket );
19904652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        if ( !EFI_ERROR ( Status )) {
19914652be0c5a106d0604c2d3274803fc0f844b0433lpleahy          DEBUG (( DEBUG_POOL,
19924652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                    "0x%08x: Free pSocket, %d bytes\r\n",
19934652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                    pSocket,
19944652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                    sizeof ( *pSocket )));
19954652be0c5a106d0604c2d3274803fc0f844b0433lpleahy          errno = 0;
19964652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        }
19974652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        else {
19984652be0c5a106d0604c2d3274803fc0f844b0433lpleahy          DEBUG (( DEBUG_ERROR | DEBUG_POOL,
19994652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                    "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",
20004652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                    pSocket,
20014652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                    Status ));
20024652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        }
20034652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      }
20044652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      else {
20054652be0c5a106d0604c2d3274803fc0f844b0433lpleahy        DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,
20064652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                    "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",
20074652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                    ChildHandle,
20084652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                    Status ));
20094652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      }
20104652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    }
20114652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    else {
20124652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      DEBUG (( DEBUG_ERROR | DEBUG_INFO,
20134652be0c5a106d0604c2d3274803fc0f844b0433lpleahy                "ERROR - The socket was not in the socket list!\r\n" ));
20144652be0c5a106d0604c2d3274803fc0f844b0433lpleahy      Status = EFI_NOT_FOUND;
20154652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    }
20164652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  }
20174652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  else {
20184652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    DEBUG (( DEBUG_ERROR,
20194652be0c5a106d0604c2d3274803fc0f844b0433lpleahy              "ERROR - Invalid parameter pSocketProtocol is NULL\r\n" ));
20204652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  }
20214652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
20224652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  //
20234652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  //  Return the errno value if possible
20244652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  //
20254652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  if ( NULL != pErrno ) {
20264652be0c5a106d0604c2d3274803fc0f844b0433lpleahy    *pErrno = errno;
20274652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  }
20284652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
20294652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  //
20304652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  //  Return the operation status
20314652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  //
20324652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  DBG_EXIT_STATUS ( Status );
20334652be0c5a106d0604c2d3274803fc0f844b0433lpleahy  return Status;
20344652be0c5a106d0604c2d3274803fc0f844b0433lpleahy}
20354652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
20364652be0c5a106d0604c2d3274803fc0f844b0433lpleahy
2037beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Get the local address.
2038d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2039a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine calls the network specific layer to get the network
2040a88c31639bb24c73383a4528a5b77066e805148blpleahy  address of the local host connection point.
2041a88c31639bb24c73383a4528a5b77066e805148blpleahy
2042a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::getsockname routine calls this routine to obtain the network
2043a88c31639bb24c73383a4528a5b77066e805148blpleahy  address associated with the local host connection point.
2044a88c31639bb24c73383a4528a5b77066e805148blpleahy
2045beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
2046beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out]     pAddress        Network address to receive the local system address
2047beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in,out]  pAddressLength  Length of the local network address structure
2048beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out]     pErrno          Address to receive the errno value upon completion.
2049d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2050d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_SUCCESS - Local address successfully returned
2051d7ce700605e1af0e455e31ec11f19ff21d26b525darylm **/
2052d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
2053d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEslSocketGetLocalAddress (
2054d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
2055d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  OUT struct sockaddr * pAddress,
2056d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN OUT socklen_t * pAddressLength,
2057d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int * pErrno
2058d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
2059d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
2060a88c31639bb24c73383a4528a5b77066e805148blpleahy  socklen_t LengthInBytes;
2061a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
2062a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
2063d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
2064d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_TPL TplPrevious;
20650164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
2066d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
20670164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
2068d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2069d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Assume success
2070d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2071d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Status = EFI_SUCCESS;
20720164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
2073d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2074d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Validate the socket
2075d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2076d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pSocket = NULL;
2077d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pSocketProtocol ) {
2078d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
2079d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2080d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
2081a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Verify the socket state
2082d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
2083f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy    EslSocketIsConfigured ( pSocket );
2084f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy    if ( pSocket->bAddressSet ) {
2085d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
2086a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Verify the address buffer and length address
2087d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
2088a88c31639bb24c73383a4528a5b77066e805148blpleahy      if (( NULL != pAddress ) && ( NULL != pAddressLength )) {
2089d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
2090f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy        //  Verify the API
2091d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
2092f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy        if ( NULL == pSocket->pApi->pfnLocalAddrGet ) {
2093f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          Status = EFI_UNSUPPORTED;
2094f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          pSocket->errno = ENOTSUP;
2095f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy        }
2096f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy        else {
2097d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
2098f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          //  Synchronize with the socket layer
2099d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
2100f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          RAISE_TPL ( TplPrevious, TPL_SOCKETS );
2101d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2102f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          //
2103f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          //  Verify that there is just a single connection
2104f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          //
2105f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          pPort = pSocket->pPortList;
2106f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          if ( NULL != pPort ) {
2107d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
2108f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy            //  Verify the address length
2109d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
2110f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy            LengthInBytes = pSocket->pApi->AddressLength;
21110164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel            if (( LengthInBytes <= *pAddressLength )
2112f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy              && ( 255 >= LengthInBytes )) {
2113a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
2114f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy              //  Return the local address and address length
2115a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
2116f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy              ZeroMem ( pAddress, LengthInBytes );
2117f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy              pAddress->sa_len = (uint8_t)LengthInBytes;
2118f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy              *pAddressLength = pAddress->sa_len;
2119f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy              pSocket->pApi->pfnLocalAddrGet ( pPort, pAddress );
2120f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy              pSocket->errno = 0;
2121f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy              Status = EFI_SUCCESS;
2122a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
2123a88c31639bb24c73383a4528a5b77066e805148blpleahy            else {
2124f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy              pSocket->errno = EINVAL;
2125f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy              Status = EFI_INVALID_PARAMETER;
2126a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
2127d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          }
2128f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          else {
2129f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy            pSocket->errno = ENOTCONN;
2130f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy            Status = EFI_NOT_STARTED;
2131f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          }
21320164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
2133f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          //
2134f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          //  Release the socket layer synchronization
2135f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          //
2136f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          RESTORE_TPL ( TplPrevious );
2137a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
2138d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
2139d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      else {
2140a88c31639bb24c73383a4528a5b77066e805148blpleahy        pSocket->errno = EINVAL;
2141a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = EFI_INVALID_PARAMETER;
2142d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
2143d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
2144f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy    else {
2145f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy      //
2146f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy      //  Address not set
2147f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy      //
2148f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy      Status = EFI_NOT_STARTED;
2149f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy      pSocket->errno = EADDRNOTAVAIL;
2150f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy    }
2151d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
21520164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
2153d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2154d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
2155d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2156d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pErrno ) {
2157d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( NULL != pSocket ) {
2158d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      *pErrno = pSocket->errno;
2159d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
2160a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
2161d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EFI_INVALID_PARAMETER;
2162a88c31639bb24c73383a4528a5b77066e805148blpleahy      *pErrno = ENOTSOCK;
2163d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
2164d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
2165d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
2166d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
2167d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
2168d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2169d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2170beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Get the peer address.
2171d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2172a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine calls the network specific layer to get the remote
2173a88c31639bb24c73383a4528a5b77066e805148blpleahy  system connection point.
2174a88c31639bb24c73383a4528a5b77066e805148blpleahy
2175a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::getpeername routine calls this routine to obtain the network
2176a88c31639bb24c73383a4528a5b77066e805148blpleahy  address of the remote connection point.
2177a88c31639bb24c73383a4528a5b77066e805148blpleahy
2178beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      pSocketProtocol   Address of an ::EFI_SOCKET_PROTOCOL structure.
2179beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out]     pAddress          Network address to receive the remote system address
2180beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in,out]  pAddressLength    Length of the remote network address structure
2181beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out]     pErrno            Address to receive the errno value upon completion.
2182d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2183d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_SUCCESS - Remote address successfully returned
2184d7ce700605e1af0e455e31ec11f19ff21d26b525darylm **/
2185d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
2186d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEslSocketGetPeerAddress (
2187d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
2188d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  OUT struct sockaddr * pAddress,
2189d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN OUT socklen_t * pAddressLength,
2190d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int * pErrno
2191d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
2192d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
2193a88c31639bb24c73383a4528a5b77066e805148blpleahy  socklen_t LengthInBytes;
2194a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
2195a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
2196d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
2197d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_TPL TplPrevious;
21980164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
2199d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
22000164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
2201d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2202d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Assume success
2203d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2204d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Status = EFI_SUCCESS;
22050164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
2206d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2207d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Validate the socket
2208d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2209d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pSocket = NULL;
2210d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pSocketProtocol ) {
2211d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
2212d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2213d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
2214a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Verify the socket state
2215d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
2216a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = EslSocketIsConfigured ( pSocket );
2217a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( !EFI_ERROR ( Status )) {
2218d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
2219a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Verify the API
2220d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
2221a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( NULL == pSocket->pApi->pfnRemoteAddrGet ) {
2222a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = EFI_UNSUPPORTED;
2223a88c31639bb24c73383a4528a5b77066e805148blpleahy        pSocket->errno = ENOTSUP;
2224a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
2225a88c31639bb24c73383a4528a5b77066e805148blpleahy      else {
2226d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
2227a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Verify the address buffer and length address
2228d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
2229a88c31639bb24c73383a4528a5b77066e805148blpleahy        if (( NULL != pAddress ) && ( NULL != pAddressLength )) {
2230d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
2231a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Verify the socket state
2232d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
2233a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
2234a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
2235a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Synchronize with the socket layer
2236a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
2237a88c31639bb24c73383a4528a5b77066e805148blpleahy            RAISE_TPL ( TplPrevious, TPL_SOCKETS );
2238d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2239d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
2240a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Verify that there is just a single connection
2241d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
2242a88c31639bb24c73383a4528a5b77066e805148blpleahy            pPort = pSocket->pPortList;
2243a88c31639bb24c73383a4528a5b77066e805148blpleahy            if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {
2244a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
2245a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Verify the address length
2246a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
2247a88c31639bb24c73383a4528a5b77066e805148blpleahy              LengthInBytes = pSocket->pApi->AddressLength;
2248a88c31639bb24c73383a4528a5b77066e805148blpleahy              if ( LengthInBytes <= *pAddressLength ) {
2249a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
2250a88c31639bb24c73383a4528a5b77066e805148blpleahy                //  Return the local address
2251a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
2252a88c31639bb24c73383a4528a5b77066e805148blpleahy                ZeroMem ( pAddress, LengthInBytes );
2253a88c31639bb24c73383a4528a5b77066e805148blpleahy                pAddress->sa_len = (uint8_t)LengthInBytes;
2254a88c31639bb24c73383a4528a5b77066e805148blpleahy                *pAddressLength = pAddress->sa_len;
2255a88c31639bb24c73383a4528a5b77066e805148blpleahy                pSocket->pApi->pfnRemoteAddrGet ( pPort, pAddress );
2256a88c31639bb24c73383a4528a5b77066e805148blpleahy                pSocket->errno = 0;
2257a88c31639bb24c73383a4528a5b77066e805148blpleahy                Status = EFI_SUCCESS;
2258a88c31639bb24c73383a4528a5b77066e805148blpleahy              }
2259a88c31639bb24c73383a4528a5b77066e805148blpleahy              else {
2260a88c31639bb24c73383a4528a5b77066e805148blpleahy                pSocket->errno = EINVAL;
2261a88c31639bb24c73383a4528a5b77066e805148blpleahy                Status = EFI_INVALID_PARAMETER;
2262a88c31639bb24c73383a4528a5b77066e805148blpleahy              }
2263a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
2264a88c31639bb24c73383a4528a5b77066e805148blpleahy            else {
2265a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket->errno = ENOTCONN;
2266a88c31639bb24c73383a4528a5b77066e805148blpleahy              Status = EFI_NOT_STARTED;
2267a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
2268d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2269d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
2270a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Release the socket layer synchronization
2271d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
2272a88c31639bb24c73383a4528a5b77066e805148blpleahy            RESTORE_TPL ( TplPrevious );
2273a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
2274a88c31639bb24c73383a4528a5b77066e805148blpleahy          else {
2275a88c31639bb24c73383a4528a5b77066e805148blpleahy            pSocket->errno = ENOTCONN;
2276a88c31639bb24c73383a4528a5b77066e805148blpleahy            Status = EFI_NOT_STARTED;
2277d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          }
2278d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
2279a88c31639bb24c73383a4528a5b77066e805148blpleahy        else {
2280a88c31639bb24c73383a4528a5b77066e805148blpleahy          pSocket->errno = EINVAL;
2281a88c31639bb24c73383a4528a5b77066e805148blpleahy          Status = EFI_INVALID_PARAMETER;
2282a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
2283d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
2284d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
2285d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
2286a88c31639bb24c73383a4528a5b77066e805148blpleahy
2287d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2288d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
2289d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2290d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pErrno ) {
2291d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( NULL != pSocket ) {
2292d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      *pErrno = pSocket->errno;
2293d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
2294a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
2295d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EFI_INVALID_PARAMETER;
2296a88c31639bb24c73383a4528a5b77066e805148blpleahy      *pErrno = ENOTSOCK;
2297d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
2298d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
2299d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
2300d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
2301d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
2302d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2303d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2304beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Free the ESL_IO_MGMT event and structure.
2305d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2306a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support routine walks the free list to close the event in
2307a88c31639bb24c73383a4528a5b77066e805148blpleahy  the ESL_IO_MGMT structure and remove the structure from the free
2308a88c31639bb24c73383a4528a5b77066e805148blpleahy  list.
2309d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2310a88c31639bb24c73383a4528a5b77066e805148blpleahy  See the \ref TransmitEngine section.
2311d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2312beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pPort         Address of an ::ESL_PORT structure
2313beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  ppFreeQueue   Address of the free queue head
2314beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  DebugFlags    Flags for debug messages
2315beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pEventName    Zero terminated string containing the event name
2316d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2317a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - The structures were properly initialized
2318d7ce700605e1af0e455e31ec11f19ff21d26b525darylm**/
2319d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
2320a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketIoFree (
2321a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort,
2322a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_IO_MGMT ** ppFreeQueue,
2323a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN UINTN DebugFlags,
2324a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN CHAR8 * pEventName
2325d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
2326d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
2327a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINT8 * pBuffer;
2328a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_EVENT * pEvent;
2329a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IO_MGMT * pIo;
2330a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
2331d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
2332d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2333d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
2334d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2335d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2336d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Assume success
2337d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2338d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Status = EFI_SUCCESS;
2339d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2340d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2341a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Walk the list of IO structures
2342d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2343a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = pPort->pSocket;
2344a88c31639bb24c73383a4528a5b77066e805148blpleahy  while ( *ppFreeQueue ) {
2345d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
2346a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Free the event for this structure
2347d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
2348a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIo = *ppFreeQueue;
2349a88c31639bb24c73383a4528a5b77066e805148blpleahy    pBuffer = (UINT8 *)pIo;
2350a88c31639bb24c73383a4528a5b77066e805148blpleahy    pBuffer = &pBuffer[ pSocket->TxTokenEventOffset ];
2351a88c31639bb24c73383a4528a5b77066e805148blpleahy    pEvent = (EFI_EVENT *)pBuffer;
2352a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = gBS->CloseEvent ( *pEvent );
2353a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( EFI_ERROR ( Status )) {
2354a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_ERROR | DebugFlags,
2355a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - Failed to close the %a event, Status: %r\r\n",
2356a88c31639bb24c73383a4528a5b77066e805148blpleahy                pEventName,
2357a88c31639bb24c73383a4528a5b77066e805148blpleahy                Status ));
2358a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = ENOMEM;
2359a88c31639bb24c73383a4528a5b77066e805148blpleahy      break;
2360a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
2361a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DebugFlags,
2362a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Closed %a event 0x%08x\r\n",
2363a88c31639bb24c73383a4528a5b77066e805148blpleahy              pIo,
2364a88c31639bb24c73383a4528a5b77066e805148blpleahy              pEventName,
2365a88c31639bb24c73383a4528a5b77066e805148blpleahy              *pEvent ));
2366d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2367d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
2368a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Remove this structure from the queue
2369d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
2370a88c31639bb24c73383a4528a5b77066e805148blpleahy    *ppFreeQueue = pIo->pNext;
2371d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
2372d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2373d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2374d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
2375d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2376d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
2377d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
2378d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
2379d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2380d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2381beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Initialize the ESL_IO_MGMT structures.
2382d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2383a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support routine initializes the ESL_IO_MGMT structure and
2384a88c31639bb24c73383a4528a5b77066e805148blpleahy  places them on to a free list.
2385d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2386a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by ::EslSocketPortAllocate routines to prepare
2387a88c31639bb24c73383a4528a5b77066e805148blpleahy  the transmit engines.  See the \ref TransmitEngine section.
2388d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2389beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]        pPort         Address of an ::ESL_PORT structure
2390beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in, out]   ppIo          Address containing the first structure address.  Upon
2391beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                                  return this buffer contains the next structure address.
2392beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]        TokenCount    Number of structures to initialize
2393beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]        ppFreeQueue   Address of the free queue head
2394beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]        DebugFlags    Flags for debug messages
2395beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]        pEventName    Zero terminated string containing the event name
2396beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]        pfnCompletion Completion routine address
2397d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2398a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - The structures were properly initialized
2399a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
2400d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
2401a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketIoInit (
2402a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort,
2403a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_IO_MGMT ** ppIo,
2404a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN UINTN TokenCount,
2405a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_IO_MGMT ** ppFreeQueue,
2406a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN UINTN DebugFlags,
2407a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN CHAR8 * pEventName,
240858081f2c64fbc2f89ac5a9b47b2643c280bc8f99lpleahy  IN PFN_API_IO_COMPLETE pfnCompletion
2409d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
2410d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
2411a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IO_MGMT * pEnd;
2412a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_EVENT * pEvent;
2413a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IO_MGMT * pIo;
2414a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
2415d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
2416d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2417d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
2418d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2419d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2420a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Assume success
2421d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2422a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
2423d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2424d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2425a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Walk the list of IO structures
2426d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2427a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = pPort->pSocket;
2428a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIo = *ppIo;
2429a88c31639bb24c73383a4528a5b77066e805148blpleahy  pEnd = &pIo [ TokenCount ];
2430a88c31639bb24c73383a4528a5b77066e805148blpleahy  while ( pEnd > pIo ) {
2431a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
2432a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Initialize the IO structure
2433a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
2434a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIo->pPort = pPort;
2435a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIo->pPacket = NULL;
2436d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2437a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
2438a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Allocate the event for this structure
2439a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
2440a88c31639bb24c73383a4528a5b77066e805148blpleahy    pEvent = (EFI_EVENT *)&(((UINT8 *)pIo)[ pSocket->TxTokenEventOffset ]);
2441a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
2442a88c31639bb24c73383a4528a5b77066e805148blpleahy                                TPL_SOCKETS,
2443a88c31639bb24c73383a4528a5b77066e805148blpleahy                                (EFI_EVENT_NOTIFY)pfnCompletion,
2444a88c31639bb24c73383a4528a5b77066e805148blpleahy                                pIo,
2445a88c31639bb24c73383a4528a5b77066e805148blpleahy                                pEvent );
2446a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( EFI_ERROR ( Status )) {
2447a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_ERROR | DebugFlags,
2448a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - Failed to create the %a event, Status: %r\r\n",
2449a88c31639bb24c73383a4528a5b77066e805148blpleahy                pEventName,
2450a88c31639bb24c73383a4528a5b77066e805148blpleahy                Status ));
2451a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = ENOMEM;
2452d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      break;
2453d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
2454a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DebugFlags,
2455a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Created %a event 0x%08x\r\n",
2456a88c31639bb24c73383a4528a5b77066e805148blpleahy              pIo,
2457a88c31639bb24c73383a4528a5b77066e805148blpleahy              pEventName,
2458a88c31639bb24c73383a4528a5b77066e805148blpleahy              *pEvent ));
2459d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2460d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
2461a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Add this structure to the queue
2462d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
2463a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIo->pNext = *ppFreeQueue;
2464a88c31639bb24c73383a4528a5b77066e805148blpleahy    *ppFreeQueue = pIo;
2465d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2466d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
2467a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Set the next structure
2468d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
2469a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIo += 1;
2470a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
2471a88c31639bb24c73383a4528a5b77066e805148blpleahy
2472a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2473a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Save the next structure
2474a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2475a88c31639bb24c73383a4528a5b77066e805148blpleahy  *ppIo = pIo;
2476a88c31639bb24c73383a4528a5b77066e805148blpleahy
2477a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2478a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
2479a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2480a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
2481a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
2482a88c31639bb24c73383a4528a5b77066e805148blpleahy}
2483a88c31639bb24c73383a4528a5b77066e805148blpleahy
2484a88c31639bb24c73383a4528a5b77066e805148blpleahy
2485beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Determine if the socket is configured.
2486a88c31639bb24c73383a4528a5b77066e805148blpleahy
2487a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support routine is called to determine if the socket if the
2488a88c31639bb24c73383a4528a5b77066e805148blpleahy  configuration call was made to the network layer.  The following
2489a88c31639bb24c73383a4528a5b77066e805148blpleahy  routines call this routine to verify that they may be successful
2490a88c31639bb24c73383a4528a5b77066e805148blpleahy  in their operations:
2491a88c31639bb24c73383a4528a5b77066e805148blpleahy  <ul>
2492a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslSocketGetLocalAddress</li>
2493a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslSocketGetPeerAddress</li>
2494a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslSocketPoll</li>
2495a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslSocketReceive</li>
2496a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslSocketTransmit</li>
2497a88c31639bb24c73383a4528a5b77066e805148blpleahy  </ul>
2498a88c31639bb24c73383a4528a5b77066e805148blpleahy
2499beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSocket       Address of an ::ESL_SOCKET structure
2500a88c31639bb24c73383a4528a5b77066e805148blpleahy
2501a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - The socket is configured
2502a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
2503a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
2504a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketIsConfigured (
2505a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_SOCKET * pSocket
2506a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
2507a88c31639bb24c73383a4528a5b77066e805148blpleahy{
2508a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
2509a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_TPL TplPrevious;
2510a88c31639bb24c73383a4528a5b77066e805148blpleahy
2511a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2512a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Assume success
2513a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2514a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
2515a88c31639bb24c73383a4528a5b77066e805148blpleahy
2516a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2517a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Verify the socket state
2518a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2519a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( !pSocket->bConfigured ) {
2520a88c31639bb24c73383a4528a5b77066e805148blpleahy    DBG_ENTER ( );
2521a88c31639bb24c73383a4528a5b77066e805148blpleahy
2522a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
2523a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Verify the API
2524a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
2525a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( NULL == pSocket->pApi->pfnIsConfigured ) {
2526a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_UNSUPPORTED;
2527a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = ENOTSUP;
2528a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
2529a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
2530a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2531a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Synchronize with the socket layer
2532a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2533a88c31639bb24c73383a4528a5b77066e805148blpleahy      RAISE_TPL ( TplPrevious, TPL_SOCKETS );
2534a88c31639bb24c73383a4528a5b77066e805148blpleahy
2535a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2536a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Determine if the socket is configured
2537a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2538a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = pSocket->pApi->pfnIsConfigured ( pSocket );
2539a88c31639bb24c73383a4528a5b77066e805148blpleahy
2540a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2541a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Release the socket layer synchronization
2542a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2543a88c31639bb24c73383a4528a5b77066e805148blpleahy      RESTORE_TPL ( TplPrevious );
2544a88c31639bb24c73383a4528a5b77066e805148blpleahy
2545a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2546a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Set errno if a failure occurs
2547a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2548a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( EFI_ERROR ( Status )) {
2549a88c31639bb24c73383a4528a5b77066e805148blpleahy        pSocket->errno = EADDRNOTAVAIL;
2550a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
2551a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
2552a88c31639bb24c73383a4528a5b77066e805148blpleahy
2553a88c31639bb24c73383a4528a5b77066e805148blpleahy    DBG_EXIT_STATUS ( Status );
2554a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
2555a88c31639bb24c73383a4528a5b77066e805148blpleahy
2556a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2557a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the configuration status
2558a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2559a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
2560a88c31639bb24c73383a4528a5b77066e805148blpleahy}
2561a88c31639bb24c73383a4528a5b77066e805148blpleahy
2562a88c31639bb24c73383a4528a5b77066e805148blpleahy
2563beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Establish the known port to listen for network connections.
2564a88c31639bb24c73383a4528a5b77066e805148blpleahy
2565a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine calls into the network protocol layer to establish
2566a88c31639bb24c73383a4528a5b77066e805148blpleahy  a handler that is called upon connection completion.  The handler
2567a88c31639bb24c73383a4528a5b77066e805148blpleahy  is responsible for inserting the connection into the FIFO.
2568a88c31639bb24c73383a4528a5b77066e805148blpleahy
2569a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::listen routine indirectly calls this routine to place the
2570a88c31639bb24c73383a4528a5b77066e805148blpleahy  socket into a state that enables connection attempts.  Connections
2571a88c31639bb24c73383a4528a5b77066e805148blpleahy  are placed in a FIFO that is serviced by the application.  The
2572a88c31639bb24c73383a4528a5b77066e805148blpleahy  application calls the ::accept (::EslSocketAccept) routine to
2573a88c31639bb24c73383a4528a5b77066e805148blpleahy  remove the next connection from the FIFO and get the associated
2574a88c31639bb24c73383a4528a5b77066e805148blpleahy  socket and address.
2575a88c31639bb24c73383a4528a5b77066e805148blpleahy
2576beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
2577beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  Backlog         Backlog specifies the maximum FIFO depth for
2578a88c31639bb24c73383a4528a5b77066e805148blpleahy                              the connections waiting for the application
2579a88c31639bb24c73383a4528a5b77066e805148blpleahy                              to call accept.  Connection attempts received
2580a88c31639bb24c73383a4528a5b77066e805148blpleahy                              while the queue is full are refused.
2581beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out] pErrno          Address to receive the errno value upon completion.
2582a88c31639bb24c73383a4528a5b77066e805148blpleahy
2583a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - Socket successfully created
2584a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval Other - Failed to enable the socket for listen
2585a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
2586a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
2587a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketListen (
2588a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
2589a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN INT32 Backlog,
2590a88c31639bb24c73383a4528a5b77066e805148blpleahy  OUT int * pErrno
2591a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
2592a88c31639bb24c73383a4528a5b77066e805148blpleahy{
2593a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
2594a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
2595a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS TempStatus;
2596a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_TPL TplPrevious;
2597a88c31639bb24c73383a4528a5b77066e805148blpleahy
2598a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
2599a88c31639bb24c73383a4528a5b77066e805148blpleahy
2600a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2601a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Assume success
2602a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2603a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
2604a88c31639bb24c73383a4528a5b77066e805148blpleahy
2605a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2606a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Validate the socket
2607a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2608a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = NULL;
2609a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL != pSocketProtocol ) {
2610a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
2611a88c31639bb24c73383a4528a5b77066e805148blpleahy
2612a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
2613a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Verify the API
2614a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
2615a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( NULL == pSocket->pApi->pfnListen ) {
2616a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_UNSUPPORTED;
2617a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = ENOTSUP;
2618a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
2619a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
2620a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2621a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Assume success
2622a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2623a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->Status = EFI_SUCCESS;
2624a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = 0;
2625a88c31639bb24c73383a4528a5b77066e805148blpleahy
2626a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2627a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Verify that the bind operation was successful
2628a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2629a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( SOCKET_STATE_BOUND == pSocket->State ) {
2630a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
2631a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Synchronize with the socket layer
2632a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
2633a88c31639bb24c73383a4528a5b77066e805148blpleahy        RAISE_TPL ( TplPrevious, TPL_SOCKETS );
2634a88c31639bb24c73383a4528a5b77066e805148blpleahy
2635a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
2636a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Create the event for SocketAccept completion
2637a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
2638a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = gBS->CreateEvent ( 0,
263928de825561f994ea7923a864ebc54b514edd8af9lpleahy                                    TPL_SOCKETS,
2640a88c31639bb24c73383a4528a5b77066e805148blpleahy                                    NULL,
2641a88c31639bb24c73383a4528a5b77066e805148blpleahy                                    NULL,
2642a88c31639bb24c73383a4528a5b77066e805148blpleahy                                    &pSocket->WaitAccept );
2643a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( !EFI_ERROR ( Status )) {
2644a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_POOL,
2645a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "0x%08x: Created WaitAccept event\r\n",
2646a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pSocket->WaitAccept ));
2647a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
2648a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Set the maximum FIFO depth
2649a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
2650a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( 0 >= Backlog ) {
2651a88c31639bb24c73383a4528a5b77066e805148blpleahy            Backlog = MAX_PENDING_CONNECTIONS;
2652a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
2653a88c31639bb24c73383a4528a5b77066e805148blpleahy          else {
2654a88c31639bb24c73383a4528a5b77066e805148blpleahy            if ( SOMAXCONN < Backlog ) {
2655a88c31639bb24c73383a4528a5b77066e805148blpleahy              Backlog = SOMAXCONN;
2656a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
2657a88c31639bb24c73383a4528a5b77066e805148blpleahy            else {
2658a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket->MaxFifoDepth = Backlog;
2659a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
2660a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
2661a88c31639bb24c73383a4528a5b77066e805148blpleahy
2662a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
2663a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Initiate the connection attempt listen
2664a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
2665a88c31639bb24c73383a4528a5b77066e805148blpleahy          Status = pSocket->pApi->pfnListen ( pSocket );
2666a88c31639bb24c73383a4528a5b77066e805148blpleahy
2667a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
2668a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Place the socket in the listen state if successful
2669a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
2670a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( !EFI_ERROR ( Status )) {
2671a88c31639bb24c73383a4528a5b77066e805148blpleahy            pSocket->State = SOCKET_STATE_LISTENING;
2672a88c31639bb24c73383a4528a5b77066e805148blpleahy            pSocket->bListenCalled = TRUE;
2673a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
2674a88c31639bb24c73383a4528a5b77066e805148blpleahy          else {
2675a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
2676a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Not waiting for SocketAccept to complete
2677a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
2678a88c31639bb24c73383a4528a5b77066e805148blpleahy            TempStatus = gBS->CloseEvent ( pSocket->WaitAccept );
2679a88c31639bb24c73383a4528a5b77066e805148blpleahy            if ( !EFI_ERROR ( TempStatus )) {
2680a88c31639bb24c73383a4528a5b77066e805148blpleahy              DEBUG (( DEBUG_POOL,
2681a88c31639bb24c73383a4528a5b77066e805148blpleahy                        "0x%08x: Closed WaitAccept event\r\n",
2682a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pSocket->WaitAccept ));
2683a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket->WaitAccept = NULL;
2684a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
2685a88c31639bb24c73383a4528a5b77066e805148blpleahy            else {
2686a88c31639bb24c73383a4528a5b77066e805148blpleahy              DEBUG (( DEBUG_ERROR | DEBUG_POOL,
2687a88c31639bb24c73383a4528a5b77066e805148blpleahy                        "ERROR - Failed to close WaitAccept event, Status: %r\r\n",
2688a88c31639bb24c73383a4528a5b77066e805148blpleahy                        TempStatus ));
2689a88c31639bb24c73383a4528a5b77066e805148blpleahy              ASSERT ( EFI_SUCCESS == TempStatus );
2690a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
2691a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
2692a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
2693a88c31639bb24c73383a4528a5b77066e805148blpleahy        else {
2694a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_ERROR | DEBUG_LISTEN,
2695a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "ERROR - Failed to create the WaitAccept event, Status: %r\r\n",
2696a88c31639bb24c73383a4528a5b77066e805148blpleahy                    Status ));
2697a88c31639bb24c73383a4528a5b77066e805148blpleahy          pSocket->errno = ENOMEM;
2698a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
2699a88c31639bb24c73383a4528a5b77066e805148blpleahy
2700a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
2701a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Release the socket layer synchronization
2702a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
2703a88c31639bb24c73383a4528a5b77066e805148blpleahy        RESTORE_TPL ( TplPrevious );
2704a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
2705a88c31639bb24c73383a4528a5b77066e805148blpleahy      else {
2706a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_ERROR | DEBUG_LISTEN,
2707a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "ERROR - Bind operation must be performed first!\r\n" ));
2708a88c31639bb24c73383a4528a5b77066e805148blpleahy        pSocket->errno = ( SOCKET_STATE_NOT_CONFIGURED == pSocket->State ) ? EDESTADDRREQ
2709a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                                           : EINVAL;
2710a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = EFI_NO_MAPPING;
2711d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
2712d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
2713d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
2714d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2715d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2716d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
2717d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2718d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pErrno ) {
2719a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( NULL != pSocket ) {
2720a88c31639bb24c73383a4528a5b77066e805148blpleahy      *pErrno = pSocket->errno;
2721a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
2722a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
2723a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_INVALID_PARAMETER;
2724a88c31639bb24c73383a4528a5b77066e805148blpleahy      *pErrno = ENOTSOCK;
2725a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
2726d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
2727d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
2728d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
2729d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
2730d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2731d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2732beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Get the socket options.
2733d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2734a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine handles the socket level options and passes the
2735a88c31639bb24c73383a4528a5b77066e805148blpleahy  others to the network specific layer.
2736d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2737a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::getsockopt routine calls this routine to retrieve the
2738a88c31639bb24c73383a4528a5b77066e805148blpleahy  socket options one at a time by name.
2739a88c31639bb24c73383a4528a5b77066e805148blpleahy
2740beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      pSocketProtocol   Address of an ::EFI_SOCKET_PROTOCOL structure.
2741beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      level             Option protocol level
2742beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      OptionName        Name of the option
2743beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out]     pOptionValue      Buffer to receive the option value
2744beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in,out]  pOptionLength     Length of the buffer in bytes,
2745beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin                                    upon return length of the option value in bytes
2746beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out]     pErrno            Address to receive the errno value upon completion.
2747d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2748d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_SUCCESS - Socket data successfully received
2749d7ce700605e1af0e455e31ec11f19ff21d26b525darylm **/
2750d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
2751a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketOptionGet (
2752d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
2753d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int level,
2754d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int OptionName,
2755a88c31639bb24c73383a4528a5b77066e805148blpleahy  OUT void * __restrict pOptionValue,
2756a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN OUT socklen_t * __restrict pOptionLength,
2757d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int * pErrno
2758d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
2759d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
2760d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  int errno;
2761d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  socklen_t LengthInBytes;
2762a88c31639bb24c73383a4528a5b77066e805148blpleahy  socklen_t MaxBytes;
276358081f2c64fbc2f89ac5a9b47b2643c280bc8f99lpleahy  CONST UINT8 * pOptionData;
2764a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
2765d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
2766a88c31639bb24c73383a4528a5b77066e805148blpleahy
2767d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
2768a88c31639bb24c73383a4528a5b77066e805148blpleahy
2769d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2770d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Assume failure
2771d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2772d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  errno = EINVAL;
2773d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Status = EFI_INVALID_PARAMETER;
2774a88c31639bb24c73383a4528a5b77066e805148blpleahy
2775d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2776d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Validate the socket
2777d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
2778d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pSocket = NULL;
2779a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL == pSocketProtocol ) {
2780a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_OPTION, "ERROR - pSocketProtocol is NULL!\r\n" ));
2781a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
2782a88c31639bb24c73383a4528a5b77066e805148blpleahy  else if ( NULL == pOptionValue ) {
2783a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_OPTION, "ERROR - No option buffer specified\r\n" ));
2784a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
2785a88c31639bb24c73383a4528a5b77066e805148blpleahy  else if ( NULL == pOptionLength ) {
2786a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_OPTION, "ERROR - Option length not specified!\r\n" ));
2787a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
2788a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
2789d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
2790d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    LengthInBytes = 0;
2791a88c31639bb24c73383a4528a5b77066e805148blpleahy    MaxBytes = *pOptionLength;
2792d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pOptionData = NULL;
2793d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    switch ( level ) {
2794d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    default:
2795d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
2796a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  See if the protocol will handle the option
2797d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
2798a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( NULL != pSocket->pApi->pfnOptionGet ) {
2799a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( pSocket->pApi->DefaultProtocol == level ) {
2800a88c31639bb24c73383a4528a5b77066e805148blpleahy          Status = pSocket->pApi->pfnOptionGet ( pSocket,
2801a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                 OptionName,
280258081f2c64fbc2f89ac5a9b47b2643c280bc8f99lpleahy                                                 (CONST void ** __restrict)&pOptionData,
2803a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                 &LengthInBytes );
2804a88c31639bb24c73383a4528a5b77066e805148blpleahy          errno = pSocket->errno;
2805a88c31639bb24c73383a4528a5b77066e805148blpleahy          break;
2806a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
2807a88c31639bb24c73383a4528a5b77066e805148blpleahy        else {
2808a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
2809a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Protocol not supported
2810a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
2811a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_OPTION,
2812a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "ERROR - The socket does not support this protocol!\r\n" ));
2813a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
2814a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
2815a88c31639bb24c73383a4528a5b77066e805148blpleahy      else {
2816a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
2817a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Protocol level not supported
2818a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
2819a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_OPTION,
2820a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "ERROR - %a does not support any options!\r\n",
2821a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pSocket->pApi->pName ));
2822a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
2823a88c31639bb24c73383a4528a5b77066e805148blpleahy      errno = ENOPROTOOPT;
2824a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_INVALID_PARAMETER;
2825d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      break;
2826a88c31639bb24c73383a4528a5b77066e805148blpleahy
2827d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    case SOL_SOCKET:
2828d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      switch ( OptionName ) {
2829d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      default:
2830d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
2831a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Socket option not supported
2832d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
2833a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_INFO | DEBUG_OPTION, "ERROR - Invalid socket option!\r\n" ));
2834a88c31639bb24c73383a4528a5b77066e805148blpleahy        errno = EINVAL;
2835a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = EFI_INVALID_PARAMETER;
2836d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        break;
2837a88c31639bb24c73383a4528a5b77066e805148blpleahy
2838a88c31639bb24c73383a4528a5b77066e805148blpleahy      case SO_ACCEPTCONN:
2839a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
2840a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Return the listen flag
2841a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
284258081f2c64fbc2f89ac5a9b47b2643c280bc8f99lpleahy        pOptionData = (CONST UINT8 *)&pSocket->bListenCalled;
2843a88c31639bb24c73383a4528a5b77066e805148blpleahy        LengthInBytes = sizeof ( pSocket->bListenCalled );
2844a88c31639bb24c73383a4528a5b77066e805148blpleahy        break;
2845a88c31639bb24c73383a4528a5b77066e805148blpleahy
2846a88c31639bb24c73383a4528a5b77066e805148blpleahy      case SO_DEBUG:
2847a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
2848a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Return the debug flags
2849a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
285058081f2c64fbc2f89ac5a9b47b2643c280bc8f99lpleahy        pOptionData = (CONST UINT8 *)&pSocket->bOobInLine;
2851a88c31639bb24c73383a4528a5b77066e805148blpleahy        LengthInBytes = sizeof ( pSocket->bOobInLine );
2852a88c31639bb24c73383a4528a5b77066e805148blpleahy        break;
2853a88c31639bb24c73383a4528a5b77066e805148blpleahy
2854a88c31639bb24c73383a4528a5b77066e805148blpleahy      case SO_OOBINLINE:
2855a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
2856a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Return the out-of-band inline flag
2857a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
285858081f2c64fbc2f89ac5a9b47b2643c280bc8f99lpleahy        pOptionData = (CONST UINT8 *)&pSocket->bOobInLine;
2859a88c31639bb24c73383a4528a5b77066e805148blpleahy        LengthInBytes = sizeof ( pSocket->bOobInLine );
2860a88c31639bb24c73383a4528a5b77066e805148blpleahy        break;
2861a88c31639bb24c73383a4528a5b77066e805148blpleahy
2862d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      case SO_RCVTIMEO:
2863d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
2864d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //  Return the receive timeout
2865d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
286658081f2c64fbc2f89ac5a9b47b2643c280bc8f99lpleahy        pOptionData = (CONST UINT8 *)&pSocket->RxTimeout;
2867d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        LengthInBytes = sizeof ( pSocket->RxTimeout );
2868d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        break;
28690164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
2870d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      case SO_RCVBUF:
2871d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
2872a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Return the maximum receive buffer size
2873d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
287458081f2c64fbc2f89ac5a9b47b2643c280bc8f99lpleahy        pOptionData = (CONST UINT8 *)&pSocket->MaxRxBuf;
2875d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        LengthInBytes = sizeof ( pSocket->MaxRxBuf );
2876d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        break;
2877d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2878f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy      case SO_REUSEADDR:
2879f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy        //
2880f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy        //  Return the address reuse flag
2881f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy        //
2882f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy        pOptionData = (UINT8 *)&pSocket->bReUseAddr;
2883f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy        LengthInBytes = sizeof ( pSocket->bReUseAddr );
2884f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy        break;
28850164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
2886d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      case SO_SNDBUF:
2887d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
2888d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //  Return the maximum transmit buffer size
2889d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
289058081f2c64fbc2f89ac5a9b47b2643c280bc8f99lpleahy        pOptionData = (CONST UINT8 *)&pSocket->MaxTxBuf;
2891d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        LengthInBytes = sizeof ( pSocket->MaxTxBuf );
2892d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        break;
2893d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
2894a88c31639bb24c73383a4528a5b77066e805148blpleahy      case SO_TYPE:
2895a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
2896a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Return the socket type
2897a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
289858081f2c64fbc2f89ac5a9b47b2643c280bc8f99lpleahy        pOptionData = (CONST UINT8 *)&pSocket->Type;
2899a88c31639bb24c73383a4528a5b77066e805148blpleahy        LengthInBytes = sizeof ( pSocket->Type );
2900a88c31639bb24c73383a4528a5b77066e805148blpleahy        break;
2901a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
2902a88c31639bb24c73383a4528a5b77066e805148blpleahy      break;
2903a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
2904a88c31639bb24c73383a4528a5b77066e805148blpleahy
2905a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
2906a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Return the option length
2907a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
2908a88c31639bb24c73383a4528a5b77066e805148blpleahy    *pOptionLength = LengthInBytes;
2909a88c31639bb24c73383a4528a5b77066e805148blpleahy
2910a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
2911a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Determine if the option is present
2912a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
2913a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( 0 != LengthInBytes ) {
2914a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2915a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Silently truncate the value length
2916a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2917a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( LengthInBytes > MaxBytes ) {
2918a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_OPTION,
2919a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "INFO - Truncating option from %d to %d bytes\r\n",
2920a88c31639bb24c73383a4528a5b77066e805148blpleahy                  LengthInBytes,
2921a88c31639bb24c73383a4528a5b77066e805148blpleahy                  MaxBytes ));
2922a88c31639bb24c73383a4528a5b77066e805148blpleahy        LengthInBytes = MaxBytes;
2923a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
2924a88c31639bb24c73383a4528a5b77066e805148blpleahy
2925a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2926a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Return the value
2927a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2928a88c31639bb24c73383a4528a5b77066e805148blpleahy      CopyMem ( pOptionValue, pOptionData, LengthInBytes );
2929a88c31639bb24c73383a4528a5b77066e805148blpleahy
2930a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2931a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Zero fill any remaining space
2932a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
2933a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( LengthInBytes < MaxBytes ) {
2934a88c31639bb24c73383a4528a5b77066e805148blpleahy        ZeroMem ( &((UINT8 *)pOptionValue)[LengthInBytes], MaxBytes - LengthInBytes );
2935a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
2936a88c31639bb24c73383a4528a5b77066e805148blpleahy      errno = 0;
2937a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_SUCCESS;
2938a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
2939a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
2940a88c31639bb24c73383a4528a5b77066e805148blpleahy
2941a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2942a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
2943a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2944a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL != pErrno ) {
2945a88c31639bb24c73383a4528a5b77066e805148blpleahy    *pErrno = errno;
2946a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
2947a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
2948a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
2949a88c31639bb24c73383a4528a5b77066e805148blpleahy}
2950a88c31639bb24c73383a4528a5b77066e805148blpleahy
2951a88c31639bb24c73383a4528a5b77066e805148blpleahy
2952beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Set the socket options.
2953a88c31639bb24c73383a4528a5b77066e805148blpleahy
2954a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine handles the socket level options and passes the
2955a88c31639bb24c73383a4528a5b77066e805148blpleahy  others to the network specific layer.
2956a88c31639bb24c73383a4528a5b77066e805148blpleahy
2957a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::setsockopt routine calls this routine to adjust the socket
2958a88c31639bb24c73383a4528a5b77066e805148blpleahy  options one at a time by name.
2959a88c31639bb24c73383a4528a5b77066e805148blpleahy
2960beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
2961beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  level           Option protocol level
2962beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  OptionName      Name of the option
2963beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pOptionValue    Buffer containing the option value
2964beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  OptionLength    Length of the buffer in bytes
2965beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out] pErrno          Address to receive the errno value upon completion.
2966a88c31639bb24c73383a4528a5b77066e805148blpleahy
2967a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - Option successfully set
2968beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
2969a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
2970a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketOptionSet (
2971a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
2972a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN int level,
2973a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN int OptionName,
2974a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN CONST void * pOptionValue,
2975a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN socklen_t OptionLength,
2976a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN int * pErrno
2977a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
2978a88c31639bb24c73383a4528a5b77066e805148blpleahy{
2979a88c31639bb24c73383a4528a5b77066e805148blpleahy  BOOLEAN bTrueFalse;
2980a88c31639bb24c73383a4528a5b77066e805148blpleahy  int errno;
2981a88c31639bb24c73383a4528a5b77066e805148blpleahy  socklen_t LengthInBytes;
2982a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINT8 * pOptionData;
2983a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
2984a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
29850164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
2986a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
29870164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
2988a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2989a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Assume failure
2990a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2991a88c31639bb24c73383a4528a5b77066e805148blpleahy  errno = EINVAL;
2992a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_INVALID_PARAMETER;
2993a88c31639bb24c73383a4528a5b77066e805148blpleahy
2994a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2995a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Validate the socket
2996a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
2997a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = NULL;
2998a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL == pSocketProtocol ) {
2999a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_OPTION, "ERROR - pSocketProtocol is NULL!\r\n" ));
3000a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3001a88c31639bb24c73383a4528a5b77066e805148blpleahy  else if ( NULL == pOptionValue ) {
3002a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_OPTION, "ERROR - No option buffer specified\r\n" ));
3003a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3004a88c31639bb24c73383a4528a5b77066e805148blpleahy  else
3005a88c31639bb24c73383a4528a5b77066e805148blpleahy  {
3006a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
3007a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( pSocket->bRxDisable || pSocket->bTxDisable ) {
3008a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_OPTION, "ERROR - Socket has been shutdown!\r\n" ));
3009a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3010a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
3011a88c31639bb24c73383a4528a5b77066e805148blpleahy      LengthInBytes = 0;
3012a88c31639bb24c73383a4528a5b77066e805148blpleahy      pOptionData = NULL;
3013a88c31639bb24c73383a4528a5b77066e805148blpleahy      switch ( level ) {
3014a88c31639bb24c73383a4528a5b77066e805148blpleahy      default:
3015a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
3016a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  See if the protocol will handle the option
3017a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
3018a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( NULL != pSocket->pApi->pfnOptionSet ) {
3019a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( pSocket->pApi->DefaultProtocol == level ) {
3020a88c31639bb24c73383a4528a5b77066e805148blpleahy            Status = pSocket->pApi->pfnOptionSet ( pSocket,
3021a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                   OptionName,
3022a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                   pOptionValue,
3023a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                   OptionLength );
3024a88c31639bb24c73383a4528a5b77066e805148blpleahy            errno = pSocket->errno;
3025a88c31639bb24c73383a4528a5b77066e805148blpleahy            break;
3026a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
3027a88c31639bb24c73383a4528a5b77066e805148blpleahy          else {
3028a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
3029a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Protocol not supported
3030a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
3031a88c31639bb24c73383a4528a5b77066e805148blpleahy            DEBUG (( DEBUG_OPTION,
3032a88c31639bb24c73383a4528a5b77066e805148blpleahy                      "ERROR - The socket does not support this protocol!\r\n" ));
3033a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
3034a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
3035a88c31639bb24c73383a4528a5b77066e805148blpleahy        else {
3036a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3037a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Protocol level not supported
3038a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3039a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_OPTION,
3040a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "ERROR - %a does not support any options!\r\n",
3041a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pSocket->pApi->pName ));
3042a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
3043a88c31639bb24c73383a4528a5b77066e805148blpleahy        errno = ENOPROTOOPT;
3044a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = EFI_INVALID_PARAMETER;
3045a88c31639bb24c73383a4528a5b77066e805148blpleahy        break;
30460164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
3047a88c31639bb24c73383a4528a5b77066e805148blpleahy      case SOL_SOCKET:
3048a88c31639bb24c73383a4528a5b77066e805148blpleahy        switch ( OptionName ) {
3049a88c31639bb24c73383a4528a5b77066e805148blpleahy        default:
3050a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3051a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Option not supported
3052a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3053a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_OPTION,
3054a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "ERROR - Sockets does not support this option!\r\n" ));
3055a88c31639bb24c73383a4528a5b77066e805148blpleahy          errno = EINVAL;
3056a88c31639bb24c73383a4528a5b77066e805148blpleahy          Status = EFI_INVALID_PARAMETER;
3057a88c31639bb24c73383a4528a5b77066e805148blpleahy          break;
3058a88c31639bb24c73383a4528a5b77066e805148blpleahy
3059a88c31639bb24c73383a4528a5b77066e805148blpleahy        case SO_DEBUG:
3060a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3061a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Set the debug flags
3062a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3063a88c31639bb24c73383a4528a5b77066e805148blpleahy          pOptionData = (UINT8 *)&pSocket->bOobInLine;
3064a88c31639bb24c73383a4528a5b77066e805148blpleahy          LengthInBytes = sizeof ( pSocket->bOobInLine );
3065a88c31639bb24c73383a4528a5b77066e805148blpleahy          break;
3066a88c31639bb24c73383a4528a5b77066e805148blpleahy
3067a88c31639bb24c73383a4528a5b77066e805148blpleahy        case SO_OOBINLINE:
3068a88c31639bb24c73383a4528a5b77066e805148blpleahy          pOptionData = (UINT8 *)&pSocket->bOobInLine;
3069a88c31639bb24c73383a4528a5b77066e805148blpleahy          LengthInBytes = sizeof ( pSocket->bOobInLine );
3070a88c31639bb24c73383a4528a5b77066e805148blpleahy
3071a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3072a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Validate the option length
3073a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3074a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( sizeof ( UINT32 ) == OptionLength ) {
3075a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
3076a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Restrict the input to TRUE or FALSE
3077a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
3078a88c31639bb24c73383a4528a5b77066e805148blpleahy            bTrueFalse = TRUE;
3079a88c31639bb24c73383a4528a5b77066e805148blpleahy            if ( 0 == *(UINT32 *)pOptionValue ) {
3080a88c31639bb24c73383a4528a5b77066e805148blpleahy              bTrueFalse = FALSE;
3081a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
3082a88c31639bb24c73383a4528a5b77066e805148blpleahy            pOptionValue = &bTrueFalse;
3083a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
3084a88c31639bb24c73383a4528a5b77066e805148blpleahy          else {
3085a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
3086a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Force an invalid option length error
3087a88c31639bb24c73383a4528a5b77066e805148blpleahy            //
3088a88c31639bb24c73383a4528a5b77066e805148blpleahy            OptionLength = LengthInBytes - 1;
3089a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
3090a88c31639bb24c73383a4528a5b77066e805148blpleahy          break;
3091a88c31639bb24c73383a4528a5b77066e805148blpleahy
3092a88c31639bb24c73383a4528a5b77066e805148blpleahy        case SO_RCVTIMEO:
3093a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3094a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Return the receive timeout
3095a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3096a88c31639bb24c73383a4528a5b77066e805148blpleahy          pOptionData = (UINT8 *)&pSocket->RxTimeout;
3097a88c31639bb24c73383a4528a5b77066e805148blpleahy          LengthInBytes = sizeof ( pSocket->RxTimeout );
3098a88c31639bb24c73383a4528a5b77066e805148blpleahy          break;
3099a88c31639bb24c73383a4528a5b77066e805148blpleahy
3100a88c31639bb24c73383a4528a5b77066e805148blpleahy        case SO_RCVBUF:
3101a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3102a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Return the maximum receive buffer size
3103a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3104a88c31639bb24c73383a4528a5b77066e805148blpleahy          pOptionData = (UINT8 *)&pSocket->MaxRxBuf;
3105a88c31639bb24c73383a4528a5b77066e805148blpleahy          LengthInBytes = sizeof ( pSocket->MaxRxBuf );
3106a88c31639bb24c73383a4528a5b77066e805148blpleahy          break;
3107a88c31639bb24c73383a4528a5b77066e805148blpleahy
3108f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy        case SO_REUSEADDR:
3109f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          //
3110f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          //  Return the address reuse flag
3111f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          //
3112f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          pOptionData = (UINT8 *)&pSocket->bReUseAddr;
3113f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          LengthInBytes = sizeof ( pSocket->bReUseAddr );
3114f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy          break;
3115f74dc4bbba84a07f8c01fea4c43aa77d800ee43clpleahy
3116a88c31639bb24c73383a4528a5b77066e805148blpleahy        case SO_SNDBUF:
3117a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3118a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Send buffer size
3119a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3120a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3121a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Return the maximum transmit buffer size
3122a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3123a88c31639bb24c73383a4528a5b77066e805148blpleahy          pOptionData = (UINT8 *)&pSocket->MaxTxBuf;
3124a88c31639bb24c73383a4528a5b77066e805148blpleahy          LengthInBytes = sizeof ( pSocket->MaxTxBuf );
3125a88c31639bb24c73383a4528a5b77066e805148blpleahy          break;
3126a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
3127a88c31639bb24c73383a4528a5b77066e805148blpleahy        break;
3128a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3129a88c31639bb24c73383a4528a5b77066e805148blpleahy
3130a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3131a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Determine if an option was found
3132a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3133a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( 0 != LengthInBytes ) {
3134a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
3135a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Validate the option length
3136a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
3137a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( LengthInBytes <= OptionLength ) {
3138a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3139a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Set the option value
3140a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
3141a88c31639bb24c73383a4528a5b77066e805148blpleahy          CopyMem ( pOptionData, pOptionValue, LengthInBytes );
3142a88c31639bb24c73383a4528a5b77066e805148blpleahy          errno = 0;
3143a88c31639bb24c73383a4528a5b77066e805148blpleahy          Status = EFI_SUCCESS;
3144a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
3145a88c31639bb24c73383a4528a5b77066e805148blpleahy        else {
3146a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_OPTION,
3147a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "ERROR - Buffer to small, %d bytes < %d bytes!\r\n",
3148a88c31639bb24c73383a4528a5b77066e805148blpleahy                    OptionLength,
3149a88c31639bb24c73383a4528a5b77066e805148blpleahy                    LengthInBytes ));
3150a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
3151a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3152a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3153a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3154a88c31639bb24c73383a4528a5b77066e805148blpleahy
3155a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3156a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
3157a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3158a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL != pErrno ) {
3159a88c31639bb24c73383a4528a5b77066e805148blpleahy    *pErrno = errno;
3160a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3161a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
3162a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
3163a88c31639bb24c73383a4528a5b77066e805148blpleahy}
3164a88c31639bb24c73383a4528a5b77066e805148blpleahy
3165a88c31639bb24c73383a4528a5b77066e805148blpleahy
3166beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/**  Allocate a packet for a receive or transmit operation.
3167a88c31639bb24c73383a4528a5b77066e805148blpleahy
3168a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support routine is called by ::EslSocketRxStart and the
3169a88c31639bb24c73383a4528a5b77066e805148blpleahy  network specific TxBuffer routines to get buffer space for the
3170a88c31639bb24c73383a4528a5b77066e805148blpleahy  next operation.
3171a88c31639bb24c73383a4528a5b77066e805148blpleahy
3172beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  ppPacket      Address to receive the ::ESL_PACKET structure
3173beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  LengthInBytes Length of the packet structure
3174beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  ZeroBytes     Length of packet to zero
3175beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  DebugFlags    Flags for debug messages
3176a88c31639bb24c73383a4528a5b77066e805148blpleahy
3177a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - The packet was allocated successfully
3178beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
3179a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
3180a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketPacketAllocate (
3181a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PACKET ** ppPacket,
3182a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN size_t LengthInBytes,
3183a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN size_t ZeroBytes,
3184a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN UINTN DebugFlags
3185a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
3186a88c31639bb24c73383a4528a5b77066e805148blpleahy{
3187a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pPacket;
3188a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
3189a88c31639bb24c73383a4528a5b77066e805148blpleahy
3190a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
3191a88c31639bb24c73383a4528a5b77066e805148blpleahy
3192a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3193a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Allocate a packet structure
3194a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3195a88c31639bb24c73383a4528a5b77066e805148blpleahy  LengthInBytes += sizeof ( *pPacket )
3196a88c31639bb24c73383a4528a5b77066e805148blpleahy                - sizeof ( pPacket->Op );
3197a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = gBS->AllocatePool ( EfiRuntimeServicesData,
3198a88c31639bb24c73383a4528a5b77066e805148blpleahy                               LengthInBytes,
3199a88c31639bb24c73383a4528a5b77066e805148blpleahy                               (VOID **)&pPacket );
3200a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( !EFI_ERROR ( Status )) {
32013bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    DEBUG (( DebugFlags | DEBUG_POOL,
3202a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Allocate pPacket, %d bytes\r\n",
3203a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPacket,
3204a88c31639bb24c73383a4528a5b77066e805148blpleahy              LengthInBytes ));
3205a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( 0 != ZeroBytes ) {
3206a88c31639bb24c73383a4528a5b77066e805148blpleahy      ZeroMem ( &pPacket->Op, ZeroBytes );
3207a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3208a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPacket->PacketSize = LengthInBytes;
3209a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3210a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
3211a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INFO,
3212a88c31639bb24c73383a4528a5b77066e805148blpleahy              "ERROR - Packet allocation failed for %d bytes, Status: %r\r\n",
3213a88c31639bb24c73383a4528a5b77066e805148blpleahy              LengthInBytes,
3214a88c31639bb24c73383a4528a5b77066e805148blpleahy              Status ));
3215a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPacket = NULL;
3216a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3217a88c31639bb24c73383a4528a5b77066e805148blpleahy
3218a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3219a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the packet
3220a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3221a88c31639bb24c73383a4528a5b77066e805148blpleahy  *ppPacket = pPacket;
3222a88c31639bb24c73383a4528a5b77066e805148blpleahy
3223a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3224a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
3225a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3226a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
3227a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
3228a88c31639bb24c73383a4528a5b77066e805148blpleahy}
3229a88c31639bb24c73383a4528a5b77066e805148blpleahy
3230a88c31639bb24c73383a4528a5b77066e805148blpleahy
3231beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Free a packet used for receive or transmit operation.
3232a88c31639bb24c73383a4528a5b77066e805148blpleahy
3233a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support routine is called by the network specific Close
3234a88c31639bb24c73383a4528a5b77066e805148blpleahy  and TxComplete routines and during error cases in RxComplete
3235a88c31639bb24c73383a4528a5b77066e805148blpleahy  and TxBuffer.  Note that the network layers typically place
3236a88c31639bb24c73383a4528a5b77066e805148blpleahy  receive packets on the ESL_SOCKET::pRxFree list for reuse.
3237a88c31639bb24c73383a4528a5b77066e805148blpleahy
3238beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pPacket     Address of an ::ESL_PACKET structure
3239beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  DebugFlags  Flags for debug messages
3240a88c31639bb24c73383a4528a5b77066e805148blpleahy
3241a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - The packet was allocated successfully
3242beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
3243a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
3244a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketPacketFree (
3245a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PACKET * pPacket,
3246a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN UINTN DebugFlags
3247a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
3248a88c31639bb24c73383a4528a5b77066e805148blpleahy{
3249a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINTN LengthInBytes;
3250a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
3251a88c31639bb24c73383a4528a5b77066e805148blpleahy
3252a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
3253a88c31639bb24c73383a4528a5b77066e805148blpleahy
3254a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3255884ed923564f35084c45a8f3f132c076b26f2423lpleahy  //  Free a packet structure
3256a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3257a88c31639bb24c73383a4528a5b77066e805148blpleahy  LengthInBytes = pPacket->PacketSize;
3258a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = gBS->FreePool ( pPacket );
3259a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( !EFI_ERROR ( Status )) {
3260a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DebugFlags | DEBUG_POOL,
3261a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Free pPacket, %d bytes\r\n",
3262a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPacket,
3263a88c31639bb24c73383a4528a5b77066e805148blpleahy              LengthInBytes ));
3264a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3265a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
3266a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INFO,
3267a88c31639bb24c73383a4528a5b77066e805148blpleahy              "ERROR - Failed to free packet 0x%08x, Status: %r\r\n",
3268a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPacket,
3269a88c31639bb24c73383a4528a5b77066e805148blpleahy              Status ));
3270a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3271a88c31639bb24c73383a4528a5b77066e805148blpleahy
3272a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3273a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
3274a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3275a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
3276a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
3277a88c31639bb24c73383a4528a5b77066e805148blpleahy}
3278a88c31639bb24c73383a4528a5b77066e805148blpleahy
3279a88c31639bb24c73383a4528a5b77066e805148blpleahy
3280beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Poll a socket for pending activity.
3281a88c31639bb24c73383a4528a5b77066e805148blpleahy
3282a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine builds a detected event mask which is returned to
3283a88c31639bb24c73383a4528a5b77066e805148blpleahy  the caller in the buffer provided.
3284a88c31639bb24c73383a4528a5b77066e805148blpleahy
3285a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::poll routine calls this routine to determine if the socket
3286a88c31639bb24c73383a4528a5b77066e805148blpleahy  needs to be serviced as a result of connection, error, receive or
3287a88c31639bb24c73383a4528a5b77066e805148blpleahy  transmit activity.
3288a88c31639bb24c73383a4528a5b77066e805148blpleahy
3289beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
3290beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  Events          Events of interest for this socket
3291beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pEvents         Address to receive the detected events
3292beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out] pErrno          Address to receive the errno value upon completion.
3293a88c31639bb24c73383a4528a5b77066e805148blpleahy
3294a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - Socket successfully polled
3295a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_INVALID_PARAMETER - When pEvents is NULL
3296beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
3297a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
3298a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketPoll (
3299a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
3300a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN short Events,
3301a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN short * pEvents,
3302a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN int * pErrno
3303a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
3304a88c31639bb24c73383a4528a5b77066e805148blpleahy{
3305a88c31639bb24c73383a4528a5b77066e805148blpleahy  short DetectedEvents;
3306a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
3307a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
33083bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  EFI_TPL TplPrevious;
3309a88c31639bb24c73383a4528a5b77066e805148blpleahy  short ValidEvents;
3310beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  int   _errno = EINVAL;
3311a88c31639bb24c73383a4528a5b77066e805148blpleahy
3312a88c31639bb24c73383a4528a5b77066e805148blpleahy  DEBUG (( DEBUG_POLL, "Entering SocketPoll\r\n" ));
3313a88c31639bb24c73383a4528a5b77066e805148blpleahy
3314a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3315a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Assume success
3316a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3317a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
3318a88c31639bb24c73383a4528a5b77066e805148blpleahy  DetectedEvents = 0;
3319a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
3320a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket->errno = 0;
3321a88c31639bb24c73383a4528a5b77066e805148blpleahy
3322a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3323a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Verify the socket state
3324a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3325a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EslSocketIsConfigured ( pSocket );
3326a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( !EFI_ERROR ( Status )) {
3327a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3328a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Check for invalid events
3329a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3330a88c31639bb24c73383a4528a5b77066e805148blpleahy    ValidEvents = POLLIN
3331a88c31639bb24c73383a4528a5b77066e805148blpleahy                | POLLPRI
3332a88c31639bb24c73383a4528a5b77066e805148blpleahy                | POLLOUT | POLLWRNORM
3333a88c31639bb24c73383a4528a5b77066e805148blpleahy                | POLLERR
3334a88c31639bb24c73383a4528a5b77066e805148blpleahy                | POLLHUP
3335a88c31639bb24c73383a4528a5b77066e805148blpleahy                | POLLNVAL
3336a88c31639bb24c73383a4528a5b77066e805148blpleahy                | POLLRDNORM
3337a88c31639bb24c73383a4528a5b77066e805148blpleahy                | POLLRDBAND
3338a88c31639bb24c73383a4528a5b77066e805148blpleahy                | POLLWRBAND ;
3339a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( 0 != ( Events & ( ~ValidEvents ))) {
3340a88c31639bb24c73383a4528a5b77066e805148blpleahy      DetectedEvents |= POLLNVAL;
3341a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_INFO | DEBUG_POLL,
3342a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - Invalid event mask, Valid Events: 0x%04x, Invalid Events: 0x%04x\r\n",
3343a88c31639bb24c73383a4528a5b77066e805148blpleahy                Events & ValidEvents,
3344a88c31639bb24c73383a4528a5b77066e805148blpleahy                Events & ( ~ValidEvents )));
3345a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3346a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
3347a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
33483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      //  Synchronize with the socket layer
33493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      //
33503bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      RAISE_TPL ( TplPrevious, TPL_SOCKETS );
33510164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
33523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      //
33533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      //  Increase the network performance by extending the
33543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      //  polling (idle) loop down into the LAN driver
33553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      //
33563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      EslSocketRxPoll ( pSocket );
33570164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
33583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      //
33593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      //  Release the socket layer synchronization
33603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      //
33613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      RESTORE_TPL ( TplPrevious );
33623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
33633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy      //
3364a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Check for pending connections
3365a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3366a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( 0 != pSocket->FifoDepth ) {
3367a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
3368a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  A connection is waiting for an accept call
3369a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  See posix connect documentation at
3370a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.htm
3371a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
3372a88c31639bb24c73383a4528a5b77066e805148blpleahy        DetectedEvents |= POLLIN | POLLRDNORM;
3373a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3374a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( pSocket->bConnected ) {
3375a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
3376a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  A connection is present
3377a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  See posix connect documentation at
3378a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.htm
3379a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
3380a88c31639bb24c73383a4528a5b77066e805148blpleahy        DetectedEvents |= POLLOUT | POLLWRNORM;
3381a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3382a88c31639bb24c73383a4528a5b77066e805148blpleahy
3383a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3384a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  The following bits are set based upon the POSIX poll documentation at
3385a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html
3386a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3387a88c31639bb24c73383a4528a5b77066e805148blpleahy
3388a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3389a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Check for urgent receive data
3390a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3391a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( 0 < pSocket->RxOobBytes ) {
3392a88c31639bb24c73383a4528a5b77066e805148blpleahy        DetectedEvents |= POLLRDBAND | POLLPRI | POLLIN;
3393a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3394a88c31639bb24c73383a4528a5b77066e805148blpleahy
3395a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3396a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Check for normal receive data
3397a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3398a88c31639bb24c73383a4528a5b77066e805148blpleahy      if (( 0 < pSocket->RxBytes )
3399a88c31639bb24c73383a4528a5b77066e805148blpleahy        || ( EFI_SUCCESS != pSocket->RxError )) {
3400a88c31639bb24c73383a4528a5b77066e805148blpleahy        DetectedEvents |= POLLRDNORM | POLLIN;
3401a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3402a88c31639bb24c73383a4528a5b77066e805148blpleahy
3403a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3404a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Handle the receive errors
3405a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3406a88c31639bb24c73383a4528a5b77066e805148blpleahy      if (( EFI_SUCCESS != pSocket->RxError )
3407a88c31639bb24c73383a4528a5b77066e805148blpleahy        && ( 0 == ( DetectedEvents & POLLIN ))) {
3408a88c31639bb24c73383a4528a5b77066e805148blpleahy        DetectedEvents |= POLLERR | POLLIN | POLLRDNORM | POLLRDBAND;
3409a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3410a88c31639bb24c73383a4528a5b77066e805148blpleahy
3411a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3412a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Check for urgent transmit data buffer space
3413a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3414a88c31639bb24c73383a4528a5b77066e805148blpleahy      if (( MAX_TX_DATA > pSocket->TxOobBytes )
3415a88c31639bb24c73383a4528a5b77066e805148blpleahy        || ( EFI_SUCCESS != pSocket->TxError )) {
3416a88c31639bb24c73383a4528a5b77066e805148blpleahy        DetectedEvents |= POLLWRBAND;
3417a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3418a88c31639bb24c73383a4528a5b77066e805148blpleahy
3419a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3420a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Check for normal transmit data buffer space
3421a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3422a88c31639bb24c73383a4528a5b77066e805148blpleahy      if (( MAX_TX_DATA > pSocket->TxBytes )
3423a88c31639bb24c73383a4528a5b77066e805148blpleahy        || ( EFI_SUCCESS != pSocket->TxError )) {
3424a88c31639bb24c73383a4528a5b77066e805148blpleahy        DetectedEvents |= POLLWRNORM;
3425a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3426a88c31639bb24c73383a4528a5b77066e805148blpleahy
3427a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3428a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Handle the transmit error
3429a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3430a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( EFI_ERROR ( pSocket->TxError )) {
3431a88c31639bb24c73383a4528a5b77066e805148blpleahy        DetectedEvents |= POLLERR;
3432a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3433beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin      _errno = pSocket->errno;
3434a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3435a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3436a88c31639bb24c73383a4528a5b77066e805148blpleahy
3437a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3438a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the detected events
3439a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3440a88c31639bb24c73383a4528a5b77066e805148blpleahy  *pEvents = DetectedEvents & ( Events
3441a88c31639bb24c73383a4528a5b77066e805148blpleahy                              | POLLERR
3442a88c31639bb24c73383a4528a5b77066e805148blpleahy                              | POLLHUP
3443a88c31639bb24c73383a4528a5b77066e805148blpleahy                              | POLLNVAL );
3444beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  if ( NULL != pErrno ) {
3445beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin    *pErrno = _errno;
3446beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  }
3447a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3448a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
3449a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3450a88c31639bb24c73383a4528a5b77066e805148blpleahy  DEBUG (( DEBUG_POLL, "Exiting SocketPoll, Status: %r\r\n", Status ));
3451a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
3452a88c31639bb24c73383a4528a5b77066e805148blpleahy}
3453a88c31639bb24c73383a4528a5b77066e805148blpleahy
3454a88c31639bb24c73383a4528a5b77066e805148blpleahy
3455beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Allocate and initialize a ESL_PORT structure.
3456a88c31639bb24c73383a4528a5b77066e805148blpleahy
3457a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine initializes an ::ESL_PORT structure for use by
3458a88c31639bb24c73383a4528a5b77066e805148blpleahy  the socket.  This routine calls a routine via
3459a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PROTOCOL_API::pfnPortAllocate to initialize the network
3460a88c31639bb24c73383a4528a5b77066e805148blpleahy  specific resources.  The resources are released later by the
3461a88c31639bb24c73383a4528a5b77066e805148blpleahy  \ref PortCloseStateMachine.
3462a88c31639bb24c73383a4528a5b77066e805148blpleahy
3463a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support routine is called by:
3464a88c31639bb24c73383a4528a5b77066e805148blpleahy  <ul>
3465a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslSocketBind</li>
3466a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslTcp4ListenComplete</li>
3467a88c31639bb24c73383a4528a5b77066e805148blpleahy  </ul>
3468a88c31639bb24c73383a4528a5b77066e805148blpleahy  to connect the socket with the underlying network adapter
3469a88c31639bb24c73383a4528a5b77066e805148blpleahy  to the socket.
3470a88c31639bb24c73383a4528a5b77066e805148blpleahy
3471beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSocket     Address of an ::ESL_SOCKET structure.
3472beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pService    Address of an ::ESL_SERVICE structure.
3473beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  ChildHandle Network protocol child handle
3474beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSockAddr   Address of a sockaddr structure that contains the
3475a88c31639bb24c73383a4528a5b77066e805148blpleahy                          connection point on the local machine.  An IPv4 address
3476a88c31639bb24c73383a4528a5b77066e805148blpleahy                          of INADDR_ANY specifies that the connection is made to
3477a88c31639bb24c73383a4528a5b77066e805148blpleahy                          all of the network stacks on the platform.  Specifying a
3478a88c31639bb24c73383a4528a5b77066e805148blpleahy                          specific IPv4 address restricts the connection to the
3479a88c31639bb24c73383a4528a5b77066e805148blpleahy                          network stack supporting that address.  Specifying zero
3480a88c31639bb24c73383a4528a5b77066e805148blpleahy                          for the port causes the network layer to assign a port
3481a88c31639bb24c73383a4528a5b77066e805148blpleahy                          number from the dynamic range.  Specifying a specific
3482a88c31639bb24c73383a4528a5b77066e805148blpleahy                          port number causes the network layer to use that port.
3483beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  bBindTest   TRUE if EslSocketBindTest should be called
3484beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  DebugFlags  Flags for debug messages
3485beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out] ppPort      Buffer to receive new ::ESL_PORT structure address
3486a88c31639bb24c73383a4528a5b77066e805148blpleahy
3487a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS - Socket successfully created
3488beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
3489a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
3490a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketPortAllocate (
3491a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_SOCKET * pSocket,
3492a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_SERVICE * pService,
3493a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN EFI_HANDLE ChildHandle,
3494a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN CONST struct sockaddr * pSockAddr,
3495a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN BOOLEAN bBindTest,
3496a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN UINTN DebugFlags,
3497a88c31639bb24c73383a4528a5b77066e805148blpleahy  OUT ESL_PORT ** ppPort
3498a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
3499a88c31639bb24c73383a4528a5b77066e805148blpleahy{
3500a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINTN LengthInBytes;
3501a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINT8 * pBuffer;
3502a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IO_MGMT * pIo;
3503a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_LAYER * pLayer;
3504a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
3505a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;
3506a88c31639bb24c73383a4528a5b77066e805148blpleahy  CONST ESL_SOCKET_BINDING * pSocketBinding;
3507a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
3508a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS TempStatus;
3509a88c31639bb24c73383a4528a5b77066e805148blpleahy
3510a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
3511a88c31639bb24c73383a4528a5b77066e805148blpleahy
3512a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3513a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Verify the socket layer synchronization
3514a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3515a88c31639bb24c73383a4528a5b77066e805148blpleahy  VERIFY_TPL ( TPL_SOCKETS );
3516a88c31639bb24c73383a4528a5b77066e805148blpleahy
3517a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3518a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Use for/break instead of goto
3519a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocketBinding = pService->pSocketBinding;
3520a88c31639bb24c73383a4528a5b77066e805148blpleahy  for ( ; ; ) {
3521a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3522a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Allocate a port structure
3523a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3524a88c31639bb24c73383a4528a5b77066e805148blpleahy    pLayer = &mEslLayer;
3525a88c31639bb24c73383a4528a5b77066e805148blpleahy    LengthInBytes = sizeof ( *pPort )
3526a88c31639bb24c73383a4528a5b77066e805148blpleahy                  + ESL_STRUCTURE_ALIGNMENT_BYTES
3527a88c31639bb24c73383a4528a5b77066e805148blpleahy                  + (( pSocketBinding->RxIo
3528a88c31639bb24c73383a4528a5b77066e805148blpleahy                       + pSocketBinding->TxIoNormal
3529a88c31639bb24c73383a4528a5b77066e805148blpleahy                       + pSocketBinding->TxIoUrgent )
3530a88c31639bb24c73383a4528a5b77066e805148blpleahy                     * sizeof ( ESL_IO_MGMT ));
3531a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort = (ESL_PORT *) AllocateZeroPool ( LengthInBytes );
3532a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( NULL == pPort ) {
3533a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_OUT_OF_RESOURCES;
3534a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = ENOMEM;
3535a88c31639bb24c73383a4528a5b77066e805148blpleahy      break;
3536a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3537a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,
3538a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Allocate pPort, %d bytes\r\n",
3539a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort,
3540a88c31639bb24c73383a4528a5b77066e805148blpleahy              LengthInBytes ));
3541a88c31639bb24c73383a4528a5b77066e805148blpleahy
3542a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3543a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Initialize the port
3544a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3545a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->DebugFlags = DebugFlags;
3546a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->Handle = ChildHandle;
3547a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->pService = pService;
3548a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->pServiceBinding = pService->pServiceBinding;
3549a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->pSocket = pSocket;
3550a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->pSocketBinding = pService->pSocketBinding;
3551a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->Signature = PORT_SIGNATURE;
3552a88c31639bb24c73383a4528a5b77066e805148blpleahy
3553a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3554a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Open the port protocol
3555a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3556a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = gBS->OpenProtocol ( pPort->Handle,
3557a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 pSocketBinding->pNetworkProtocolGuid,
3558a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 &pPort->pProtocol.v,
3559a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 pLayer->ImageHandle,
3560a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 NULL,
3561a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
3562a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( EFI_ERROR ( Status )) {
3563a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_ERROR | DebugFlags,
3564a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - Failed to open network protocol GUID on controller 0x%08x\r\n",
3565a88c31639bb24c73383a4528a5b77066e805148blpleahy                pPort->Handle ));
3566a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = EEXIST;
3567a88c31639bb24c73383a4528a5b77066e805148blpleahy      break;
3568a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3569a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DebugFlags,
3570a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Network protocol GUID opened on controller 0x%08x\r\n",
3571a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort->pProtocol.v,
3572a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort->Handle ));
3573a88c31639bb24c73383a4528a5b77066e805148blpleahy
3574a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3575a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Initialize the port specific resources
3576a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3577a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = pSocket->pApi->pfnPortAllocate ( pPort,
3578a88c31639bb24c73383a4528a5b77066e805148blpleahy                                              DebugFlags );
3579a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( EFI_ERROR ( Status )) {
3580a88c31639bb24c73383a4528a5b77066e805148blpleahy      break;
3581a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3582a88c31639bb24c73383a4528a5b77066e805148blpleahy
3583a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3584a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Set the local address
3585a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3586a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = pSocket->pApi->pfnLocalAddrSet ( pPort, pSockAddr, bBindTest );
3587a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( EFI_ERROR ( Status )) {
3588a88c31639bb24c73383a4528a5b77066e805148blpleahy      break;
3589a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3590a88c31639bb24c73383a4528a5b77066e805148blpleahy
3591a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3592a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Test the address/port configuration
3593a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3594a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( bBindTest ) {
3595a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EslSocketBindTest ( pPort, pSocket->pApi->BindTestErrno );
3596a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( EFI_ERROR ( Status )) {
3597a88c31639bb24c73383a4528a5b77066e805148blpleahy        break;
3598a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3599a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3600a88c31639bb24c73383a4528a5b77066e805148blpleahy
3601a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3602a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Initialize the receive structures
3603a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3604a88c31639bb24c73383a4528a5b77066e805148blpleahy    pBuffer = (UINT8 *)&pPort[ 1 ];
3605a88c31639bb24c73383a4528a5b77066e805148blpleahy    pBuffer = &pBuffer[ ESL_STRUCTURE_ALIGNMENT_BYTES ];
3606a88c31639bb24c73383a4528a5b77066e805148blpleahy    pBuffer = (UINT8 *)( ESL_STRUCTURE_ALIGNMENT_MASK & (UINTN)pBuffer );
3607a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIo = (ESL_IO_MGMT *)pBuffer;
3608a88c31639bb24c73383a4528a5b77066e805148blpleahy    if (( 0 != pSocketBinding->RxIo )
3609a88c31639bb24c73383a4528a5b77066e805148blpleahy      && ( NULL != pSocket->pApi->pfnRxComplete )) {
3610a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EslSocketIoInit ( pPort,
3611a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 &pIo,
3612a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 pSocketBinding->RxIo,
3613a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 &pPort->pRxFree,
3614a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 DebugFlags | DEBUG_POOL,
3615a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 "receive",
3616a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 pSocket->pApi->pfnRxComplete );
3617a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( EFI_ERROR ( Status )) {
3618a88c31639bb24c73383a4528a5b77066e805148blpleahy        break;
3619a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3620a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3621a88c31639bb24c73383a4528a5b77066e805148blpleahy
3622a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3623a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Initialize the urgent transmit structures
3624a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3625a88c31639bb24c73383a4528a5b77066e805148blpleahy    if (( 0 != pSocketBinding->TxIoUrgent )
3626a88c31639bb24c73383a4528a5b77066e805148blpleahy      && ( NULL != pSocket->pApi->pfnTxOobComplete )) {
3627a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EslSocketIoInit ( pPort,
3628a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 &pIo,
3629a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 pSocketBinding->TxIoUrgent,
3630a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 &pPort->pTxOobFree,
3631a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 DebugFlags | DEBUG_POOL,
3632a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 "urgent transmit",
3633a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 pSocket->pApi->pfnTxOobComplete );
3634a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( EFI_ERROR ( Status )) {
3635a88c31639bb24c73383a4528a5b77066e805148blpleahy        break;
3636a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3637a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3638a88c31639bb24c73383a4528a5b77066e805148blpleahy
3639a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3640a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Initialize the normal transmit structures
3641a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3642a88c31639bb24c73383a4528a5b77066e805148blpleahy    if (( 0 != pSocketBinding->TxIoNormal )
3643a88c31639bb24c73383a4528a5b77066e805148blpleahy      && ( NULL != pSocket->pApi->pfnTxComplete )) {
3644a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EslSocketIoInit ( pPort,
3645a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 &pIo,
3646a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 pSocketBinding->TxIoNormal,
3647a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 &pPort->pTxFree,
3648a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 DebugFlags | DEBUG_POOL,
3649a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 "normal transmit",
3650a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 pSocket->pApi->pfnTxComplete );
3651a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( EFI_ERROR ( Status )) {
3652a88c31639bb24c73383a4528a5b77066e805148blpleahy        break;
3653a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3654a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3655a88c31639bb24c73383a4528a5b77066e805148blpleahy
3656a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3657a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Add this port to the socket
3658a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3659a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->pLinkSocket = pSocket->pPortList;
3660a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->pPortList = pPort;
3661a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DebugFlags,
3662a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Socket adding port: 0x%08x\r\n",
3663a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket,
3664a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort ));
3665a88c31639bb24c73383a4528a5b77066e805148blpleahy
3666a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3667a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Add this port to the service
3668a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3669a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->pLinkService = pService->pPortList;
3670a88c31639bb24c73383a4528a5b77066e805148blpleahy    pService->pPortList = pPort;
3671a88c31639bb24c73383a4528a5b77066e805148blpleahy
3672a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3673a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Return the port
3674a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3675a88c31639bb24c73383a4528a5b77066e805148blpleahy    *ppPort = pPort;
3676a88c31639bb24c73383a4528a5b77066e805148blpleahy    break;
3677a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3678a88c31639bb24c73383a4528a5b77066e805148blpleahy
3679a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3680a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Clean up after the error if necessary
3681a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3682a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( EFI_ERROR ( Status )) {
3683a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( NULL != pPort ) {
3684a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3685a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Close the port
3686a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3687a88c31639bb24c73383a4528a5b77066e805148blpleahy      EslSocketPortClose ( pPort );
3688a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3689a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
3690a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3691a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Close the port if necessary
3692a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3693a88c31639bb24c73383a4528a5b77066e805148blpleahy      pServiceBinding = pService->pServiceBinding;
3694a88c31639bb24c73383a4528a5b77066e805148blpleahy      TempStatus = pServiceBinding->DestroyChild ( pServiceBinding,
3695a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                   ChildHandle );
3696a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( !EFI_ERROR ( TempStatus )) {
3697a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_BIND | DEBUG_POOL,
3698a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "0x%08x: %s port handle destroyed\r\n",
3699a88c31639bb24c73383a4528a5b77066e805148blpleahy                  ChildHandle,
3700a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pSocketBinding->pName ));
3701a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3702a88c31639bb24c73383a4528a5b77066e805148blpleahy      else {
3703a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_ERROR | DEBUG_BIND | DEBUG_POOL,
3704a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "ERROR - Failed to destroy the %s port handle 0x%08x, Status: %r\r\n",
3705a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pSocketBinding->pName,
3706a88c31639bb24c73383a4528a5b77066e805148blpleahy                  ChildHandle,
3707a88c31639bb24c73383a4528a5b77066e805148blpleahy                  TempStatus ));
3708a88c31639bb24c73383a4528a5b77066e805148blpleahy        ASSERT ( EFI_SUCCESS == TempStatus );
3709a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3710a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3711a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3712a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3713a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
3714a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3715a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
3716a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
3717a88c31639bb24c73383a4528a5b77066e805148blpleahy}
3718a88c31639bb24c73383a4528a5b77066e805148blpleahy
3719a88c31639bb24c73383a4528a5b77066e805148blpleahy
3720beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Close a port.
3721a88c31639bb24c73383a4528a5b77066e805148blpleahy
3722a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine releases the resources allocated by ::EslSocketPortAllocate.
3723a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine calls ESL_PROTOCOL_API::pfnPortClose to release the network
3724a88c31639bb24c73383a4528a5b77066e805148blpleahy  specific resources.
3725a88c31639bb24c73383a4528a5b77066e805148blpleahy
3726a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by:
3727a88c31639bb24c73383a4528a5b77066e805148blpleahy  <ul>
3728a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslSocketPortAllocate - Port initialization failure</li>
3729a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslSocketPortCloseRxDone - Last step of close processing</li>
3730a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslTcp4ConnectComplete - Connection failure and reducing the port list to a single port</li>
3731a88c31639bb24c73383a4528a5b77066e805148blpleahy  </ul>
3732a88c31639bb24c73383a4528a5b77066e805148blpleahy  See the \ref PortCloseStateMachine section.
37330164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
3734beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pPort       Address of an ::ESL_PORT structure.
3735a88c31639bb24c73383a4528a5b77066e805148blpleahy
3736a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS     The port is closed
3737a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval other           Port close error
3738a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
3739a88c31639bb24c73383a4528a5b77066e805148blpleahyEFI_STATUS
3740a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketPortClose (
3741a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort
3742a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
3743a88c31639bb24c73383a4528a5b77066e805148blpleahy{
3744a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINTN DebugFlags;
3745a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_LAYER * pLayer;
3746a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pPacket;
3747a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPreviousPort;
3748a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SERVICE * pService;
3749a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;
3750a88c31639bb24c73383a4528a5b77066e805148blpleahy  CONST ESL_SOCKET_BINDING * pSocketBinding;
3751a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
3752a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
37530164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
3754a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
3755a88c31639bb24c73383a4528a5b77066e805148blpleahy
3756a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3757a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Verify the socket layer synchronization
3758a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3759a88c31639bb24c73383a4528a5b77066e805148blpleahy  VERIFY_TPL ( TPL_SOCKETS );
3760a88c31639bb24c73383a4528a5b77066e805148blpleahy
3761a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3762a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Locate the port in the socket list
3763a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3764a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
3765a88c31639bb24c73383a4528a5b77066e805148blpleahy  pLayer = &mEslLayer;
3766a88c31639bb24c73383a4528a5b77066e805148blpleahy  DebugFlags = pPort->DebugFlags;
3767a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = pPort->pSocket;
3768a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPreviousPort = pSocket->pPortList;
3769a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( pPreviousPort == pPort ) {
3770a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3771a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Remove this port from the head of the socket list
3772a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3773a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->pPortList = pPort->pLinkSocket;
3774a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3775a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
3776a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3777a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Locate the port in the middle of the socket list
3778a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
3779a88c31639bb24c73383a4528a5b77066e805148blpleahy    while (( NULL != pPreviousPort )
3780a88c31639bb24c73383a4528a5b77066e805148blpleahy      && ( pPreviousPort->pLinkSocket != pPort )) {
3781a88c31639bb24c73383a4528a5b77066e805148blpleahy      pPreviousPort = pPreviousPort->pLinkSocket;
3782a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3783a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( NULL != pPreviousPort ) {
3784a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3785a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Remove the port from the middle of the socket list
3786a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3787a88c31639bb24c73383a4528a5b77066e805148blpleahy      pPreviousPort->pLinkSocket = pPort->pLinkSocket;
3788a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3789a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3790a88c31639bb24c73383a4528a5b77066e805148blpleahy
3791a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3792a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Locate the port in the service list
3793a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Note that the port may not be in the service list
3794a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  if the service has been shutdown.
3795a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3796a88c31639bb24c73383a4528a5b77066e805148blpleahy  pService = pPort->pService;
3797a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL != pService ) {
3798a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPreviousPort = pService->pPortList;
3799a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( pPreviousPort == pPort ) {
3800a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3801a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Remove this port from the head of the service list
3802a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3803a88c31639bb24c73383a4528a5b77066e805148blpleahy      pService->pPortList = pPort->pLinkService;
3804a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3805a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
3806a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3807a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Locate the port in the middle of the service list
3808a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
3809a88c31639bb24c73383a4528a5b77066e805148blpleahy      while (( NULL != pPreviousPort )
3810a88c31639bb24c73383a4528a5b77066e805148blpleahy        && ( pPreviousPort->pLinkService != pPort )) {
3811a88c31639bb24c73383a4528a5b77066e805148blpleahy        pPreviousPort = pPreviousPort->pLinkService;
3812a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3813a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( NULL != pPreviousPort ) {
3814a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
3815a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Remove the port from the middle of the service list
3816a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
3817a88c31639bb24c73383a4528a5b77066e805148blpleahy        pPreviousPort->pLinkService = pPort->pLinkService;
3818a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
3819a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3820a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3821a88c31639bb24c73383a4528a5b77066e805148blpleahy
3822a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3823a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Empty the urgent receive queue
3824a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3825a88c31639bb24c73383a4528a5b77066e805148blpleahy  while ( NULL != pSocket->pRxOobPacketListHead ) {
3826a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPacket = pSocket->pRxOobPacketListHead;
3827a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->pRxOobPacketListHead = pPacket->pNext;
3828a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->pApi->pfnPacketFree ( pPacket, &pSocket->RxOobBytes );
3829a88c31639bb24c73383a4528a5b77066e805148blpleahy    EslSocketPacketFree ( pPacket, DEBUG_RX );
3830a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3831a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket->pRxOobPacketListTail = NULL;
3832a88c31639bb24c73383a4528a5b77066e805148blpleahy  ASSERT ( 0 == pSocket->RxOobBytes );
3833a88c31639bb24c73383a4528a5b77066e805148blpleahy
3834a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3835a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Empty the receive queue
3836a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3837a88c31639bb24c73383a4528a5b77066e805148blpleahy  while ( NULL != pSocket->pRxPacketListHead ) {
3838a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPacket = pSocket->pRxPacketListHead;
3839a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->pRxPacketListHead = pPacket->pNext;
3840a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->pApi->pfnPacketFree ( pPacket, &pSocket->RxBytes );
3841a88c31639bb24c73383a4528a5b77066e805148blpleahy    EslSocketPacketFree ( pPacket, DEBUG_RX );
3842a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3843a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket->pRxPacketListTail = NULL;
3844a88c31639bb24c73383a4528a5b77066e805148blpleahy  ASSERT ( 0 == pSocket->RxBytes );
3845a88c31639bb24c73383a4528a5b77066e805148blpleahy
3846a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3847a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Empty the receive free queue
3848a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3849a88c31639bb24c73383a4528a5b77066e805148blpleahy  while ( NULL != pSocket->pRxFree ) {
3850a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPacket = pSocket->pRxFree;
3851a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->pRxFree = pPacket->pNext;
3852a88c31639bb24c73383a4528a5b77066e805148blpleahy    EslSocketPacketFree ( pPacket, DEBUG_RX );
3853a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3854a88c31639bb24c73383a4528a5b77066e805148blpleahy
3855a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3856a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Release the network specific resources
3857a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3858a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL != pSocket->pApi->pfnPortClose ) {
3859a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = pSocket->pApi->pfnPortClose ( pPort );
3860a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3861a88c31639bb24c73383a4528a5b77066e805148blpleahy
3862a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3863a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Done with the normal transmit events
3864a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3865a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EslSocketIoFree ( pPort,
3866a88c31639bb24c73383a4528a5b77066e805148blpleahy                             &pPort->pTxFree,
3867a88c31639bb24c73383a4528a5b77066e805148blpleahy                             DebugFlags | DEBUG_POOL,
3868a88c31639bb24c73383a4528a5b77066e805148blpleahy                             "normal transmit" );
3869a88c31639bb24c73383a4528a5b77066e805148blpleahy
3870a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3871a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Done with the urgent transmit events
3872a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3873a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EslSocketIoFree ( pPort,
3874a88c31639bb24c73383a4528a5b77066e805148blpleahy                             &pPort->pTxOobFree,
3875a88c31639bb24c73383a4528a5b77066e805148blpleahy                             DebugFlags | DEBUG_POOL,
3876a88c31639bb24c73383a4528a5b77066e805148blpleahy                             "urgent transmit" );
3877a88c31639bb24c73383a4528a5b77066e805148blpleahy
3878a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3879a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Done with the receive events
3880a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3881a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EslSocketIoFree ( pPort,
3882a88c31639bb24c73383a4528a5b77066e805148blpleahy                             &pPort->pRxFree,
3883a88c31639bb24c73383a4528a5b77066e805148blpleahy                             DebugFlags | DEBUG_POOL,
3884a88c31639bb24c73383a4528a5b77066e805148blpleahy                             "receive" );
3885a88c31639bb24c73383a4528a5b77066e805148blpleahy
3886a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3887a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Done with the lower layer network protocol
3888a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3889a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocketBinding = pPort->pSocketBinding;
3890a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL != pPort->pProtocol.v ) {
3891a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = gBS->CloseProtocol ( pPort->Handle,
3892a88c31639bb24c73383a4528a5b77066e805148blpleahy                                  pSocketBinding->pNetworkProtocolGuid,
3893a88c31639bb24c73383a4528a5b77066e805148blpleahy                                  pLayer->ImageHandle,
3894a88c31639bb24c73383a4528a5b77066e805148blpleahy                                  NULL );
3895a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( !EFI_ERROR ( Status )) {
3896a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DebugFlags,
3897a88c31639bb24c73383a4528a5b77066e805148blpleahy                "0x%08x: Network protocol GUID closed on controller 0x%08x\r\n",
3898a88c31639bb24c73383a4528a5b77066e805148blpleahy                pPort->pProtocol.v,
3899a88c31639bb24c73383a4528a5b77066e805148blpleahy                pPort->Handle ));
3900a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3901a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
3902a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_ERROR | DebugFlags,
3903a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - Failed to close network protocol GUID on controller 0x%08x, Status: %r\r\n",
3904a88c31639bb24c73383a4528a5b77066e805148blpleahy                pPort->Handle,
3905a88c31639bb24c73383a4528a5b77066e805148blpleahy                Status ));
3906a88c31639bb24c73383a4528a5b77066e805148blpleahy      ASSERT ( EFI_SUCCESS == Status );
3907a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3908a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3909a88c31639bb24c73383a4528a5b77066e805148blpleahy
3910a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3911a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Done with the network port
3912a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3913a88c31639bb24c73383a4528a5b77066e805148blpleahy  pServiceBinding = pPort->pServiceBinding;
3914a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL != pPort->Handle ) {
3915a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = pServiceBinding->DestroyChild ( pServiceBinding,
3916a88c31639bb24c73383a4528a5b77066e805148blpleahy                                             pPort->Handle );
3917a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( !EFI_ERROR ( Status )) {
3918a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DebugFlags | DEBUG_POOL,
3919a88c31639bb24c73383a4528a5b77066e805148blpleahy                "0x%08x: %s port handle destroyed\r\n",
3920a88c31639bb24c73383a4528a5b77066e805148blpleahy                pPort->Handle,
3921a88c31639bb24c73383a4528a5b77066e805148blpleahy                pSocketBinding->pName ));
3922a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3923a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
3924a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,
3925a88c31639bb24c73383a4528a5b77066e805148blpleahy                "ERROR - Failed to destroy the %s port handle, Status: %r\r\n",
3926a88c31639bb24c73383a4528a5b77066e805148blpleahy                pSocketBinding->pName,
3927a88c31639bb24c73383a4528a5b77066e805148blpleahy                Status ));
3928a88c31639bb24c73383a4528a5b77066e805148blpleahy      ASSERT ( EFI_SUCCESS == Status );
3929a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
3930a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3931a88c31639bb24c73383a4528a5b77066e805148blpleahy
3932a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3933a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Release the port structure
3934a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3935a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = gBS->FreePool ( pPort );
3936a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( !EFI_ERROR ( Status )) {
3937a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DebugFlags | DEBUG_POOL,
3938a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Free pPort, %d bytes\r\n",
3939a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort,
3940a88c31639bb24c73383a4528a5b77066e805148blpleahy              sizeof ( *pPort )));
3941a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3942a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
3943a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,
3944a88c31639bb24c73383a4528a5b77066e805148blpleahy              "ERROR - Failed to free pPort: 0x%08x, Status: %r\r\n",
3945a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort,
3946a88c31639bb24c73383a4528a5b77066e805148blpleahy              Status ));
3947a88c31639bb24c73383a4528a5b77066e805148blpleahy    ASSERT ( EFI_SUCCESS == Status );
3948a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3949a88c31639bb24c73383a4528a5b77066e805148blpleahy
3950a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3951a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Mark the socket as closed if necessary
3952a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3953a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL == pSocket->pPortList ) {
3954a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket->State = SOCKET_STATE_CLOSED;
3955a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
3956a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Socket State: SOCKET_STATE_CLOSED\r\n",
3957a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket ));
3958a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
3959a88c31639bb24c73383a4528a5b77066e805148blpleahy
3960a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3961a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
3962a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
3963a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
3964a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
3965a88c31639bb24c73383a4528a5b77066e805148blpleahy}
3966a88c31639bb24c73383a4528a5b77066e805148blpleahy
3967a88c31639bb24c73383a4528a5b77066e805148blpleahy
3968beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Port close state 3.
3969a88c31639bb24c73383a4528a5b77066e805148blpleahy
3970a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine attempts to complete the port close operation.
3971a88c31639bb24c73383a4528a5b77066e805148blpleahy
3972a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by the TCP layer upon completion of
3973a88c31639bb24c73383a4528a5b77066e805148blpleahy  the close operation and by ::EslSocketPortCloseTxDone.
3974a88c31639bb24c73383a4528a5b77066e805148blpleahy  See the \ref PortCloseStateMachine section.
3975a88c31639bb24c73383a4528a5b77066e805148blpleahy
3976beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  Event     The close completion event
3977beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pPort     Address of an ::ESL_PORT structure.
3978a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
3979a88c31639bb24c73383a4528a5b77066e805148blpleahyVOID
3980a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketPortCloseComplete (
3981a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN EFI_EVENT Event,
3982a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort
3983a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
3984a88c31639bb24c73383a4528a5b77066e805148blpleahy{
3985a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IO_MGMT * pIo;
3986a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
3987a88c31639bb24c73383a4528a5b77066e805148blpleahy
3988a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
3989a88c31639bb24c73383a4528a5b77066e805148blpleahy  VERIFY_AT_TPL ( TPL_SOCKETS );
3990a88c31639bb24c73383a4528a5b77066e805148blpleahy
3991a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Update the port state
3992a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPort->State = PORT_STATE_CLOSE_DONE;
3993a88c31639bb24c73383a4528a5b77066e805148blpleahy  DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
3994a88c31639bb24c73383a4528a5b77066e805148blpleahy            "0x%08x: Port Close State: PORT_STATE_CLOSE_DONE\r\n",
3995a88c31639bb24c73383a4528a5b77066e805148blpleahy            pPort ));
3996a88c31639bb24c73383a4528a5b77066e805148blpleahy
3997a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Shutdown the receive operation on the port
3998a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL != pPort->pfnRxCancel ) {
3999a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIo = pPort->pRxActive;
4000a88c31639bb24c73383a4528a5b77066e805148blpleahy    while ( NULL != pIo ) {
4001a88c31639bb24c73383a4528a5b77066e805148blpleahy      EslSocketRxCancel ( pPort, pIo );
4002a88c31639bb24c73383a4528a5b77066e805148blpleahy      pIo = pIo->pNext;
4003d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
4004d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
4005a88c31639bb24c73383a4528a5b77066e805148blpleahy
4006a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Determine if the receive operation is pending
4007a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EslSocketPortCloseRxDone ( pPort );
4008d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
4009b81cc7d6249671a2c1e36f6c8ac01da0e0b7c612Olivier Martin  --Status;
4010d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
4011d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4012d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4013beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Port close state 4.
4014d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4015a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine determines the state of the receive operations and
4016a88c31639bb24c73383a4528a5b77066e805148blpleahy  continues the close operation after the pending receive operations
4017a88c31639bb24c73383a4528a5b77066e805148blpleahy  are cancelled.
4018d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4019a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by
4020a88c31639bb24c73383a4528a5b77066e805148blpleahy  <ul>
4021a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslSocketPortCloseComplete</li>
4022a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslSocketPortCloseTxDone</li>
4023a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslSocketRxComplete</li>
4024a88c31639bb24c73383a4528a5b77066e805148blpleahy  </ul>
4025a88c31639bb24c73383a4528a5b77066e805148blpleahy  to determine the state of the receive operations.
4026a88c31639bb24c73383a4528a5b77066e805148blpleahy  See the \ref PortCloseStateMachine section.
4027d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4028beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pPort       Address of an ::ESL_PORT structure.
4029a88c31639bb24c73383a4528a5b77066e805148blpleahy
4030a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS         The port is closed
4031a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_NOT_READY       The port is still closing
4032a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
4033a88c31639bb24c73383a4528a5b77066e805148blpleahy                              most likely the routine was called already.
4034a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
4035d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
4036a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketPortCloseRxDone (
4037a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort
4038d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
4039d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
4040d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
4041d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4042d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
4043d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4044d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4045a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Verify the socket layer synchronization
4046d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4047a88c31639bb24c73383a4528a5b77066e805148blpleahy  VERIFY_TPL ( TPL_SOCKETS );
4048d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4049d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4050a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Verify that the port is closing
4051d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4052a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_ALREADY_STARTED;
4053a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( PORT_STATE_CLOSE_DONE == pPort->State ) {
4054a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4055a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Determine if the receive operation is pending
4056a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4057a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = EFI_NOT_READY;
4058a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( NULL == pPort->pRxActive ) {
4059a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
4060a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  The receive operation is complete
4061a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Update the port state
4062a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
4063a88c31639bb24c73383a4528a5b77066e805148blpleahy      pPort->State = PORT_STATE_CLOSE_RX_DONE;
4064a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
4065a88c31639bb24c73383a4528a5b77066e805148blpleahy                "0x%08x: Port Close State: PORT_STATE_CLOSE_RX_DONE\r\n",
4066a88c31639bb24c73383a4528a5b77066e805148blpleahy                pPort ));
4067a88c31639bb24c73383a4528a5b77066e805148blpleahy
4068a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
4069a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Complete the port close operation
4070a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
4071a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EslSocketPortClose ( pPort );
4072a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4073a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
4074a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG_CODE_BEGIN ();
4075a88c31639bb24c73383a4528a5b77066e805148blpleahy      {
4076a88c31639bb24c73383a4528a5b77066e805148blpleahy        ESL_IO_MGMT * pIo;
4077a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
4078a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Display the outstanding receive operations
4079a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
4080a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
4081a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "0x%08x: Port Close: Receive still pending!\r\n",
4082a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pPort ));
4083a88c31639bb24c73383a4528a5b77066e805148blpleahy        pIo = pPort->pRxActive;
4084a88c31639bb24c73383a4528a5b77066e805148blpleahy        while ( NULL != pIo ) {
4085a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
4086a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "0x%08x: Packet pending on network adapter\r\n",
4087a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIo->pPacket ));
4088a88c31639bb24c73383a4528a5b77066e805148blpleahy          pIo = pIo->pNext;
4089a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
4090a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
4091a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG_CODE_END ( );
4092a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4093a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4094d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4095d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4096d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
4097d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4098d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
4099d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
4100d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
4101d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4102d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4103beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Start the close operation on a port, state 1.
4104a88c31639bb24c73383a4528a5b77066e805148blpleahy
4105a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine marks the port as closed and initiates the \ref
4106a88c31639bb24c73383a4528a5b77066e805148blpleahy  PortCloseStateMachine. The first step is to allow the \ref
4107a88c31639bb24c73383a4528a5b77066e805148blpleahy  TransmitEngine to run down.
4108d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4109a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by ::EslSocketCloseStart to initiate the socket
4110a88c31639bb24c73383a4528a5b77066e805148blpleahy  network specific close operation on the socket.
4111a88c31639bb24c73383a4528a5b77066e805148blpleahy
4112beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pPort       Address of an ::ESL_PORT structure.
4113beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  bCloseNow   Set TRUE to abort active transfers
4114beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  DebugFlags  Flags for debug messages
4115d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4116a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS         The port is closed, not normally returned
4117a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_NOT_READY       The port has started the closing process
4118a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
4119a88c31639bb24c73383a4528a5b77066e805148blpleahy                              most likely the routine was called already.
4120a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
4121d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
4122a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketPortCloseStart (
4123a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort,
4124a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN BOOLEAN bCloseNow,
4125d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN UINTN DebugFlags
4126d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
4127d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
4128a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
4129d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
4130d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4131d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
4132d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4133d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4134a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Verify the socket layer synchronization
4135d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4136a88c31639bb24c73383a4528a5b77066e805148blpleahy  VERIFY_TPL ( TPL_SOCKETS );
4137a88c31639bb24c73383a4528a5b77066e805148blpleahy
4138a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4139a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Mark the port as closing
4140a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4141a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_ALREADY_STARTED;
4142a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = pPort->pSocket;
4143a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket->errno = EALREADY;
4144a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( PORT_STATE_CLOSE_STARTED > pPort->State ) {
4145a88c31639bb24c73383a4528a5b77066e805148blpleahy
4146a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4147a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Update the port state
4148a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4149a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->State = PORT_STATE_CLOSE_STARTED;
4150a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
4151a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Port Close State: PORT_STATE_CLOSE_STARTED\r\n",
4152a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort ));
4153a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->bCloseNow = bCloseNow;
4154a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->DebugFlags = DebugFlags;
4155a88c31639bb24c73383a4528a5b77066e805148blpleahy
4156a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4157a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Determine if transmits are complete
4158a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4159a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = EslSocketPortCloseTxDone ( pPort );
4160d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
4161d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4162d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4163d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
4164d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4165d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
4166d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
4167d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
4168d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4169d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4170beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Port close state 2.
4171d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4172a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine determines the state of the transmit engine and
4173a88c31639bb24c73383a4528a5b77066e805148blpleahy  continue the close operation after the transmission is complete.
4174a88c31639bb24c73383a4528a5b77066e805148blpleahy  The next step is to stop the \ref ReceiveEngine.
4175a88c31639bb24c73383a4528a5b77066e805148blpleahy  See the \ref PortCloseStateMachine section.
4176d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4177a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by ::EslSocketPortCloseStart to determine
4178a88c31639bb24c73383a4528a5b77066e805148blpleahy  if the transmission is complete.
4179d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4180beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pPort           Address of an ::ESL_PORT structure.
4181d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4182a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_SUCCESS         The port is closed, not normally returned
4183a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_NOT_READY       The port is still closing
4184a88c31639bb24c73383a4528a5b77066e805148blpleahy  @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
4185a88c31639bb24c73383a4528a5b77066e805148blpleahy                              most likely the routine was called already.
4186d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4187a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
4188d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
4189a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketPortCloseTxDone (
4190a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort
4191d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
4192d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
4193a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IO_MGMT * pIo;
4194a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
4195d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
4196d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4197a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
4198d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4199d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4200a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Verify the socket layer synchronization
4201d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4202a88c31639bb24c73383a4528a5b77066e805148blpleahy  VERIFY_TPL ( TPL_SOCKETS );
4203d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4204d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4205a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  All transmissions are complete or must be stopped
4206a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Mark the port as TX complete
4207d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4208a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_ALREADY_STARTED;
4209a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( PORT_STATE_CLOSE_STARTED == pPort->State ) {
4210d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
4211a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Verify that the transmissions are complete
4212d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
4213a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket = pPort->pSocket;
4214a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( pPort->bCloseNow
4215a88c31639bb24c73383a4528a5b77066e805148blpleahy         || ( EFI_SUCCESS != pSocket->TxError )
4216a88c31639bb24c73383a4528a5b77066e805148blpleahy         || (( NULL == pPort->pTxActive )
4217a88c31639bb24c73383a4528a5b77066e805148blpleahy                && ( NULL == pPort->pTxOobActive ))) {
4218d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
4219a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Update the port state
4220d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
4221a88c31639bb24c73383a4528a5b77066e805148blpleahy      pPort->State = PORT_STATE_CLOSE_TX_DONE;
4222a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
4223a88c31639bb24c73383a4528a5b77066e805148blpleahy                "0x%08x: Port Close State: PORT_STATE_CLOSE_TX_DONE\r\n",
4224a88c31639bb24c73383a4528a5b77066e805148blpleahy                pPort ));
4225d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4226d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
4227a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Close the port
4228a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Skip the close operation if the port is not configured
4229d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
4230a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_SUCCESS;
4231a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket = pPort->pSocket;
4232a88c31639bb24c73383a4528a5b77066e805148blpleahy      if (( pPort->bConfigured )
4233a88c31639bb24c73383a4528a5b77066e805148blpleahy        && ( NULL != pSocket->pApi->pfnPortCloseOp )) {
4234a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
4235a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Start the close operation
4236a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
4237a88c31639bb24c73383a4528a5b77066e805148blpleahy          Status = pSocket->pApi->pfnPortCloseOp ( pPort );
4238a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
4239a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "0x%08x: Port Close: Close operation still pending!\r\n",
4240a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPort ));
4241a88c31639bb24c73383a4528a5b77066e805148blpleahy          ASSERT ( EFI_SUCCESS == Status );
4242d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
4243a88c31639bb24c73383a4528a5b77066e805148blpleahy      else {
4244d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
4245a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  The receive operation is complete
4246a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Update the port state
4247d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
4248a88c31639bb24c73383a4528a5b77066e805148blpleahy        EslSocketPortCloseComplete ( NULL, pPort );
4249d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
4250a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4251a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
4252d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
4253a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Transmissions are still active, exit
4254d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
4255a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_NOT_READY;
4256a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = EAGAIN;
4257a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG_CODE_BEGIN ( );
4258a88c31639bb24c73383a4528a5b77066e805148blpleahy      {
4259a88c31639bb24c73383a4528a5b77066e805148blpleahy        ESL_PACKET * pPacket;
4260d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4261a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
4262a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "0x%08x: Port Close: Transmits are still pending!\r\n",
4263a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pPort ));
4264d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4265a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
4266a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Display the pending urgent transmit packets
4267a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
4268a88c31639bb24c73383a4528a5b77066e805148blpleahy        pPacket = pSocket->pTxOobPacketListHead;
4269a88c31639bb24c73383a4528a5b77066e805148blpleahy        while ( NULL != pPacket ) {
4270a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
4271a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "0x%08x: Packet pending on urgent TX list, %d bytes\r\n",
4272a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPacket,
4273a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPacket->PacketSize ));
4274a88c31639bb24c73383a4528a5b77066e805148blpleahy          pPacket = pPacket->pNext;
4275a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
4276d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4277a88c31639bb24c73383a4528a5b77066e805148blpleahy        pIo = pPort->pTxOobActive;
4278a88c31639bb24c73383a4528a5b77066e805148blpleahy        while ( NULL != pIo ) {
4279a88c31639bb24c73383a4528a5b77066e805148blpleahy          pPacket = pIo->pPacket;
4280a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
4281a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "0x%08x: Packet active %d bytes, pIo: 0x%08x\r\n",
4282a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPacket,
4283a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPacket->PacketSize,
4284a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIo ));
4285a88c31639bb24c73383a4528a5b77066e805148blpleahy          pIo = pIo->pNext;
4286a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
4287d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4288a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
4289a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Display the pending normal transmit packets
4290a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
4291a88c31639bb24c73383a4528a5b77066e805148blpleahy        pPacket = pSocket->pTxPacketListHead;
4292a88c31639bb24c73383a4528a5b77066e805148blpleahy        while ( NULL != pPacket ) {
4293a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
4294a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "0x%08x: Packet pending on normal TX list, %d bytes\r\n",
4295a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPacket,
4296a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPacket->PacketSize ));
4297a88c31639bb24c73383a4528a5b77066e805148blpleahy          pPacket = pPacket->pNext;
4298a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
4299d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4300a88c31639bb24c73383a4528a5b77066e805148blpleahy        pIo = pPort->pTxActive;
4301a88c31639bb24c73383a4528a5b77066e805148blpleahy        while ( NULL != pIo ) {
4302a88c31639bb24c73383a4528a5b77066e805148blpleahy          pPacket = pIo->pPacket;
4303a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
4304a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "0x%08x: Packet active %d bytes, pIo: 0x%08x\r\n",
4305a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPacket,
4306a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPacket->PacketSize,
4307a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pIo ));
4308a88c31639bb24c73383a4528a5b77066e805148blpleahy          pIo = pIo->pNext;
4309a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
4310d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
4311a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG_CODE_END ();
4312a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4313a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4314d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4315d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4316d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
4317d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4318a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
4319d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
4320d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
4321d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4322d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4323beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Receive data from a network connection.
4324d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4325a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine calls the network specific routine to remove the
4326a88c31639bb24c73383a4528a5b77066e805148blpleahy  next portion of data from the receive queue and return it to the
4327a88c31639bb24c73383a4528a5b77066e805148blpleahy  caller.
4328d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4329a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::recvfrom routine calls this routine to determine if any data
4330a88c31639bb24c73383a4528a5b77066e805148blpleahy  is received from the remote system.  Note that the other routines
4331a88c31639bb24c73383a4528a5b77066e805148blpleahy  ::recv and ::read are layered on top of ::recvfrom.
4332a88c31639bb24c73383a4528a5b77066e805148blpleahy
4333beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
4334beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      Flags           Message control flags
4335beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      BufferLength    Length of the the buffer
4336beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      pBuffer         Address of a buffer to receive the data.
4337beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]      pDataLength     Number of received data bytes in the buffer.
4338beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out]     pAddress        Network address to receive the remote system address
4339beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in,out]  pAddressLength  Length of the remote network address structure
4340beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out]     pErrno          Address to receive the errno value upon completion.
4341d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4342d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_SUCCESS - Socket data successfully received
4343beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
4344d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
4345d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEslSocketReceive (
4346d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
4347d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN INT32 Flags,
4348d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN size_t BufferLength,
4349d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN UINT8 * pBuffer,
4350d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  OUT size_t * pDataLength,
4351d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  OUT struct sockaddr * pAddress,
4352d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN OUT socklen_t * pAddressLength,
4353d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int * pErrno
4354d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
4355d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
4356a88c31639bb24c73383a4528a5b77066e805148blpleahy  union {
4357a88c31639bb24c73383a4528a5b77066e805148blpleahy    struct sockaddr_in v4;
4358a88c31639bb24c73383a4528a5b77066e805148blpleahy    struct sockaddr_in6 v6;
4359a88c31639bb24c73383a4528a5b77066e805148blpleahy  } Addr;
4360a88c31639bb24c73383a4528a5b77066e805148blpleahy  socklen_t AddressLength;
4361a88c31639bb24c73383a4528a5b77066e805148blpleahy  BOOLEAN bConsumePacket;
4362a88c31639bb24c73383a4528a5b77066e805148blpleahy  BOOLEAN bUrgentQueue;
4363a88c31639bb24c73383a4528a5b77066e805148blpleahy  size_t DataLength;
4364a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pNextPacket;
4365a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pPacket;
4366a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
4367a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET ** ppQueueHead;
4368a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET ** ppQueueTail;
4369a88c31639bb24c73383a4528a5b77066e805148blpleahy  struct sockaddr * pRemoteAddress;
4370a88c31639bb24c73383a4528a5b77066e805148blpleahy  size_t * pRxDataBytes;
4371a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
4372a88c31639bb24c73383a4528a5b77066e805148blpleahy  size_t SkipBytes;
4373d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
4374d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_TPL TplPrevious;
4375d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4376d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
4377d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4378d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4379d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Assume success
4380d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4381d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Status = EFI_SUCCESS;
4382d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4383d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4384d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Validate the socket
4385d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
4386d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pSocket = NULL;
4387d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pSocketProtocol ) {
4388d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
4389d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4390d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
4391a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Validate the return address parameters
4392d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
4393a88c31639bb24c73383a4528a5b77066e805148blpleahy    if (( NULL == pAddress ) || ( NULL != pAddressLength )) {
4394d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
4395a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Return the transmit error if necessary
4396d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
4397a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( EFI_SUCCESS != pSocket->TxError ) {
4398a88c31639bb24c73383a4528a5b77066e805148blpleahy        pSocket->errno = EIO;
4399a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = pSocket->TxError;
4400a88c31639bb24c73383a4528a5b77066e805148blpleahy        pSocket->TxError = EFI_SUCCESS;
4401a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
4402a88c31639bb24c73383a4528a5b77066e805148blpleahy      else {
4403d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
4404a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Verify the socket state
4405d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
4406a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = EslSocketIsConfigured ( pSocket );
4407a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( !EFI_ERROR ( Status )) {
4408d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
4409a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Validate the buffer length
4410d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
4411a88c31639bb24c73383a4528a5b77066e805148blpleahy          if (( NULL == pDataLength )
4412a88c31639bb24c73383a4528a5b77066e805148blpleahy            || ( NULL == pBuffer )) {
4413a88c31639bb24c73383a4528a5b77066e805148blpleahy            if ( NULL == pDataLength ) {
4414a88c31639bb24c73383a4528a5b77066e805148blpleahy              DEBUG (( DEBUG_RX,
4415a88c31639bb24c73383a4528a5b77066e805148blpleahy                        "ERROR - pDataLength is NULL!\r\n" ));
4416a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
4417a88c31639bb24c73383a4528a5b77066e805148blpleahy            else {
4418a88c31639bb24c73383a4528a5b77066e805148blpleahy              DEBUG (( DEBUG_RX,
4419a88c31639bb24c73383a4528a5b77066e805148blpleahy                        "ERROR - pBuffer is NULL!\r\n" ));
4420a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
4421d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            Status = EFI_INVALID_PARAMETER;
4422a88c31639bb24c73383a4528a5b77066e805148blpleahy            pSocket->errno = EFAULT;
4423a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
4424a88c31639bb24c73383a4528a5b77066e805148blpleahy          else {
44251c34b250f66ba304a4da510404caa827af2ad91elpleahy            //
4426a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Verify the API
44271c34b250f66ba304a4da510404caa827af2ad91elpleahy            //
4428a88c31639bb24c73383a4528a5b77066e805148blpleahy            if ( NULL == pSocket->pApi->pfnReceive ) {
4429a88c31639bb24c73383a4528a5b77066e805148blpleahy              Status = EFI_UNSUPPORTED;
4430a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket->errno = ENOTSUP;
4431a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
4432a88c31639bb24c73383a4528a5b77066e805148blpleahy            else {
4433a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
4434a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Zero the receive address if being returned
4435a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
4436a88c31639bb24c73383a4528a5b77066e805148blpleahy              pRemoteAddress = NULL;
4437a88c31639bb24c73383a4528a5b77066e805148blpleahy              if ( NULL != pAddress ) {
4438a88c31639bb24c73383a4528a5b77066e805148blpleahy                pRemoteAddress = (struct sockaddr *)&Addr;
4439a88c31639bb24c73383a4528a5b77066e805148blpleahy                ZeroMem ( pRemoteAddress, sizeof ( Addr ));
4440a88c31639bb24c73383a4528a5b77066e805148blpleahy                pRemoteAddress->sa_family = pSocket->pApi->AddressFamily;
4441a88c31639bb24c73383a4528a5b77066e805148blpleahy                pRemoteAddress->sa_len = (UINT8)pSocket->pApi->AddressLength;
4442a88c31639bb24c73383a4528a5b77066e805148blpleahy              }
44430164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
4444a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
4445a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Synchronize with the socket layer
4446a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
4447a88c31639bb24c73383a4528a5b77066e805148blpleahy              RAISE_TPL ( TplPrevious, TPL_SOCKETS );
4448d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
4449a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
4450a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Assume failure
4451a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
4452a88c31639bb24c73383a4528a5b77066e805148blpleahy              Status = EFI_UNSUPPORTED;
4453a88c31639bb24c73383a4528a5b77066e805148blpleahy              pSocket->errno = ENOTCONN;
4454a88c31639bb24c73383a4528a5b77066e805148blpleahy
4455a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
4456a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Verify that the socket is connected
4457a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
4458a88c31639bb24c73383a4528a5b77066e805148blpleahy              if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
4459a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
44603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy                //  Poll the network to increase performance
44613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy                //
44623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy                EslSocketRxPoll ( pSocket );
44633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
44643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy                //
4465a88c31639bb24c73383a4528a5b77066e805148blpleahy                //  Locate the port
4466a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
4467a88c31639bb24c73383a4528a5b77066e805148blpleahy                pPort = pSocket->pPortList;
4468a88c31639bb24c73383a4528a5b77066e805148blpleahy                if ( NULL != pPort ) {
4469a88c31639bb24c73383a4528a5b77066e805148blpleahy                  //
4470a88c31639bb24c73383a4528a5b77066e805148blpleahy                  //  Determine the queue head
4471a88c31639bb24c73383a4528a5b77066e805148blpleahy                  //
4472a88c31639bb24c73383a4528a5b77066e805148blpleahy                  bUrgentQueue = (BOOLEAN)( 0 != ( Flags & MSG_OOB ));
4473a88c31639bb24c73383a4528a5b77066e805148blpleahy                  if ( bUrgentQueue ) {
4474a88c31639bb24c73383a4528a5b77066e805148blpleahy                    ppQueueHead = &pSocket->pRxOobPacketListHead;
4475a88c31639bb24c73383a4528a5b77066e805148blpleahy                    ppQueueTail = &pSocket->pRxOobPacketListTail;
4476a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pRxDataBytes = &pSocket->RxOobBytes;
4477a88c31639bb24c73383a4528a5b77066e805148blpleahy                  }
4478a88c31639bb24c73383a4528a5b77066e805148blpleahy                  else {
4479a88c31639bb24c73383a4528a5b77066e805148blpleahy                    ppQueueHead = &pSocket->pRxPacketListHead;
4480a88c31639bb24c73383a4528a5b77066e805148blpleahy                    ppQueueTail = &pSocket->pRxPacketListTail;
4481a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pRxDataBytes = &pSocket->RxBytes;
4482a88c31639bb24c73383a4528a5b77066e805148blpleahy                  }
4483a88c31639bb24c73383a4528a5b77066e805148blpleahy
4484a88c31639bb24c73383a4528a5b77066e805148blpleahy                  //
4485a88c31639bb24c73383a4528a5b77066e805148blpleahy                  //  Determine if there is any data on the queue
4486a88c31639bb24c73383a4528a5b77066e805148blpleahy                  //
4487a88c31639bb24c73383a4528a5b77066e805148blpleahy                  *pDataLength = 0;
4488a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pPacket = *ppQueueHead;
4489a88c31639bb24c73383a4528a5b77066e805148blpleahy                  if ( NULL != pPacket ) {
4490a88c31639bb24c73383a4528a5b77066e805148blpleahy                    //
4491a88c31639bb24c73383a4528a5b77066e805148blpleahy                    //  Copy the received data
4492a88c31639bb24c73383a4528a5b77066e805148blpleahy                    //
4493a88c31639bb24c73383a4528a5b77066e805148blpleahy                    do {
4494a88c31639bb24c73383a4528a5b77066e805148blpleahy                      //
4495a88c31639bb24c73383a4528a5b77066e805148blpleahy                      //  Attempt to receive a packet
4496a88c31639bb24c73383a4528a5b77066e805148blpleahy                      //
4497a88c31639bb24c73383a4528a5b77066e805148blpleahy                      SkipBytes = 0;
4498a88c31639bb24c73383a4528a5b77066e805148blpleahy                      bConsumePacket = (BOOLEAN)( 0 == ( Flags & MSG_PEEK ));
4499a88c31639bb24c73383a4528a5b77066e805148blpleahy                      pBuffer = pSocket->pApi->pfnReceive ( pPort,
4500a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                            pPacket,
4501a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                            &bConsumePacket,
4502a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                            BufferLength,
4503a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                            pBuffer,
4504a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                            &DataLength,
4505a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                            (struct sockaddr *)&Addr,
4506a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                            &SkipBytes );
4507a88c31639bb24c73383a4528a5b77066e805148blpleahy                      *pDataLength += DataLength;
4508a88c31639bb24c73383a4528a5b77066e805148blpleahy                      BufferLength -= DataLength;
4509a88c31639bb24c73383a4528a5b77066e805148blpleahy
4510a88c31639bb24c73383a4528a5b77066e805148blpleahy                      //
4511a88c31639bb24c73383a4528a5b77066e805148blpleahy                      //  Determine if the data is being read
4512a88c31639bb24c73383a4528a5b77066e805148blpleahy                      //
4513a88c31639bb24c73383a4528a5b77066e805148blpleahy                      pNextPacket = pPacket->pNext;
4514a88c31639bb24c73383a4528a5b77066e805148blpleahy                      if ( bConsumePacket ) {
4515a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //
4516a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //  All done with this packet
4517a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //  Account for any discarded data
4518a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //
4519a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pSocket->pApi->pfnPacketFree ( pPacket, pRxDataBytes );
4520a88c31639bb24c73383a4528a5b77066e805148blpleahy                        if ( 0 != SkipBytes ) {
4521a88c31639bb24c73383a4528a5b77066e805148blpleahy                          DEBUG (( DEBUG_RX,
4522a88c31639bb24c73383a4528a5b77066e805148blpleahy                                    "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n",
4523a88c31639bb24c73383a4528a5b77066e805148blpleahy                                    pPort,
4524a88c31639bb24c73383a4528a5b77066e805148blpleahy                                    SkipBytes ));
4525a88c31639bb24c73383a4528a5b77066e805148blpleahy                        }
4526a88c31639bb24c73383a4528a5b77066e805148blpleahy
4527a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //
4528a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //  Remove this packet from the queue
4529a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //
4530a88c31639bb24c73383a4528a5b77066e805148blpleahy                        *ppQueueHead = pPacket->pNext;
4531a88c31639bb24c73383a4528a5b77066e805148blpleahy                        if ( NULL == *ppQueueHead ) {
4532a88c31639bb24c73383a4528a5b77066e805148blpleahy                          *ppQueueTail = NULL;
4533a88c31639bb24c73383a4528a5b77066e805148blpleahy                        }
4534a88c31639bb24c73383a4528a5b77066e805148blpleahy
4535a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //
4536a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //  Move the packet to the free queue
4537a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //
4538a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pPacket->pNext = pSocket->pRxFree;
4539a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pSocket->pRxFree = pPacket;
4540a88c31639bb24c73383a4528a5b77066e805148blpleahy                        DEBUG (( DEBUG_RX,
4541a88c31639bb24c73383a4528a5b77066e805148blpleahy                                  "0x%08x: Port freeing packet 0x%08x\r\n",
4542a88c31639bb24c73383a4528a5b77066e805148blpleahy                                  pPort,
4543a88c31639bb24c73383a4528a5b77066e805148blpleahy                                  pPacket ));
4544a88c31639bb24c73383a4528a5b77066e805148blpleahy
4545a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //
4546a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //  Restart the receive operation if necessary
4547a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //
4548a88c31639bb24c73383a4528a5b77066e805148blpleahy                        if (( NULL != pPort->pRxFree )
4549a88c31639bb24c73383a4528a5b77066e805148blpleahy                          && ( MAX_RX_DATA > pSocket->RxBytes )) {
4550a88c31639bb24c73383a4528a5b77066e805148blpleahy                            EslSocketRxStart ( pPort );
4551a88c31639bb24c73383a4528a5b77066e805148blpleahy                        }
4552a88c31639bb24c73383a4528a5b77066e805148blpleahy                      }
4553a88c31639bb24c73383a4528a5b77066e805148blpleahy
4554a88c31639bb24c73383a4528a5b77066e805148blpleahy                      //
4555a88c31639bb24c73383a4528a5b77066e805148blpleahy                      //  Get the next packet
4556a88c31639bb24c73383a4528a5b77066e805148blpleahy                      //
4557a88c31639bb24c73383a4528a5b77066e805148blpleahy                      pPacket = pNextPacket;
4558a88c31639bb24c73383a4528a5b77066e805148blpleahy                    } while (( SOCK_STREAM == pSocket->Type )
4559a88c31639bb24c73383a4528a5b77066e805148blpleahy                          && ( NULL != pPacket )
4560a88c31639bb24c73383a4528a5b77066e805148blpleahy                          && ( 0 < BufferLength ));
4561a88c31639bb24c73383a4528a5b77066e805148blpleahy
4562a88c31639bb24c73383a4528a5b77066e805148blpleahy                    //
4563a88c31639bb24c73383a4528a5b77066e805148blpleahy                    //  Successful operation
4564a88c31639bb24c73383a4528a5b77066e805148blpleahy                    //
4565a88c31639bb24c73383a4528a5b77066e805148blpleahy                    Status = EFI_SUCCESS;
4566a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pSocket->errno = 0;
4567a88c31639bb24c73383a4528a5b77066e805148blpleahy                  }
4568a88c31639bb24c73383a4528a5b77066e805148blpleahy                  else {
4569a88c31639bb24c73383a4528a5b77066e805148blpleahy                    //
4570a88c31639bb24c73383a4528a5b77066e805148blpleahy                    //  The queue is empty
4571a88c31639bb24c73383a4528a5b77066e805148blpleahy                    //  Determine if it is time to return the receive error
4572a88c31639bb24c73383a4528a5b77066e805148blpleahy                    //
4573a88c31639bb24c73383a4528a5b77066e805148blpleahy                    if ( EFI_ERROR ( pSocket->RxError )
4574a88c31639bb24c73383a4528a5b77066e805148blpleahy                      && ( NULL == pSocket->pRxPacketListHead )
4575a88c31639bb24c73383a4528a5b77066e805148blpleahy                      && ( NULL == pSocket->pRxOobPacketListHead )) {
4576a88c31639bb24c73383a4528a5b77066e805148blpleahy                      Status = pSocket->RxError;
4577a88c31639bb24c73383a4528a5b77066e805148blpleahy                      pSocket->RxError = EFI_SUCCESS;
4578a88c31639bb24c73383a4528a5b77066e805148blpleahy                      switch ( Status ) {
4579a88c31639bb24c73383a4528a5b77066e805148blpleahy                      default:
4580a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pSocket->errno = EIO;
4581a88c31639bb24c73383a4528a5b77066e805148blpleahy                        break;
4582a88c31639bb24c73383a4528a5b77066e805148blpleahy
4583a88c31639bb24c73383a4528a5b77066e805148blpleahy                      case EFI_CONNECTION_FIN:
4584a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //
4585a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //  Continue to return zero bytes received when the
4586a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //  peer has successfully closed the connection
4587a88c31639bb24c73383a4528a5b77066e805148blpleahy                        //
4588a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pSocket->RxError = EFI_CONNECTION_FIN;
4589a88c31639bb24c73383a4528a5b77066e805148blpleahy                        *pDataLength = 0;
4590a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pSocket->errno = 0;
4591a88c31639bb24c73383a4528a5b77066e805148blpleahy                        Status = EFI_SUCCESS;
4592a88c31639bb24c73383a4528a5b77066e805148blpleahy                        break;
4593a88c31639bb24c73383a4528a5b77066e805148blpleahy
4594a88c31639bb24c73383a4528a5b77066e805148blpleahy                      case EFI_CONNECTION_REFUSED:
4595a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pSocket->errno = ECONNREFUSED;
4596a88c31639bb24c73383a4528a5b77066e805148blpleahy                        break;
4597a88c31639bb24c73383a4528a5b77066e805148blpleahy
4598a88c31639bb24c73383a4528a5b77066e805148blpleahy                      case EFI_CONNECTION_RESET:
4599a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pSocket->errno = ECONNRESET;
4600a88c31639bb24c73383a4528a5b77066e805148blpleahy                        break;
4601a88c31639bb24c73383a4528a5b77066e805148blpleahy
4602a88c31639bb24c73383a4528a5b77066e805148blpleahy                      case EFI_HOST_UNREACHABLE:
4603a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pSocket->errno = EHOSTUNREACH;
4604a88c31639bb24c73383a4528a5b77066e805148blpleahy                        break;
4605a88c31639bb24c73383a4528a5b77066e805148blpleahy
4606a88c31639bb24c73383a4528a5b77066e805148blpleahy                      case EFI_NETWORK_UNREACHABLE:
4607a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pSocket->errno = ENETUNREACH;
4608a88c31639bb24c73383a4528a5b77066e805148blpleahy                        break;
4609a88c31639bb24c73383a4528a5b77066e805148blpleahy
4610a88c31639bb24c73383a4528a5b77066e805148blpleahy                      case EFI_PORT_UNREACHABLE:
4611a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pSocket->errno = EPROTONOSUPPORT;
4612a88c31639bb24c73383a4528a5b77066e805148blpleahy                        break;
4613a88c31639bb24c73383a4528a5b77066e805148blpleahy
4614a88c31639bb24c73383a4528a5b77066e805148blpleahy                      case EFI_PROTOCOL_UNREACHABLE:
4615a88c31639bb24c73383a4528a5b77066e805148blpleahy                        pSocket->errno = ENOPROTOOPT;
4616a88c31639bb24c73383a4528a5b77066e805148blpleahy                        break;
4617a88c31639bb24c73383a4528a5b77066e805148blpleahy                      }
4618a88c31639bb24c73383a4528a5b77066e805148blpleahy                    }
4619a88c31639bb24c73383a4528a5b77066e805148blpleahy                    else {
4620a88c31639bb24c73383a4528a5b77066e805148blpleahy                      Status = EFI_NOT_READY;
4621a88c31639bb24c73383a4528a5b77066e805148blpleahy                      pSocket->errno = EAGAIN;
4622a88c31639bb24c73383a4528a5b77066e805148blpleahy                    }
4623a88c31639bb24c73383a4528a5b77066e805148blpleahy                  }
4624a88c31639bb24c73383a4528a5b77066e805148blpleahy                }
4625a88c31639bb24c73383a4528a5b77066e805148blpleahy              }
4626a88c31639bb24c73383a4528a5b77066e805148blpleahy
4627a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
4628a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Release the socket layer synchronization
4629a88c31639bb24c73383a4528a5b77066e805148blpleahy              //
4630a88c31639bb24c73383a4528a5b77066e805148blpleahy              RESTORE_TPL ( TplPrevious );
4631a88c31639bb24c73383a4528a5b77066e805148blpleahy
4632a88c31639bb24c73383a4528a5b77066e805148blpleahy              if (( !EFI_ERROR ( Status )) && ( NULL != pAddress )) {
4633a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
4634a88c31639bb24c73383a4528a5b77066e805148blpleahy                //  Return the remote address if requested, truncate if necessary
4635a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
4636a88c31639bb24c73383a4528a5b77066e805148blpleahy                AddressLength = pRemoteAddress->sa_len;
4637a88c31639bb24c73383a4528a5b77066e805148blpleahy                if ( AddressLength > *pAddressLength ) {
4638a88c31639bb24c73383a4528a5b77066e805148blpleahy                  AddressLength = *pAddressLength;
4639a88c31639bb24c73383a4528a5b77066e805148blpleahy                }
4640a88c31639bb24c73383a4528a5b77066e805148blpleahy                DEBUG (( DEBUG_RX,
4641a88c31639bb24c73383a4528a5b77066e805148blpleahy                          "Returning the remote address, 0x%016x bytes --> 0x%16x\r\n", *pAddressLength, pAddress ));
4642a88c31639bb24c73383a4528a5b77066e805148blpleahy                ZeroMem ( pAddress, *pAddressLength );
4643a88c31639bb24c73383a4528a5b77066e805148blpleahy                CopyMem ( pAddress, &Addr, AddressLength );
4644a88c31639bb24c73383a4528a5b77066e805148blpleahy
4645a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
4646a88c31639bb24c73383a4528a5b77066e805148blpleahy                //  Update the address length
4647a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
4648a88c31639bb24c73383a4528a5b77066e805148blpleahy                *pAddressLength = pRemoteAddress->sa_len;
4649a88c31639bb24c73383a4528a5b77066e805148blpleahy              }
4650a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
4651a88c31639bb24c73383a4528a5b77066e805148blpleahy          }
4652a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
4653a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
4654a88c31639bb24c73383a4528a5b77066e805148blpleahy
46550164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
4656a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4657a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
4658a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
4659a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Bad return address pointer and length
4660a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
4661a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_INVALID_PARAMETER;
4662a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = EINVAL;
4663a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4664a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4665a88c31639bb24c73383a4528a5b77066e805148blpleahy
4666a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4667a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Return the operation status
4668a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4669a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( NULL != pErrno ) {
4670a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( NULL != pSocket ) {
4671a88c31639bb24c73383a4528a5b77066e805148blpleahy      *pErrno = pSocket->errno;
4672a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4673a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
4674a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_INVALID_PARAMETER;
4675a88c31639bb24c73383a4528a5b77066e805148blpleahy      *pErrno = ENOTSOCK;
4676a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4677a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4678a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT_STATUS ( Status );
4679a88c31639bb24c73383a4528a5b77066e805148blpleahy  return Status;
4680a88c31639bb24c73383a4528a5b77066e805148blpleahy}
4681a88c31639bb24c73383a4528a5b77066e805148blpleahy
4682a88c31639bb24c73383a4528a5b77066e805148blpleahy
4683beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Cancel the receive operations.
4684a88c31639bb24c73383a4528a5b77066e805148blpleahy
4685a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine cancels a pending receive operation.
4686a88c31639bb24c73383a4528a5b77066e805148blpleahy  See the \ref ReceiveEngine section.
4687a88c31639bb24c73383a4528a5b77066e805148blpleahy
4688a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by ::EslSocketShutdown when the socket
4689a88c31639bb24c73383a4528a5b77066e805148blpleahy  layer is being shutdown.
4690a88c31639bb24c73383a4528a5b77066e805148blpleahy
4691beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pPort     Address of an ::ESL_PORT structure
4692beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pIo       Address of an ::ESL_IO_MGMT structure
4693beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
4694a88c31639bb24c73383a4528a5b77066e805148blpleahyVOID
4695a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketRxCancel (
4696a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort,
4697a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_IO_MGMT * pIo
4698a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
4699a88c31639bb24c73383a4528a5b77066e805148blpleahy{
4700a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
4701a88c31639bb24c73383a4528a5b77066e805148blpleahy
4702a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
4703a88c31639bb24c73383a4528a5b77066e805148blpleahy
4704a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4705a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Cancel the outstanding receive
4706a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4707a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = pPort->pfnRxCancel ( pPort->pProtocol.v,
4708a88c31639bb24c73383a4528a5b77066e805148blpleahy                                &pIo->Token );
4709a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( !EFI_ERROR ( Status )) {
4710a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
4711a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Packet receive aborted on port: 0x%08x\r\n",
4712a88c31639bb24c73383a4528a5b77066e805148blpleahy              pIo->pPacket,
4713a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort ));
4714a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4715a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
4716a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
4717a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Packet receive pending on Port 0x%08x, Status: %r\r\n",
4718a88c31639bb24c73383a4528a5b77066e805148blpleahy              pIo->pPacket,
4719a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort,
4720a88c31639bb24c73383a4528a5b77066e805148blpleahy              Status ));
4721a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4722a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT ( );
4723a88c31639bb24c73383a4528a5b77066e805148blpleahy}
4724a88c31639bb24c73383a4528a5b77066e805148blpleahy
4725a88c31639bb24c73383a4528a5b77066e805148blpleahy
4726beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Process the receive completion.
4727a88c31639bb24c73383a4528a5b77066e805148blpleahy
4728a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine queues the data in FIFO order in either the urgent
4729a88c31639bb24c73383a4528a5b77066e805148blpleahy  or normal data queues depending upon the type of data received.
4730a88c31639bb24c73383a4528a5b77066e805148blpleahy  See the \ref ReceiveEngine section.
4731a88c31639bb24c73383a4528a5b77066e805148blpleahy
4732a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called when some data is received by:
4733a88c31639bb24c73383a4528a5b77066e805148blpleahy  <ul>
4734a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslIp4RxComplete</li>
4735a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslTcp4RxComplete</li>
4736a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslUdp4RxComplete</li>
4737a88c31639bb24c73383a4528a5b77066e805148blpleahy  </ul>
4738a88c31639bb24c73383a4528a5b77066e805148blpleahy
4739beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pIo           Address of an ::ESL_IO_MGMT structure
4740beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  Status        Receive status
4741beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  LengthInBytes Length of the receive data
4742beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  bUrgent       TRUE if urgent data is received and FALSE
4743a88c31639bb24c73383a4528a5b77066e805148blpleahy                            for normal data.
4744a88c31639bb24c73383a4528a5b77066e805148blpleahy**/
4745a88c31639bb24c73383a4528a5b77066e805148blpleahyVOID
4746a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketRxComplete (
4747a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_IO_MGMT * pIo,
4748a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN EFI_STATUS Status,
4749a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN UINTN LengthInBytes,
4750a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN BOOLEAN bUrgent
4751a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
4752a88c31639bb24c73383a4528a5b77066e805148blpleahy{
4753a88c31639bb24c73383a4528a5b77066e805148blpleahy  BOOLEAN bUrgentQueue;
4754a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IO_MGMT * pIoNext;
4755a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pPacket;
4756a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
4757a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pPrevious;
4758a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET ** ppQueueHead;
4759a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET ** ppQueueTail;
4760a88c31639bb24c73383a4528a5b77066e805148blpleahy  size_t * pRxBytes;
4761a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
4762a88c31639bb24c73383a4528a5b77066e805148blpleahy
4763a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
4764a88c31639bb24c73383a4528a5b77066e805148blpleahy  VERIFY_AT_TPL ( TPL_SOCKETS );
4765a88c31639bb24c73383a4528a5b77066e805148blpleahy
4766a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4767a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Locate the active receive packet
4768a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4769a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPacket = pIo->pPacket;
4770a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPort = pIo->pPort;
4771a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = pPort->pSocket;
4772a88c31639bb24c73383a4528a5b77066e805148blpleahy
4773a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4774a88c31639bb24c73383a4528a5b77066e805148blpleahy  //         pPort->pRxActive
4775a88c31639bb24c73383a4528a5b77066e805148blpleahy  //                |
4776a88c31639bb24c73383a4528a5b77066e805148blpleahy  //                V
47770164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  //          +-------------+   +-------------+   +-------------+
4778a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL
47790164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  //          +-------------+   +-------------+   +-------------+
4780a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
47810164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  //          +-------------+   +-------------+   +-------------+
4782a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL
47830164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  //          +-------------+   +-------------+   +-------------+
4784a88c31639bb24c73383a4528a5b77066e805148blpleahy  //                ^
4785a88c31639bb24c73383a4528a5b77066e805148blpleahy  //                |
4786a88c31639bb24c73383a4528a5b77066e805148blpleahy  //          pPort->pRxFree
4787a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4788a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4789a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Remove the IO structure from the active list
4790a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  The following code searches for the entry in the list and does not
4791a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  assume that the receive operations complete in the order they were
4792a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  issued to the UEFI network layer.
4793a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4794a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIoNext = pPort->pRxActive;
4795a88c31639bb24c73383a4528a5b77066e805148blpleahy  while (( NULL != pIoNext ) && ( pIoNext != pIo ) && ( pIoNext->pNext != pIo ))
4796a88c31639bb24c73383a4528a5b77066e805148blpleahy  {
4797a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIoNext = pIoNext->pNext;
4798a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4799a88c31639bb24c73383a4528a5b77066e805148blpleahy  ASSERT ( NULL != pIoNext );
4800a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( pIoNext == pIo ) {
4801a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPort->pRxActive = pIo->pNext;  //  Beginning of list
4802a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4803a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
4804a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIoNext->pNext = pIo->pNext;    //  Middle of list
4805a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4806a88c31639bb24c73383a4528a5b77066e805148blpleahy
4807a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4808a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Free the IO structure
4809a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4810a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIo->pNext = pPort->pRxFree;
4811a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPort->pRxFree = pIo;
4812a88c31639bb24c73383a4528a5b77066e805148blpleahy
4813a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4814a88c31639bb24c73383a4528a5b77066e805148blpleahy  //            pRxOobPacketListHead              pRxOobPacketListTail
4815a88c31639bb24c73383a4528a5b77066e805148blpleahy  //                      |                                 |
4816a88c31639bb24c73383a4528a5b77066e805148blpleahy  //                      V                                 V
48170164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  //               +------------+   +------------+   +------------+
4818a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Urgent Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL
48190164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  //               +------------+   +------------+   +------------+
4820a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
48210164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  //               +------------+   +------------+   +------------+
4822a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Normal Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL
48230164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel  //               +------------+   +------------+   +------------+
4824a88c31639bb24c73383a4528a5b77066e805148blpleahy  //                      ^                                 ^
4825a88c31639bb24c73383a4528a5b77066e805148blpleahy  //                      |                                 |
4826a88c31639bb24c73383a4528a5b77066e805148blpleahy  //              pRxPacketListHead                pRxPacketListTail
4827a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4828a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4829a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Determine the queue to use
4830a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4831a88c31639bb24c73383a4528a5b77066e805148blpleahy  bUrgentQueue = (BOOLEAN)( bUrgent
4832a88c31639bb24c73383a4528a5b77066e805148blpleahy               && pSocket->pApi->bOobSupported
4833a88c31639bb24c73383a4528a5b77066e805148blpleahy               && ( !pSocket->bOobInLine ));
4834a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( bUrgentQueue ) {
4835a88c31639bb24c73383a4528a5b77066e805148blpleahy    ppQueueHead = &pSocket->pRxOobPacketListHead;
4836a88c31639bb24c73383a4528a5b77066e805148blpleahy    ppQueueTail = &pSocket->pRxOobPacketListTail;
4837a88c31639bb24c73383a4528a5b77066e805148blpleahy    pRxBytes = &pSocket->RxOobBytes;
4838a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4839a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
4840a88c31639bb24c73383a4528a5b77066e805148blpleahy    ppQueueHead = &pSocket->pRxPacketListHead;
4841a88c31639bb24c73383a4528a5b77066e805148blpleahy    ppQueueTail = &pSocket->pRxPacketListTail;
4842a88c31639bb24c73383a4528a5b77066e805148blpleahy    pRxBytes = &pSocket->RxBytes;
4843a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4844a88c31639bb24c73383a4528a5b77066e805148blpleahy
4845a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4846a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Determine if this receive was successful
4847a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
4848a88c31639bb24c73383a4528a5b77066e805148blpleahy  if (( !EFI_ERROR ( Status ))
4849a88c31639bb24c73383a4528a5b77066e805148blpleahy    && ( PORT_STATE_CLOSE_STARTED > pPort->State )
4850a88c31639bb24c73383a4528a5b77066e805148blpleahy    && ( !pSocket->bRxDisable )) {
4851a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4852a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Account for the received data
4853a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4854a88c31639bb24c73383a4528a5b77066e805148blpleahy    *pRxBytes += LengthInBytes;
4855a88c31639bb24c73383a4528a5b77066e805148blpleahy
4856a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4857a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Log the received data
4858a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4859a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_RX | DEBUG_INFO,
4860a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: Packet queued on %s queue of port 0x%08x with 0x%08x bytes of %s data\r\n",
4861a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPacket,
4862a88c31639bb24c73383a4528a5b77066e805148blpleahy              bUrgentQueue ? L"urgent" : L"normal",
4863a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPort,
4864a88c31639bb24c73383a4528a5b77066e805148blpleahy              LengthInBytes,
4865a88c31639bb24c73383a4528a5b77066e805148blpleahy              bUrgent ? L"urgent" : L"normal" ));
4866a88c31639bb24c73383a4528a5b77066e805148blpleahy
4867a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4868a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Add the packet to the list tail.
4869a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4870a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPacket->pNext = NULL;
4871a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPrevious = *ppQueueTail;
4872a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( NULL == pPrevious ) {
4873a88c31639bb24c73383a4528a5b77066e805148blpleahy      *ppQueueHead = pPacket;
4874a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4875a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
4876a88c31639bb24c73383a4528a5b77066e805148blpleahy      pPrevious->pNext = pPacket;
4877a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4878a88c31639bb24c73383a4528a5b77066e805148blpleahy    *ppQueueTail = pPacket;
4879a88c31639bb24c73383a4528a5b77066e805148blpleahy
4880a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4881a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Attempt to restart this receive operation
4882a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4883a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( pSocket->MaxRxBuf > pSocket->RxBytes ) {
4884a88c31639bb24c73383a4528a5b77066e805148blpleahy      EslSocketRxStart ( pPort );
4885a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4886a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
4887a88c31639bb24c73383a4528a5b77066e805148blpleahy      DEBUG (( DEBUG_RX,
4888a88c31639bb24c73383a4528a5b77066e805148blpleahy                "0x%08x: Port RX suspended, 0x%08x bytes queued\r\n",
4889a88c31639bb24c73383a4528a5b77066e805148blpleahy                pPort,
4890a88c31639bb24c73383a4528a5b77066e805148blpleahy                pSocket->RxBytes ));
4891a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4892a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4893a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
4894a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( EFI_ERROR ( Status )) {
4895a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_RX | DEBUG_INFO,
4896a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "ERROR - Receive error on port 0x%08x, packet 0x%08x, Status:%r\r\n",
4897a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pPort,
4898a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pPacket,
4899a88c31639bb24c73383a4528a5b77066e805148blpleahy                  Status ));
4900a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4901a88c31639bb24c73383a4528a5b77066e805148blpleahy
4902a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4903a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Account for the receive bytes and release the driver's buffer
4904a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4905a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( !EFI_ERROR ( Status )) {
4906a88c31639bb24c73383a4528a5b77066e805148blpleahy      *pRxBytes += LengthInBytes;
4907a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->pApi->pfnPacketFree ( pPacket, pRxBytes );
4908a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4909a88c31639bb24c73383a4528a5b77066e805148blpleahy
4910a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4911a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Receive error, free the packet save the error
4912a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4913a88c31639bb24c73383a4528a5b77066e805148blpleahy    EslSocketPacketFree ( pPacket, DEBUG_RX );
4914a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( !EFI_ERROR ( pSocket->RxError )) {
4915a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->RxError = Status;
4916a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4917a88c31639bb24c73383a4528a5b77066e805148blpleahy
4918a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4919a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Update the port state
4920a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
4921a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {
4922a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( PORT_STATE_CLOSE_DONE == pPort->State ) {
4923a88c31639bb24c73383a4528a5b77066e805148blpleahy        EslSocketPortCloseRxDone ( pPort );
4924a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
4925a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4926a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
4927a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( EFI_ERROR ( Status )) {
4928a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_RX | DEBUG_INFO,
4929a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "0x%08x: Port state: PORT_STATE_RX_ERROR, Status: %r\r\n",
4930a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pPort,
4931a88c31639bb24c73383a4528a5b77066e805148blpleahy                  Status ));
4932a88c31639bb24c73383a4528a5b77066e805148blpleahy        pPort->State = PORT_STATE_RX_ERROR;
4933a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
4934a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
4935a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
4936a88c31639bb24c73383a4528a5b77066e805148blpleahy
4937a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT ( );
4938a88c31639bb24c73383a4528a5b77066e805148blpleahy}
4939a88c31639bb24c73383a4528a5b77066e805148blpleahy
4940a88c31639bb24c73383a4528a5b77066e805148blpleahy
4941beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Poll a socket for pending receive activity.
49423bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
49433bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  This routine is called at elivated TPL and extends the idle
49443bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  loop which polls a socket down into the LAN driver layer to
49453bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  determine if there is any receive activity.
49463bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
49473bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  The ::EslSocketPoll, ::EslSocketReceive and ::EslSocketTransmit
49483bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  routines call this routine when there is nothing to do.
49493bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4950beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSocket   Address of an ::EFI_SOCKET structure.
49513bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy **/
49523bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyVOID
49533bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahyEslSocketRxPoll (
49543bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  IN ESL_SOCKET * pSocket
49553bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  )
49563bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy{
49573bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  ESL_PORT * pPort;
49583bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
49593bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  DEBUG (( DEBUG_POLL, "Entering EslSocketRxPoll\r\n" ));
49603bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
49613bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  //
49623bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  //  Increase the network performance by extending the
49633bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  //  polling (idle) loop down into the LAN driver
49643bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  //
49653bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  pPort = pSocket->pPortList;
49663bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  while ( NULL != pPort ) {
49673bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    //
49683bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    //  Poll the LAN adapter
49693bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    //
49703bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    pPort->pfnRxPoll ( pPort->pProtocol.v );
49713bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
49723bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    //
49733bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    //  Locate the next LAN adapter
49743bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    //
49753bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy    pPort = pPort->pLinkSocket;
49763bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  }
49773bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
49783bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy  DEBUG (( DEBUG_POLL, "Exiting EslSocketRxPoll\r\n" ));
49793bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy}
49803bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
49813bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
4982beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Start a receive operation.
4983a88c31639bb24c73383a4528a5b77066e805148blpleahy
4984a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine posts a receive buffer to the network adapter.
4985a88c31639bb24c73383a4528a5b77066e805148blpleahy  See the \ref ReceiveEngine section.
4986a88c31639bb24c73383a4528a5b77066e805148blpleahy
4987a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support routine is called by:
4988a88c31639bb24c73383a4528a5b77066e805148blpleahy  <ul>
4989a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslIp4Receive to restart the receive engine to release flow control.</li>
4990a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslIp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>
4991ceecdc62ab73e5b726630345865a512c780c134elpleahy  leroy.p.leahy <lpleahy    <li>::EslIp4SocketIsConfigured to start the receive engine for the new socket.</li>
4992a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslTcp4ListenComplete to start the recevie engine for the new socket.</li>
4993a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslTcp4Receive to restart the receive engine to release flow control.</li>
4994a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslTcp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>
4995a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslUdp4Receive to restart the receive engine to release flow control.</li>
4996a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslUdp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>
4997a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslUdp4SocketIsConfigured to start the recevie engine for the new socket.</li>
4998a88c31639bb24c73383a4528a5b77066e805148blpleahy  </ul>
4999a88c31639bb24c73383a4528a5b77066e805148blpleahy
5000beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pPort       Address of an ::ESL_PORT structure.
5001beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
5002a88c31639bb24c73383a4528a5b77066e805148blpleahyVOID
5003a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketRxStart (
5004a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort
5005a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
5006a88c31639bb24c73383a4528a5b77066e805148blpleahy{
5007a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINT8 * pBuffer;
5008a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IO_MGMT * pIo;
5009a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pPacket;
5010a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
5011a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
5012a88c31639bb24c73383a4528a5b77066e805148blpleahy
5013a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
5014a88c31639bb24c73383a4528a5b77066e805148blpleahy
5015a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5016a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Determine if a receive is already pending
5017a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5018a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
5019a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPacket = NULL;
5020a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = pPort->pSocket;
5021a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( !EFI_ERROR ( pPort->pSocket->RxError )) {
5022a88c31639bb24c73383a4528a5b77066e805148blpleahy    if (( NULL != pPort->pRxFree )
5023a88c31639bb24c73383a4528a5b77066e805148blpleahy      && ( !pSocket->bRxDisable )
5024a88c31639bb24c73383a4528a5b77066e805148blpleahy      && ( PORT_STATE_CLOSE_STARTED > pPort->State )) {
5025a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5026a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Start all of the pending receive operations
5027a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5028a88c31639bb24c73383a4528a5b77066e805148blpleahy      while ( NULL != pPort->pRxFree ) {
5029a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
5030a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Determine if there are any free packets
5031a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
5032a88c31639bb24c73383a4528a5b77066e805148blpleahy        pPacket = pSocket->pRxFree;
5033a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( NULL != pPacket ) {
5034a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
5035a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Remove this packet from the free list
5036a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
5037a88c31639bb24c73383a4528a5b77066e805148blpleahy          pSocket->pRxFree = pPacket->pNext;
5038a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_RX,
5039a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "0x%08x: Port removed packet 0x%08x from free list\r\n",
5040a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPort,
5041a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPacket ));
5042a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
5043a88c31639bb24c73383a4528a5b77066e805148blpleahy        else {
5044a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
5045a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Allocate a packet structure
5046a88c31639bb24c73383a4528a5b77066e805148blpleahy          //
5047a88c31639bb24c73383a4528a5b77066e805148blpleahy          Status = EslSocketPacketAllocate ( &pPacket,
5048a88c31639bb24c73383a4528a5b77066e805148blpleahy                                             pSocket->pApi->RxPacketBytes,
5049a88c31639bb24c73383a4528a5b77066e805148blpleahy                                             pSocket->pApi->RxZeroBytes,
5050a88c31639bb24c73383a4528a5b77066e805148blpleahy                                             DEBUG_RX );
5051a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( EFI_ERROR ( Status )) {
5052a88c31639bb24c73383a4528a5b77066e805148blpleahy            pPacket = NULL;
5053a88c31639bb24c73383a4528a5b77066e805148blpleahy            DEBUG (( DEBUG_ERROR | DEBUG_RX,
5054a88c31639bb24c73383a4528a5b77066e805148blpleahy                      "0x%08x: Port failed to allocate RX packet, Status: %r\r\n",
5055a88c31639bb24c73383a4528a5b77066e805148blpleahy                      pPort,
5056a88c31639bb24c73383a4528a5b77066e805148blpleahy                      Status ));
5057d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            break;
5058d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          }
5059d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
5060d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5061d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5062a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Connect the IO and packet structures
5063d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5064a88c31639bb24c73383a4528a5b77066e805148blpleahy        pIo = pPort->pRxFree;
5065a88c31639bb24c73383a4528a5b77066e805148blpleahy        pIo->pPacket = pPacket;
5066a88c31639bb24c73383a4528a5b77066e805148blpleahy
5067a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
5068a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Eliminate the need for IP4 and UDP4 specific routines by
5069a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  clearing the RX data pointer here.
5070a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
5071a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  No driver buffer for this packet
5072a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
5073a88c31639bb24c73383a4528a5b77066e805148blpleahy        //    +--------------------+
5074a88c31639bb24c73383a4528a5b77066e805148blpleahy        //    | ESL_IO_MGMT        |
5075a88c31639bb24c73383a4528a5b77066e805148blpleahy        //    |                    |
5076a88c31639bb24c73383a4528a5b77066e805148blpleahy        //    |    +---------------+
5077a88c31639bb24c73383a4528a5b77066e805148blpleahy        //    |    | Token         |
5078a88c31639bb24c73383a4528a5b77066e805148blpleahy        //    |    |        RxData --> NULL
5079a88c31639bb24c73383a4528a5b77066e805148blpleahy        //    +----+---------------+
5080a88c31639bb24c73383a4528a5b77066e805148blpleahy        //
5081a88c31639bb24c73383a4528a5b77066e805148blpleahy        pBuffer = (UINT8 *)pIo;
5082a88c31639bb24c73383a4528a5b77066e805148blpleahy        pBuffer = &pBuffer[ pSocket->pApi->RxBufferOffset ];
5083a88c31639bb24c73383a4528a5b77066e805148blpleahy        *(VOID **)pBuffer = NULL;
50841c34b250f66ba304a4da510404caa827af2ad91elpleahy
50851c34b250f66ba304a4da510404caa827af2ad91elpleahy        //
5086a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Network specific receive packet initialization
50871c34b250f66ba304a4da510404caa827af2ad91elpleahy        //
5088a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( NULL != pSocket->pApi->pfnRxStart ) {
5089a88c31639bb24c73383a4528a5b77066e805148blpleahy          pSocket->pApi->pfnRxStart ( pPort, pIo );
50901c34b250f66ba304a4da510404caa827af2ad91elpleahy        }
5091a88c31639bb24c73383a4528a5b77066e805148blpleahy
50921c34b250f66ba304a4da510404caa827af2ad91elpleahy        //
5093a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Start the receive on the packet
50941c34b250f66ba304a4da510404caa827af2ad91elpleahy        //
5095a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = pPort->pfnRxStart ( pPort->pProtocol.v, &pIo->Token );
5096a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( !EFI_ERROR ( Status )) {
5097a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_RX | DEBUG_INFO,
5098a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "0x%08x: Packet receive pending on port 0x%08x\r\n",
5099a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPacket,
5100a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPort ));
51011c34b250f66ba304a4da510404caa827af2ad91elpleahy          //
5102a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Allocate the receive control structure
51031c34b250f66ba304a4da510404caa827af2ad91elpleahy          //
5104a88c31639bb24c73383a4528a5b77066e805148blpleahy          pPort->pRxFree = pIo->pNext;
51050164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
51061c34b250f66ba304a4da510404caa827af2ad91elpleahy          //
5107a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Mark this receive as pending
51081c34b250f66ba304a4da510404caa827af2ad91elpleahy          //
5109a88c31639bb24c73383a4528a5b77066e805148blpleahy          pIo->pNext = pPort->pRxActive;
5110a88c31639bb24c73383a4528a5b77066e805148blpleahy          pPort->pRxActive = pIo;
51110164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
5112a88c31639bb24c73383a4528a5b77066e805148blpleahy        }
5113a88c31639bb24c73383a4528a5b77066e805148blpleahy        else {
5114a88c31639bb24c73383a4528a5b77066e805148blpleahy          DEBUG (( DEBUG_RX | DEBUG_INFO,
5115a88c31639bb24c73383a4528a5b77066e805148blpleahy                    "ERROR - Failed to post a receive on port 0x%08x, Status: %r\r\n",
5116a88c31639bb24c73383a4528a5b77066e805148blpleahy                    pPort,
5117a88c31639bb24c73383a4528a5b77066e805148blpleahy                    Status ));
5118a88c31639bb24c73383a4528a5b77066e805148blpleahy          if ( !EFI_ERROR ( pSocket->RxError )) {
51191c34b250f66ba304a4da510404caa827af2ad91elpleahy            //
5120a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Save the error status
51211c34b250f66ba304a4da510404caa827af2ad91elpleahy            //
5122a88c31639bb24c73383a4528a5b77066e805148blpleahy            pSocket->RxError = Status;
51231c34b250f66ba304a4da510404caa827af2ad91elpleahy          }
51241c34b250f66ba304a4da510404caa827af2ad91elpleahy
51251c34b250f66ba304a4da510404caa827af2ad91elpleahy          //
5126a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Free the packet
51271c34b250f66ba304a4da510404caa827af2ad91elpleahy          //
5128a88c31639bb24c73383a4528a5b77066e805148blpleahy          pIo->pPacket = NULL;
5129a88c31639bb24c73383a4528a5b77066e805148blpleahy          pPacket->pNext = pSocket->pRxFree;
5130a88c31639bb24c73383a4528a5b77066e805148blpleahy          pSocket->pRxFree = pPacket;
5131a88c31639bb24c73383a4528a5b77066e805148blpleahy          break;
51321c34b250f66ba304a4da510404caa827af2ad91elpleahy        }
5133d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
5134d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
5135a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
5136a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( NULL == pPort->pRxFree ) {
5137a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_RX | DEBUG_INFO,
5138a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "0x%08x: Port, no available ESL_IO_MGMT structures\r\n",
5139a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pPort));
5140a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
5141a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( pSocket->bRxDisable ) {
5142a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_RX | DEBUG_INFO,
5143a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "0x%08x: Port, receive disabled!\r\n",
5144a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pPort ));
5145a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
5146a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {
5147a88c31639bb24c73383a4528a5b77066e805148blpleahy        DEBUG (( DEBUG_RX | DEBUG_INFO,
5148a88c31639bb24c73383a4528a5b77066e805148blpleahy                  "0x%08x: Port, is closing!\r\n",
5149a88c31639bb24c73383a4528a5b77066e805148blpleahy                  pPort ));
5150a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
5151d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
5152d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
5153a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
5154a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_ERROR | DEBUG_RX,
5155a88c31639bb24c73383a4528a5b77066e805148blpleahy              "ERROR - Previous receive error, Status: %r\r\n",
5156a88c31639bb24c73383a4528a5b77066e805148blpleahy               pPort->pSocket->RxError ));
5157a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
5158a88c31639bb24c73383a4528a5b77066e805148blpleahy
5159a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT ( );
5160d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
5161d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5162d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5163beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Shutdown the socket receive and transmit operations.
5164d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5165a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine sets a flag to stop future transmissions and calls
5166a88c31639bb24c73383a4528a5b77066e805148blpleahy  the network specific layer to cancel the pending receive operation.
5167d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5168a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::shutdown routine calls this routine to stop receive and transmit
5169a88c31639bb24c73383a4528a5b77066e805148blpleahy  operations on the socket.
5170a88c31639bb24c73383a4528a5b77066e805148blpleahy
5171beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
5172beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  How             Which operations to stop
5173beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out] pErrno          Address to receive the errno value upon completion.
5174d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5175d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_SUCCESS - Socket operations successfully shutdown
5176beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
5177d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
5178d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEslSocketShutdown (
5179d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
5180d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int How,
5181d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int * pErrno
5182d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
5183d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
5184a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IO_MGMT * pIo;
5185a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
5186a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
5187d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
5188d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_TPL TplPrevious;
51890164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
5190d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
51910164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
5192d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
5193d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Assume success
5194d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
5195d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Status = EFI_SUCCESS;
5196d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5197d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
5198d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Validate the socket
5199d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
5200d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pSocket = NULL;
5201d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pSocketProtocol ) {
5202d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
5203d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5204d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
5205d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //  Verify that the socket is connected
5206d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
5207d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( pSocket->bConnected ) {
5208d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
5209d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //  Validate the How value
5210d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
5211d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      if (( SHUT_RD <= How ) && ( SHUT_RDWR >= How )) {
5212d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5213d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //  Synchronize with the socket layer
5214d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5215d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        RAISE_TPL ( TplPrevious, TPL_SOCKETS );
5216d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5217d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5218d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //  Disable the receiver if requested
5219d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5220d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        if (( SHUT_RD == How ) || ( SHUT_RDWR == How )) {
5221d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          pSocket->bRxDisable = TRUE;
5222d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
5223d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5224d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5225d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //  Disable the transmitter if requested
5226d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5227d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        if (( SHUT_WR == How ) || ( SHUT_RDWR == How )) {
5228d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          pSocket->bTxDisable = TRUE;
5229d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
5230d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5231d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5232a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Cancel the pending receive operations
5233d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5234a88c31639bb24c73383a4528a5b77066e805148blpleahy        if ( pSocket->bRxDisable ) {
5235d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
5236a88c31639bb24c73383a4528a5b77066e805148blpleahy          //  Walk the list of ports
5237d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
5238a88c31639bb24c73383a4528a5b77066e805148blpleahy          pPort = pSocket->pPortList;
5239a88c31639bb24c73383a4528a5b77066e805148blpleahy          while ( NULL != pPort ) {
5240d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
5241a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Walk the list of active receive operations
5242d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
5243a88c31639bb24c73383a4528a5b77066e805148blpleahy            pIo = pPort->pRxActive;
5244a88c31639bb24c73383a4528a5b77066e805148blpleahy            while ( NULL != pIo ) {
5245a88c31639bb24c73383a4528a5b77066e805148blpleahy              EslSocketRxCancel ( pPort, pIo );
5246a88c31639bb24c73383a4528a5b77066e805148blpleahy            }
5247a88c31639bb24c73383a4528a5b77066e805148blpleahy
5248d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
5249a88c31639bb24c73383a4528a5b77066e805148blpleahy            //  Set the next port
5250d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
5251a88c31639bb24c73383a4528a5b77066e805148blpleahy            pPort = pPort->pLinkSocket;
5252d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          }
5253d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
5254a88c31639bb24c73383a4528a5b77066e805148blpleahy
5255d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5256d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //  Release the socket layer synchronization
5257d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5258d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        RESTORE_TPL ( TplPrevious );
5259d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
5260d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      else {
5261d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5262a88c31639bb24c73383a4528a5b77066e805148blpleahy        //  Invalid How value
5263d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        //
5264a88c31639bb24c73383a4528a5b77066e805148blpleahy        pSocket->errno = EINVAL;
5265a88c31639bb24c73383a4528a5b77066e805148blpleahy        Status = EFI_INVALID_PARAMETER;
5266d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
5267d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
5268d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    else {
5269d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
5270a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  The socket is not connected
5271d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
5272a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->errno = ENOTCONN;
5273a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EFI_NOT_STARTED;
5274d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
5275d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
5276d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5277d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
5278d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
5279d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
5280d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pErrno ) {
5281d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( NULL != pSocket ) {
5282d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      *pErrno = pSocket->errno;
5283d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
5284a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
5285d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EFI_INVALID_PARAMETER;
5286a88c31639bb24c73383a4528a5b77066e805148blpleahy      *pErrno = ENOTSOCK;
5287d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
5288d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
5289d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
5290d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
5291d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
5292d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5293d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5294beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Send data using a network connection.
5295d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5296a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine calls the network specific layer to queue the data
5297a88c31639bb24c73383a4528a5b77066e805148blpleahy  for transmission.  Eventually the buffer will reach the head of
5298a88c31639bb24c73383a4528a5b77066e805148blpleahy  the queue and will get transmitted over the network by the
5299a88c31639bb24c73383a4528a5b77066e805148blpleahy  \ref TransmitEngine.  For datagram
5300a88c31639bb24c73383a4528a5b77066e805148blpleahy  sockets (SOCK_DGRAM and SOCK_RAW) there is no guarantee that
5301a88c31639bb24c73383a4528a5b77066e805148blpleahy  the data reaches the application running on the remote system.
5302d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5303a88c31639bb24c73383a4528a5b77066e805148blpleahy  The ::sendto routine calls this routine to send data to the remote
5304a88c31639bb24c73383a4528a5b77066e805148blpleahy  system.  Note that ::send and ::write are layered on top of ::sendto.
5305a88c31639bb24c73383a4528a5b77066e805148blpleahy
5306beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
5307beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  Flags           Message control flags
5308beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  BufferLength    Length of the the buffer
5309beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pBuffer         Address of a buffer containing the data to send
5310beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pDataLength     Address to receive the number of data bytes sent
5311beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pAddress        Network address of the remote system address
5312beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  AddressLength   Length of the remote network address structure
5313beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[out] pErrno          Address to receive the errno value upon completion.
5314d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5315d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  @retval EFI_SUCCESS - Socket data successfully queued for transmit
5316beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
5317d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEFI_STATUS
5318d7ce700605e1af0e455e31ec11f19ff21d26b525darylmEslSocketTransmit (
5319d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
5320d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int Flags,
5321d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN size_t BufferLength,
5322d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN CONST UINT8 * pBuffer,
5323d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  OUT size_t * pDataLength,
5324d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN const struct sockaddr * pAddress,
5325d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN socklen_t AddressLength,
5326d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  IN int * pErrno
5327d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  )
5328d7ce700605e1af0e455e31ec11f19ff21d26b525darylm{
5329a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
5330d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_STATUS Status;
5331d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  EFI_TPL TplPrevious;
5332d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5333d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_ENTER ( );
5334d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5335d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
5336d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Assume success
5337d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
5338d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  Status = EFI_SUCCESS;
5339d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5340d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
5341d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Validate the socket
5342d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
5343d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  pSocket = NULL;
5344d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pSocketProtocol ) {
5345d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
5346d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5347d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
53481c34b250f66ba304a4da510404caa827af2ad91elpleahy    //  Return the transmit error if necessary
5349d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    //
53501c34b250f66ba304a4da510404caa827af2ad91elpleahy    if ( EFI_SUCCESS != pSocket->TxError ) {
53511c34b250f66ba304a4da510404caa827af2ad91elpleahy      pSocket->errno = EIO;
53521c34b250f66ba304a4da510404caa827af2ad91elpleahy      Status = pSocket->TxError;
53531c34b250f66ba304a4da510404caa827af2ad91elpleahy      pSocket->TxError = EFI_SUCCESS;
53541c34b250f66ba304a4da510404caa827af2ad91elpleahy    }
53551c34b250f66ba304a4da510404caa827af2ad91elpleahy    else {
5356d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
53571c34b250f66ba304a4da510404caa827af2ad91elpleahy      //  Verify the socket state
5358d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      //
5359a88c31639bb24c73383a4528a5b77066e805148blpleahy      Status = EslSocketIsConfigured ( pSocket );
53601c34b250f66ba304a4da510404caa827af2ad91elpleahy      if ( !EFI_ERROR ( Status )) {
53611c34b250f66ba304a4da510404caa827af2ad91elpleahy        //
53621c34b250f66ba304a4da510404caa827af2ad91elpleahy        //  Verify that transmit is still allowed
53631c34b250f66ba304a4da510404caa827af2ad91elpleahy        //
53641c34b250f66ba304a4da510404caa827af2ad91elpleahy        if ( !pSocket->bTxDisable ) {
5365d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
53661c34b250f66ba304a4da510404caa827af2ad91elpleahy          //  Validate the buffer length
5367d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          //
53681c34b250f66ba304a4da510404caa827af2ad91elpleahy          if (( NULL == pDataLength )
53691c34b250f66ba304a4da510404caa827af2ad91elpleahy            && ( 0 > pDataLength )
53701c34b250f66ba304a4da510404caa827af2ad91elpleahy            && ( NULL == pBuffer )) {
53711c34b250f66ba304a4da510404caa827af2ad91elpleahy            if ( NULL == pDataLength ) {
53721c34b250f66ba304a4da510404caa827af2ad91elpleahy              DEBUG (( DEBUG_RX,
53731c34b250f66ba304a4da510404caa827af2ad91elpleahy                        "ERROR - pDataLength is NULL!\r\n" ));
53741c34b250f66ba304a4da510404caa827af2ad91elpleahy            }
53751c34b250f66ba304a4da510404caa827af2ad91elpleahy            else if ( NULL == pBuffer ) {
53761c34b250f66ba304a4da510404caa827af2ad91elpleahy              DEBUG (( DEBUG_RX,
53771c34b250f66ba304a4da510404caa827af2ad91elpleahy                        "ERROR - pBuffer is NULL!\r\n" ));
53781c34b250f66ba304a4da510404caa827af2ad91elpleahy            }
53791c34b250f66ba304a4da510404caa827af2ad91elpleahy            else {
53801c34b250f66ba304a4da510404caa827af2ad91elpleahy              DEBUG (( DEBUG_RX,
53811c34b250f66ba304a4da510404caa827af2ad91elpleahy                        "ERROR - Data length < 0!\r\n" ));
53821c34b250f66ba304a4da510404caa827af2ad91elpleahy            }
5383d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            Status = EFI_INVALID_PARAMETER;
5384d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            pSocket->errno = EFAULT;
5385d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          }
5386d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          else {
5387d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
53881c34b250f66ba304a4da510404caa827af2ad91elpleahy            //  Validate the remote network address
5389d7ce700605e1af0e455e31ec11f19ff21d26b525darylm            //
53901c34b250f66ba304a4da510404caa827af2ad91elpleahy            if (( NULL != pAddress )
53911c34b250f66ba304a4da510404caa827af2ad91elpleahy              && ( AddressLength < pAddress->sa_len )) {
53921c34b250f66ba304a4da510404caa827af2ad91elpleahy              DEBUG (( DEBUG_TX,
53931c34b250f66ba304a4da510404caa827af2ad91elpleahy                        "ERROR - Invalid sin_len field in address\r\n" ));
5394d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              Status = EFI_INVALID_PARAMETER;
53951c34b250f66ba304a4da510404caa827af2ad91elpleahy              pSocket->errno = EFAULT;
53961c34b250f66ba304a4da510404caa827af2ad91elpleahy            }
53971c34b250f66ba304a4da510404caa827af2ad91elpleahy            else {
53981c34b250f66ba304a4da510404caa827af2ad91elpleahy              //
5399a88c31639bb24c73383a4528a5b77066e805148blpleahy              //  Verify the API
5400d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              //
5401a88c31639bb24c73383a4528a5b77066e805148blpleahy              if ( NULL == pSocket->pApi->pfnTransmit ) {
5402a88c31639bb24c73383a4528a5b77066e805148blpleahy                Status = EFI_UNSUPPORTED;
5403a88c31639bb24c73383a4528a5b77066e805148blpleahy                pSocket->errno = ENOTSUP;
5404a88c31639bb24c73383a4528a5b77066e805148blpleahy              }
5405a88c31639bb24c73383a4528a5b77066e805148blpleahy              else {
54061c34b250f66ba304a4da510404caa827af2ad91elpleahy                //
5407a88c31639bb24c73383a4528a5b77066e805148blpleahy                //  Synchronize with the socket layer
54081c34b250f66ba304a4da510404caa827af2ad91elpleahy                //
5409a88c31639bb24c73383a4528a5b77066e805148blpleahy                RAISE_TPL ( TplPrevious, TPL_SOCKETS );
54101c34b250f66ba304a4da510404caa827af2ad91elpleahy
5411a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
54123bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy                //  Poll the network to increase performance
54133bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy                //
54143bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy                EslSocketRxPoll ( pSocket );
54153bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy
54163bdf9aae5f7f4c5f47fc8f807ae4409dfe3bdd58lpleahy                //
5417a88c31639bb24c73383a4528a5b77066e805148blpleahy                //  Attempt to buffer the packet for transmission
5418a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
5419a88c31639bb24c73383a4528a5b77066e805148blpleahy                Status = pSocket->pApi->pfnTransmit ( pSocket,
5420a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                      Flags,
5421a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                      BufferLength,
5422a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                      pBuffer,
5423a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                      pDataLength,
5424a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                      pAddress,
5425a88c31639bb24c73383a4528a5b77066e805148blpleahy                                                      AddressLength );
54261c34b250f66ba304a4da510404caa827af2ad91elpleahy
5427a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
5428a88c31639bb24c73383a4528a5b77066e805148blpleahy                //  Release the socket layer synchronization
5429a88c31639bb24c73383a4528a5b77066e805148blpleahy                //
5430a88c31639bb24c73383a4528a5b77066e805148blpleahy                RESTORE_TPL ( TplPrevious );
5431d7ce700605e1af0e455e31ec11f19ff21d26b525darylm              }
54321c34b250f66ba304a4da510404caa827af2ad91elpleahy            }
5433d7ce700605e1af0e455e31ec11f19ff21d26b525darylm          }
5434d7ce700605e1af0e455e31ec11f19ff21d26b525darylm        }
54351c34b250f66ba304a4da510404caa827af2ad91elpleahy        else {
54361c34b250f66ba304a4da510404caa827af2ad91elpleahy          //
54371c34b250f66ba304a4da510404caa827af2ad91elpleahy          //  The transmitter was shutdown
54381c34b250f66ba304a4da510404caa827af2ad91elpleahy          //
54391c34b250f66ba304a4da510404caa827af2ad91elpleahy          pSocket->errno = EPIPE;
54401c34b250f66ba304a4da510404caa827af2ad91elpleahy          Status = EFI_NOT_STARTED;
54411c34b250f66ba304a4da510404caa827af2ad91elpleahy        }
5442d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      }
5443d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
5444d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
5445d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5446d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
5447d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //  Return the operation status
5448d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  //
5449d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  if ( NULL != pErrno ) {
5450d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    if ( NULL != pSocket ) {
5451d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      *pErrno = pSocket->errno;
5452d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
5453a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
5454d7ce700605e1af0e455e31ec11f19ff21d26b525darylm      Status = EFI_INVALID_PARAMETER;
5455a88c31639bb24c73383a4528a5b77066e805148blpleahy      *pErrno = ENOTSOCK;
5456d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    }
5457d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  }
5458d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  DBG_EXIT_STATUS ( Status );
5459d7ce700605e1af0e455e31ec11f19ff21d26b525darylm  return Status;
5460d7ce700605e1af0e455e31ec11f19ff21d26b525darylm}
5461d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5462d7ce700605e1af0e455e31ec11f19ff21d26b525darylm
5463beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Complete the transmit operation.
5464a88c31639bb24c73383a4528a5b77066e805148blpleahy
5465a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support routine handles the transmit completion processing for
5466a88c31639bb24c73383a4528a5b77066e805148blpleahy  the various network layers.  It frees the ::ESL_IO_MGMT structure
5467a88c31639bb24c73383a4528a5b77066e805148blpleahy  and and frees packet resources by calling ::EslSocketPacketFree.
5468a88c31639bb24c73383a4528a5b77066e805148blpleahy  Transmit errors are logged in ESL_SOCKET::TxError.
5469a88c31639bb24c73383a4528a5b77066e805148blpleahy  See the \ref TransmitEngine section.
5470a88c31639bb24c73383a4528a5b77066e805148blpleahy
5471a88c31639bb24c73383a4528a5b77066e805148blpleahy  This routine is called by:
5472a88c31639bb24c73383a4528a5b77066e805148blpleahy  <ul>
5473a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslIp4TxComplete</li>
5474a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslTcp4TxComplete</li>
5475a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslTcp4TxOobComplete</li>
5476a88c31639bb24c73383a4528a5b77066e805148blpleahy    <li>::EslUdp4TxComplete</li>
5477a88c31639bb24c73383a4528a5b77066e805148blpleahy  </ul>
5478a88c31639bb24c73383a4528a5b77066e805148blpleahy
5479beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pIo             Address of an ::ESL_IO_MGMT structure
5480beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  LengthInBytes   Length of the data in bytes
5481beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  Status          Transmit operation status
5482beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pQueueType      Zero terminated string describing queue type
5483beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  ppQueueHead     Transmit queue head address
5484beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  ppQueueTail     Transmit queue tail address
5485beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  ppActive        Active transmit queue address
5486beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  ppFree          Free transmit queue address
5487beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
5488a88c31639bb24c73383a4528a5b77066e805148blpleahyVOID
5489a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketTxComplete (
5490a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_IO_MGMT * pIo,
5491a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN UINT32 LengthInBytes,
5492a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN EFI_STATUS Status,
5493a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN CONST CHAR8 * pQueueType,
5494a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PACKET ** ppQueueHead,
5495a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PACKET ** ppQueueTail,
5496a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_IO_MGMT ** ppActive,
5497a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_IO_MGMT ** ppFree
5498a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
5499a88c31639bb24c73383a4528a5b77066e805148blpleahy{
5500a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pCurrentPacket;
5501a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IO_MGMT * pIoNext;
5502a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pNextPacket;
5503a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pPacket;
5504a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PORT * pPort;
5505a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
5506a88c31639bb24c73383a4528a5b77066e805148blpleahy
5507a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
5508a88c31639bb24c73383a4528a5b77066e805148blpleahy  VERIFY_AT_TPL ( TPL_SOCKETS );
5509a88c31639bb24c73383a4528a5b77066e805148blpleahy
5510a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5511a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Locate the active transmit packet
5512a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5513a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPacket = pIo->pPacket;
5514a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPort = pIo->pPort;
5515a88c31639bb24c73383a4528a5b77066e805148blpleahy  pSocket = pPort->pSocket;
5516a88c31639bb24c73383a4528a5b77066e805148blpleahy
5517a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5518a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  No more packet
5519a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5520a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIo->pPacket = NULL;
5521a88c31639bb24c73383a4528a5b77066e805148blpleahy
5522a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5523a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Remove the IO structure from the active list
5524a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5525a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIoNext = *ppActive;
5526a88c31639bb24c73383a4528a5b77066e805148blpleahy  while (( NULL != pIoNext ) && ( pIoNext != pIo ) && ( pIoNext->pNext != pIo ))
5527a88c31639bb24c73383a4528a5b77066e805148blpleahy  {
5528a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIoNext = pIoNext->pNext;
5529a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
5530a88c31639bb24c73383a4528a5b77066e805148blpleahy  ASSERT ( NULL != pIoNext );
5531a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( pIoNext == pIo ) {
5532a88c31639bb24c73383a4528a5b77066e805148blpleahy    *ppActive = pIo->pNext;       //  Beginning of list
5533a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
5534a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
5535a88c31639bb24c73383a4528a5b77066e805148blpleahy    pIoNext->pNext = pIo->pNext;  //  Middle of list
5536a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
5537a88c31639bb24c73383a4528a5b77066e805148blpleahy
5538a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5539a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Free the IO structure
5540a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5541a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIo->pNext = *ppFree;
5542a88c31639bb24c73383a4528a5b77066e805148blpleahy  *ppFree = pIo;
5543a88c31639bb24c73383a4528a5b77066e805148blpleahy
5544a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5545a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Display the results
5546a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5547a88c31639bb24c73383a4528a5b77066e805148blpleahy  DEBUG (( DEBUG_TX | DEBUG_INFO,
5548a88c31639bb24c73383a4528a5b77066e805148blpleahy            "0x%08x: pIo Released\r\n",
5549a88c31639bb24c73383a4528a5b77066e805148blpleahy            pIo ));
5550a88c31639bb24c73383a4528a5b77066e805148blpleahy
5551a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5552a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Save any transmit error
5553a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5554a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( EFI_ERROR ( Status )) {
5555a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( !EFI_ERROR ( pSocket->TxError )) {
5556a88c31639bb24c73383a4528a5b77066e805148blpleahy      pSocket->TxError = Status;
5557a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
5558a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_TX | DEBUG_INFO,
5559a88c31639bb24c73383a4528a5b77066e805148blpleahy              "ERROR - Transmit failure for %apacket 0x%08x, Status: %r\r\n",
5560a88c31639bb24c73383a4528a5b77066e805148blpleahy              pQueueType,
5561a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPacket,
5562a88c31639bb24c73383a4528a5b77066e805148blpleahy              Status ));
5563a88c31639bb24c73383a4528a5b77066e805148blpleahy
5564a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5565a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Empty the normal transmit list
5566a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5567a88c31639bb24c73383a4528a5b77066e805148blpleahy    pCurrentPacket = pPacket;
5568a88c31639bb24c73383a4528a5b77066e805148blpleahy    pNextPacket = *ppQueueHead;
5569a88c31639bb24c73383a4528a5b77066e805148blpleahy    while ( NULL != pNextPacket ) {
5570a88c31639bb24c73383a4528a5b77066e805148blpleahy      pPacket = pNextPacket;
5571a88c31639bb24c73383a4528a5b77066e805148blpleahy      pNextPacket = pPacket->pNext;
5572a88c31639bb24c73383a4528a5b77066e805148blpleahy      EslSocketPacketFree ( pPacket, DEBUG_TX );
5573a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
5574a88c31639bb24c73383a4528a5b77066e805148blpleahy    *ppQueueHead = NULL;
5575a88c31639bb24c73383a4528a5b77066e805148blpleahy    *ppQueueTail = NULL;
5576a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPacket = pCurrentPacket;
5577a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
5578a88c31639bb24c73383a4528a5b77066e805148blpleahy  else {
5579a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_TX | DEBUG_INFO,
5580a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: %apacket transmitted %d bytes successfully\r\n",
5581a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPacket,
5582a88c31639bb24c73383a4528a5b77066e805148blpleahy              pQueueType,
5583a88c31639bb24c73383a4528a5b77066e805148blpleahy              LengthInBytes ));
5584a88c31639bb24c73383a4528a5b77066e805148blpleahy
5585a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5586a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Verify the transmit engine is still running
5587a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5588a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( !pPort->bCloseNow ) {
5589a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5590a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Start the next packet transmission
5591a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5592a88c31639bb24c73383a4528a5b77066e805148blpleahy      EslSocketTxStart ( pPort,
5593a88c31639bb24c73383a4528a5b77066e805148blpleahy                         ppQueueHead,
5594a88c31639bb24c73383a4528a5b77066e805148blpleahy                         ppQueueTail,
5595a88c31639bb24c73383a4528a5b77066e805148blpleahy                         ppActive,
5596a88c31639bb24c73383a4528a5b77066e805148blpleahy                         ppFree );
5597a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
5598a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
5599a88c31639bb24c73383a4528a5b77066e805148blpleahy
5600a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5601a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Release this packet
5602a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5603a88c31639bb24c73383a4528a5b77066e805148blpleahy  EslSocketPacketFree ( pPacket, DEBUG_TX );
5604a88c31639bb24c73383a4528a5b77066e805148blpleahy
5605a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5606a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Finish the close operation if necessary
5607a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5608a88c31639bb24c73383a4528a5b77066e805148blpleahy  if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {
5609a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5610a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Indicate that the transmit is complete
5611a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5612a88c31639bb24c73383a4528a5b77066e805148blpleahy    EslSocketPortCloseTxDone ( pPort );
5613a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
5614a88c31639bb24c73383a4528a5b77066e805148blpleahy
5615a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT ( );
5616a88c31639bb24c73383a4528a5b77066e805148blpleahy}
5617a88c31639bb24c73383a4528a5b77066e805148blpleahy
5618a88c31639bb24c73383a4528a5b77066e805148blpleahy
5619beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin/** Transmit data using a network connection.
5620a88c31639bb24c73383a4528a5b77066e805148blpleahy
5621a88c31639bb24c73383a4528a5b77066e805148blpleahy  This support routine starts a transmit operation on the
5622a88c31639bb24c73383a4528a5b77066e805148blpleahy  underlying network layer.
5623a88c31639bb24c73383a4528a5b77066e805148blpleahy
5624a88c31639bb24c73383a4528a5b77066e805148blpleahy  The network specific code calls this routine to start a
5625a88c31639bb24c73383a4528a5b77066e805148blpleahy  transmit operation.  See the \ref TransmitEngine section.
5626a88c31639bb24c73383a4528a5b77066e805148blpleahy
5627beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  pPort           Address of an ::ESL_PORT structure
5628beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  ppQueueHead     Transmit queue head address
5629beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  ppQueueTail     Transmit queue tail address
5630beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  ppActive        Active transmit queue address
5631beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin  @param[in]  ppFree          Free transmit queue address
5632beaaa3b715381d05c454619a66dd6d27c0b420e5Olivier Martin**/
5633a88c31639bb24c73383a4528a5b77066e805148blpleahyVOID
5634a88c31639bb24c73383a4528a5b77066e805148blpleahyEslSocketTxStart (
5635a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PORT * pPort,
5636a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PACKET ** ppQueueHead,
5637a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_PACKET ** ppQueueTail,
5638a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_IO_MGMT ** ppActive,
5639a88c31639bb24c73383a4528a5b77066e805148blpleahy  IN ESL_IO_MGMT ** ppFree
5640a88c31639bb24c73383a4528a5b77066e805148blpleahy  )
5641a88c31639bb24c73383a4528a5b77066e805148blpleahy{
5642a88c31639bb24c73383a4528a5b77066e805148blpleahy  UINT8 * pBuffer;
5643a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_IO_MGMT * pIo;
5644a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pNextPacket;
5645a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_PACKET * pPacket;
5646a88c31639bb24c73383a4528a5b77066e805148blpleahy  VOID ** ppTokenData;
5647a88c31639bb24c73383a4528a5b77066e805148blpleahy  ESL_SOCKET * pSocket;
5648a88c31639bb24c73383a4528a5b77066e805148blpleahy  EFI_STATUS Status;
5649a88c31639bb24c73383a4528a5b77066e805148blpleahy
5650a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_ENTER ( );
5651a88c31639bb24c73383a4528a5b77066e805148blpleahy
5652a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5653a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Assume success
5654a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5655a88c31639bb24c73383a4528a5b77066e805148blpleahy  Status = EFI_SUCCESS;
5656a88c31639bb24c73383a4528a5b77066e805148blpleahy
5657a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5658a88c31639bb24c73383a4528a5b77066e805148blpleahy  //  Get the packet from the queue head
5659a88c31639bb24c73383a4528a5b77066e805148blpleahy  //
5660a88c31639bb24c73383a4528a5b77066e805148blpleahy  pPacket = *ppQueueHead;
5661a88c31639bb24c73383a4528a5b77066e805148blpleahy  pIo = *ppFree;
5662a88c31639bb24c73383a4528a5b77066e805148blpleahy  if (( NULL != pPacket ) && ( NULL != pIo )) {
5663a88c31639bb24c73383a4528a5b77066e805148blpleahy    pSocket = pPort->pSocket;
5664a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5665a88c31639bb24c73383a4528a5b77066e805148blpleahy    //     *ppQueueHead: pSocket->pRxPacketListHead or pSocket->pRxOobPacketListHead
5666a88c31639bb24c73383a4528a5b77066e805148blpleahy    //          |
5667a88c31639bb24c73383a4528a5b77066e805148blpleahy    //          V
56680164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel    //        +------------+   +------------+   +------------+
5669a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL
56700164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel    //        +------------+   +------------+   +------------+
5671a88c31639bb24c73383a4528a5b77066e805148blpleahy    //                                                     ^
5672a88c31639bb24c73383a4528a5b77066e805148blpleahy    //                                                     |
5673a88c31639bb24c73383a4528a5b77066e805148blpleahy    //     *ppQueueTail: pSocket->pRxPacketListTail or pSocket->pRxOobPacketListTail
5674a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5675a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5676a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Remove the packet from the queue
5677a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5678a88c31639bb24c73383a4528a5b77066e805148blpleahy    pNextPacket = pPacket->pNext;
5679a88c31639bb24c73383a4528a5b77066e805148blpleahy    *ppQueueHead = pNextPacket;
5680a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( NULL == pNextPacket ) {
5681a88c31639bb24c73383a4528a5b77066e805148blpleahy      *ppQueueTail = NULL;
5682a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
5683a88c31639bb24c73383a4528a5b77066e805148blpleahy    pPacket->pNext = NULL;
5684a88c31639bb24c73383a4528a5b77066e805148blpleahy
5685a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5686a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Eliminate the need for IP4 and UDP4 specific routines by
5687a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  connecting the token with the TX data control structure here.
5688a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5689a88c31639bb24c73383a4528a5b77066e805148blpleahy    //    +--------------------+   +--------------------+
5690a88c31639bb24c73383a4528a5b77066e805148blpleahy    //    | ESL_IO_MGMT        |   | ESL_PACKET         |
5691a88c31639bb24c73383a4528a5b77066e805148blpleahy    //    |                    |   |                    |
5692a88c31639bb24c73383a4528a5b77066e805148blpleahy    //    |    +---------------+   +----------------+   |
5693a88c31639bb24c73383a4528a5b77066e805148blpleahy    //    |    | Token         |   | Buffer Length  |   |
5694a88c31639bb24c73383a4528a5b77066e805148blpleahy    //    |    |        TxData --> | Buffer Address |   |
5695a88c31639bb24c73383a4528a5b77066e805148blpleahy    //    |    |               |   +----------------+---+
5696a88c31639bb24c73383a4528a5b77066e805148blpleahy    //    |    |        Event  |   | Data Buffer        |
5697a88c31639bb24c73383a4528a5b77066e805148blpleahy    //    +----+---------------+   |                    |
5698a88c31639bb24c73383a4528a5b77066e805148blpleahy    //                             +--------------------+
5699a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5700a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Compute the address of the TxData pointer in the token
5701a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5702a88c31639bb24c73383a4528a5b77066e805148blpleahy    pBuffer = (UINT8 *)&pIo->Token;
5703a88c31639bb24c73383a4528a5b77066e805148blpleahy    pBuffer = &pBuffer[ pSocket->TxTokenOffset ];
5704a88c31639bb24c73383a4528a5b77066e805148blpleahy    ppTokenData = (VOID **)pBuffer;
5705a88c31639bb24c73383a4528a5b77066e805148blpleahy
5706a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5707a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Compute the address of the TX data control structure in the packet
5708a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5709a88c31639bb24c73383a4528a5b77066e805148blpleahy    //      * EFI_IP4_TRANSMIT_DATA
5710a88c31639bb24c73383a4528a5b77066e805148blpleahy    //      * EFI_TCP4_TRANSMIT_DATA
5711a88c31639bb24c73383a4528a5b77066e805148blpleahy    //      * EFI_UDP4_TRANSMIT_DATA
5712a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5713a88c31639bb24c73383a4528a5b77066e805148blpleahy    pBuffer = (UINT8 *)pPacket;
5714a88c31639bb24c73383a4528a5b77066e805148blpleahy    pBuffer = &pBuffer[ pSocket->TxPacketOffset ];
5715a88c31639bb24c73383a4528a5b77066e805148blpleahy
5716a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5717a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Connect the token to the transmit data control structure
5718a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5719a88c31639bb24c73383a4528a5b77066e805148blpleahy    *ppTokenData = (VOID **)pBuffer;
5720a88c31639bb24c73383a4528a5b77066e805148blpleahy
5721a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5722a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Display the results
5723a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5724a88c31639bb24c73383a4528a5b77066e805148blpleahy    DEBUG (( DEBUG_TX | DEBUG_INFO,
5725a88c31639bb24c73383a4528a5b77066e805148blpleahy              "0x%08x: pIo allocated for pPacket: 0x%08x\r\n",
5726a88c31639bb24c73383a4528a5b77066e805148blpleahy              pIo,
5727a88c31639bb24c73383a4528a5b77066e805148blpleahy              pPacket ));
5728a88c31639bb24c73383a4528a5b77066e805148blpleahy
5729a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5730a88c31639bb24c73383a4528a5b77066e805148blpleahy    //  Start the transmit operation
5731a88c31639bb24c73383a4528a5b77066e805148blpleahy    //
5732a88c31639bb24c73383a4528a5b77066e805148blpleahy    Status = pPort->pfnTxStart ( pPort->pProtocol.v,
5733a88c31639bb24c73383a4528a5b77066e805148blpleahy                                 &pIo->Token );
5734a88c31639bb24c73383a4528a5b77066e805148blpleahy    if ( !EFI_ERROR ( Status )) {
5735a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5736a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Connect the structures
5737a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5738a88c31639bb24c73383a4528a5b77066e805148blpleahy      pIo->pPacket = pPacket;
5739a88c31639bb24c73383a4528a5b77066e805148blpleahy
5740a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
57410164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel      //          +-------------+   +-------------+   +-------------+
5742a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL
57430164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel      //          +-------------+   +-------------+   +-------------+
5744a88c31639bb24c73383a4528a5b77066e805148blpleahy      //              ^
5745a88c31639bb24c73383a4528a5b77066e805148blpleahy      //              |
5746a88c31639bb24c73383a4528a5b77066e805148blpleahy      //          *ppFree:  pPort->pTxFree or pTxOobFree
5747a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5748a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5749a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Remove the IO structure from the queue
5750a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5751a88c31639bb24c73383a4528a5b77066e805148blpleahy      *ppFree = pIo->pNext;
57520164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel
5753a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5754a88c31639bb24c73383a4528a5b77066e805148blpleahy      //         *ppActive:  pPort->pTxActive or pTxOobActive
5755a88c31639bb24c73383a4528a5b77066e805148blpleahy      //             |
5756a88c31639bb24c73383a4528a5b77066e805148blpleahy      //             V
57570164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel      //          +-------------+   +-------------+   +-------------+
5758a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL
57590164fc8e76b6ca9023c893940ddb00ef0b6bee5adaryl.mcdaniel      //          +-------------+   +-------------+   +-------------+
5760a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5761a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5762a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Mark this packet as active
5763a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5764a88c31639bb24c73383a4528a5b77066e805148blpleahy      pIo->pPacket = pPacket;
5765a88c31639bb24c73383a4528a5b77066e805148blpleahy      pIo->pNext = *ppActive;
5766a88c31639bb24c73383a4528a5b77066e805148blpleahy      *ppActive = pIo;
5767a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
5768a88c31639bb24c73383a4528a5b77066e805148blpleahy    else {
57692dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      //
57702dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      //  Display the transmit error
57712dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      //
57722dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      DEBUG (( DEBUG_TX | DEBUG_INFO,
57732dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                "0x%08x, 0x%08x: pIo, pPacket transmit failure: %r\r\n",
57742dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                pIo,
57752dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                pPacket,
57762dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy                Status ));
5777a88c31639bb24c73383a4528a5b77066e805148blpleahy      if ( EFI_SUCCESS == pSocket->TxError ) {
5778a88c31639bb24c73383a4528a5b77066e805148blpleahy        pSocket->TxError = Status;
5779a88c31639bb24c73383a4528a5b77066e805148blpleahy      }
5780a88c31639bb24c73383a4528a5b77066e805148blpleahy
5781a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
57822dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      //  Free the IO structure
57832dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      //
57842dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      pIo->pNext = *ppFree;
57852dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      *ppFree = pIo;
57862dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy
57872dc09dd50fe30496efe9922ee6177ed7bdef6bc2Lee Leahy      //
5788a88c31639bb24c73383a4528a5b77066e805148blpleahy      //  Discard the transmit buffer
5789a88c31639bb24c73383a4528a5b77066e805148blpleahy      //
5790a88c31639bb24c73383a4528a5b77066e805148blpleahy      EslSocketPacketFree ( pPacket, DEBUG_TX );
5791a88c31639bb24c73383a4528a5b77066e805148blpleahy    }
5792a88c31639bb24c73383a4528a5b77066e805148blpleahy  }
5793a88c31639bb24c73383a4528a5b77066e805148blpleahy
5794a88c31639bb24c73383a4528a5b77066e805148blpleahy  DBG_EXIT ( );
5795a88c31639bb24c73383a4528a5b77066e805148blpleahy}
5796