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