]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/EfiSocketLib/Socket.c
edk2: Remove AppPkg, StdLib, StdLibPrivateInternalFiles
[mirror_edk2.git] / StdLib / EfiSocketLib / Socket.c
diff --git a/StdLib/EfiSocketLib/Socket.c b/StdLib/EfiSocketLib/Socket.c
deleted file mode 100644 (file)
index 59b8efa..0000000
+++ /dev/null
@@ -1,5789 +0,0 @@
-/** @file\r
-  Implement the socket support for the socket layer.\r
-\r
-  Socket States:\r
-  * Bound - pSocket->PortList is not NULL\r
-  * Listen - AcceptWait event is not NULL\r
-\r
-  Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-\r
-  \section DataStructures Data Structures\r
-\r
-  <code><pre>\r
-\r
-                +---------------+   +-------------+   +-------------+\r
-  Service Lists | ::ESL_SERVICE |-->| ESL_SERVICE |-->| ESL_SERVICE |--> NULL (pNext)\r
-                +---------------+   +-------------+   +-------------+\r
-                  ^                       | (pPortList)    |\r
-    pUdp4List ^   | pTcp4List             |                |\r
-              |   |                       |                |\r
-          ^   |   |                       |                |\r
- pIp4List |   |   |                       |                |\r
-        +---------------+                 |                |\r
-        | ::ESL_LAYER   | ::mEslLayer     |                |\r
-        +---------------+                 |                |\r
-                  | (pSocketList)         |                |\r
-    Socket List   V                       V                V\r
-                +---------------+   +-------------+   +-------------+\r
-                | ::ESL_SOCKET  |-->| ::ESL_PORT  |-->|   ESL_PORT  |--> NULL (pLinkSocket)\r
-                +---------------+   +-------------+   +-------------+\r
-                  |                       |                |\r
-                  |                       |                V\r
-                  V                       V               NULL\r
-                +-------------+   +-------------+\r
-                | ESL_SOCKET  |-->|   ESL_PORT  |--> NULL\r
-                +-------------+   +-------------+\r
-                  |    | | | |            |\r
-                  V    | | | |            V\r
-                 NULL  | | | |           NULL\r
-               (pNext) | | | |     (pLinkService)\r
-                       | | | |                                     pRxPacketListHead\r
-                       | | | `-----------------------------------------------.\r
-                       | | |                     pRxOobPacketListHead        |\r
-                       | | `--------------------------------.                |\r
-                       | |      pTxPacketListHead           |                |\r
-                       | `---------------.                  |                |\r
-  pTxOobPacketListHead |                 |                  |                |\r
-                       V                 V                  V                V\r
-                  +--------------+    +------------+    +------------+    +------------+\r
-                  | ::ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |\r
-                  +--------------+    +------------+    +------------+    +------------+\r
-                         |                 |                |                |\r
-                         V                 V                V                V\r
-                  +------------+    +------------+    +------------+    +------------+\r
-                  | ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |\r
-                  +------------+    +------------+    +------------+    +------------+\r
-                         |                 |                |                |\r
-                         V                 V                V                V\r
-                        NULL              NULL             NULL             NULL\r
-                       (pNext)\r
-\r
-  </pre></code>\r
-\r
-  ::mEslLayer is the one and only ::ESL_LAYER structure.  It connects directly or\r
-  indirectly to the other data structures.  The ESL_LAYER structure has a unique\r
-  service list for each of the network protocol interfaces.\r
-\r
-  ::ESL_SERVICE manages the network interfaces for a given transport type (IP4, TCP4, UDP4, etc.)\r
-\r
-  ::ESL_SOCKET manages the activity for a single socket instance.  As such, it contains\r
-  the ::EFI_SOCKET_PROTOCOL structure which the BSD socket library uses as the object\r
-  reference and the API into the EFI socket library.\r
-\r
-  ::ESL_PORT manages the connection with a single instance of the lower layer network.\r
-  This structure is the socket equivalent of an IP connection or a TCP or UDP port.\r
-\r
-  ::ESL_PACKET buffers data for transmit and receive.  There are four queues connected\r
-  to the ::ESL_SOCKET that manage the data:\r
-  <ul>\r
-    <li>ESL_SOCKET::pRxPacketListHead - Normal (low) priority receive data</li>\r
-    <li>ESL_SOCKET::pRxOobPacketListHead - High (out-of-band or urgent) priority receive data</li>\r
-    <li>ESL_SOCKET::pTxPacketListHead - Normal (low) priority transmit data</li>\r
-    <li>ESL_SOCKET::pTxOobPacketListHead - High (out-of-band or urgent) priority transmit data</li>\r
-  </ul>\r
-  The selection of the transmit queue is controlled by the MSG_OOB flag on the transmit\r
-  request as well as the socket option SO_OOBINLINE.  The receive queue is selected by\r
-  the URGENT data flag for TCP and the setting of the socket option SO_OOBINLINE.\r
-\r
-  Data structure synchronization is done by raising TPL to TPL_SOCKET.  Modifying\r
-  critical elements within the data structures must be done at this TPL.  TPL is then\r
-  restored to the previous level.  Note that the code verifies that all callbacks are\r
-  entering at TPL_SOCKETS for proper data structure synchronization.\r
-\r
-  \section PortCloseStateMachine Port Close State Machine\r
-\r
-  The port close state machine walks the port through the necessary\r
-  states to stop activity on the port and get it into a state where\r
-  the resources may be released.  The state machine consists of the\r
-  following arcs and states:\r
-\r
-  <code><pre>\r
-\r
-      +--------------------------+\r
-      |          Open            |\r
-      +--------------------------+\r
-                   |\r
-                   |  ::EslSocketPortCloseStart\r
-                   V\r
-      +--------------------------+\r
-      | PORT_STATE_CLOSE_STARTED |\r
-      +--------------------------+\r
-                   |\r
-                   |  ::EslSocketPortCloseTxDone\r
-                   V\r
-      +--------------------------+\r
-      | PORT_STATE_CLOSE_TX_DONE |\r
-      +--------------------------+\r
-                   |\r
-                   |  ::EslSocketPortCloseComplete\r
-                   V\r
-      +--------------------------+\r
-      |  PORT_STATE_CLOSE_DONE   |\r
-      +--------------------------+\r
-                   |\r
-                   |  ::EslSocketPortCloseRxDone\r
-                   V\r
-      +--------------------------+\r
-      | PORT_STATE_CLOSE_RX_DONE |\r
-      +--------------------------+\r
-                   |\r
-                   |  ::EslSocketPortClose\r
-                   V\r
-      +--------------------------+\r
-      |          Closed          |\r
-      +--------------------------+\r
-\r
-  </pre></code>\r
-\r
-  <ul>\r
-    <li>Arc: ::EslSocketPortCloseStart - Marks the port as closing and\r
-      initiates the port close operation</li>\r
-    <li>State: PORT_STATE_CLOSE_STARTED</li>\r
-    <li>Arc: ::EslSocketPortCloseTxDone - Waits until all of the transmit\r
-      operations to complete.  After all of the transmits are complete,\r
-      this routine initiates the network specific close operation by calling\r
-      through ESL_PROTOCOL_API::pfnPortCloseOp.  One such routine is\r
-      ::EslTcp4PortCloseOp.\r
-    </li>\r
-    <li>State: PORT_STATE_CLOSE_TX_DONE</li>\r
-    <li>Arc: ::EslSocketPortCloseComplete - Called when the close operation is\r
-      complete.  After the transition to PORT_STATE_CLOSE_DONE,\r
-      this routine calls ::EslSocketRxCancel to abort the pending receive operations.\r
-    </li>\r
-    <li>State: PORT_STATE_CLOSE_DONE</li>\r
-    <li>Arc: ::EslSocketPortCloseRxDone - Waits until all of the receive\r
-      operation have been cancelled.  After the transition to\r
-      PORT_STATE_CLOSE_RX_DONE, this routine calls ::EslSocketPortClose.\r
-    </li>\r
-    <li>State: PORT_STATE_CLOSE_RX_DONE</li>\r
-    <li>Arc: ::EslSocketPortClose - This routine discards any receive buffers\r
-      using a network specific support routine via ESL_PROTOCOL_API::pfnPacketFree.\r
-      This routine then releases the port resources allocated by ::EslSocketPortAllocate\r
-      and calls the network specific port close routine (e.g. ::EslTcp4PortClose)\r
-      via ESL_PROTOCOL_API::pfnPortClose to release any network specific resources.\r
-    </li>\r
-  </ul>\r
-\r
-\r
-  \section ReceiveEngine Receive Engine\r
-\r
-  The receive path accepts data from the network and queues (buffers) it for the\r
-  application.  Flow control is applied once a maximum amount of buffering is reached\r
-  and is released when the buffer usage drops below that limit.  Eventually the\r
-  application requests data from the socket which removes entries from the queue and\r
-  returns the data.\r
-\r
-  The receive engine is the state machine which reads data from the network and\r
-  fills the queue with received packets.  The receive engine uses two data structures\r
-  to manage the network receive opeations and the buffers.\r
-\r
-  At a high level, the ::ESL_IO_MGMT structures are managing the tokens and\r
-  events for the interface to the UEFI network stack.  The ::ESL_PACKET\r
-  structures are managing the receive data buffers.  The receive engine\r
-  connects these two structures in the network specific receive completion\r
-  routines.\r
-\r
-<code><pre>\r
-\r
-      +------------------+\r
-      |     ::ESL_PORT     |\r
-      |                  |\r
-      +------------------+\r
-      |    ::ESL_IO_MGMT   |\r
-      +------------------+\r
-      |    ESL_IO_MGMT   |\r
-      +------------------+\r
-      .                  .\r
-      .    ESL_IO_MGMT   .\r
-      .                  .\r
-      +------------------+\r
-\r
-</pre></code>\r
-\r
-  The ::ESL_IO_MGMT structures are allocated as part of the ::ESL_PORT structure in\r
-  ::EslSocketPortAllocate.  The ESL_IO_MGMT structures are separated and placed on\r
-  the free list by calling ::EslSocketIoInit.  The ESL_IO_MGMT structure contains\r
-  the network layer specific receive completion token and event.  The receive engine\r
-  is eventually shutdown by ::EslSocketPortCloseTxDone and the resources in these\r
-  structures are released in ::EslSocketPortClose by a call to ::EslSocketIoFree.\r
-\r
-<code><pre>\r
-\r
-         pPort->pRxActive\r
-                |\r
-                V\r
-          +-------------+   +-------------+   +-------------+\r
-  Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-          +-------------+   +-------------+   +-------------+\r
-\r
-          +-------------+   +-------------+   +-------------+\r
-  Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-          +-------------+   +-------------+   +-------------+\r
-                ^\r
-                |\r
-          pPort->pRxFree\r
-</pre></code>\r
-\r
-  The receive engine is started by calling ::EslSocketRxStart.  Flow control pauses\r
-  the receive engine by stopping the calls to EslSocketRxStart when the amount of\r
-  receive data waiting for the application meets or exceeds MAX_RX_DATA.  After\r
-  the application reads enough data that the amount of buffering drops below this\r
-  limit, the calls to EslSockeRxStart continue which releases the flow control.\r
-\r
-  Receive flow control is applied when the port is created, since no receive\r
-  operation are pending to the low layer network driver.  The flow control gets\r
-  released when the low layer network port is configured or the first receive\r
-  operation is posted.  Flow control remains in the released state until the\r
-  maximum buffer space is consumed.  During this time, ::EslSocketRxComplete\r
-  calls ::EslSocketRxStart.  Flow control is applied in EslSocketRxComplete\r
-  by skipping the call to EslSocketRxStart.  Flow control is eventually\r
-  released in ::EslSocketReceive when the buffer space drops below the\r
-  maximum amount causing EslSocketReceive to call EslSocketRxStart.\r
-\r
-<code><pre>\r
-\r
-                    +------------+   +------------+\r
-    High     .----->| ESL_PACKET |-->| ESL_PACKET |--> NULL (pNext)\r
-  Priority   |      +------------+   +------------+\r
-             |\r
-             | pRxOobPacketListHead\r
-       +------------+\r
-       | ::ESL_SOCKET |\r
-       +------------+\r
-             | pRxPacketListHead\r
-    Low      |\r
-  Priority   |      +------------+   +------------+   +------------+\r
-             `----->| ::ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL\r
-                    +------------+   +------------+   +------------+\r
-\r
-</pre></code>\r
-\r
-  ::EslSocketRxStart connects an ::ESL_PACKET structure to the ::ESL_IO_MGMT structure\r
-  and then calls the network layer to start the receive operation.  Upon\r
-  receive completion, ::EslSocketRxComplete breaks the connection between these\r
-  structrues and places the ESL_IO_MGMT structure onto the ESL_PORT::pRxFree list to\r
-  make token and event available for another receive operation.  EslSocketRxComplete\r
-  then queues the ESL_PACKET structure (data packet) to either the\r
-  ESL_SOCKET::pRxOobPacketListTail or ESL_SOCKET::pRxPacketListTail depending on\r
-  whether urgent or normal data was received.  Finally ::EslSocketRxComplete attempts\r
-  to start another receive operation.\r
-\r
-<code><pre>\r
-\r
-  Setup for IP4 and UDP4\r
-\r
-      +--------------------+\r
-      | ESL_IO_MGMT        |\r
-      |                    |\r
-      |    +---------------+\r
-      |    | Token         |\r
-      |    |        RxData --> NULL\r
-      +----+---------------+\r
-         |\r
-         V\r
-      +--------------------+\r
-      | ESL_PACKET         |\r
-      |                    |\r
-      |    +---------------+\r
-      |    |       pRxData --> NULL\r
-      +----+---------------+\r
-\r
-  Completion for IP4 and UDP4\r
-\r
-      +--------------------+   +----------------------+\r
-      | ESL_IO_MGMT        |   |      Data Buffer     |\r
-      |                    |   |     (Driver owned)   |\r
-      |    +---------------+   +----------------------+\r
-      |    | Token         |               ^\r
-      |    |      Rx Event |               |\r
-      |    |               |   +----------------------+\r
-      |    |        RxData --> | EFI_IP4_RECEIVE_DATA |\r
-      +----+---------------+   |    (Driver owned)    |\r
-         |                     +----------------------+\r
-         V                                 ^\r
-      +--------------------+               .\r
-      | ESL_PACKET         |               .\r
-      |                    |               .\r
-      |    +---------------+               .\r
-      |    |       pRxData --> NULL  .......\r
-      +----+---------------+\r
-\r
-\r
-  Setup and completion for TCP4\r
-\r
-      +--------------------+   +--------------------------+\r
-      | ESL_IO_MGMT        |-->| ESL_PACKET               |\r
-      |                    |   |                          |\r
-      |    +---------------+   +----------------------+   |\r
-      |    | Token         |   | EFI_IP4_RECEIVE_DATA |   |\r
-      |    |        RxData --> |                      |   |\r
-      |    |               |   +----------------------+---+\r
-      |    |        Event  |   |       Data Buffer        |\r
-      +----+---------------+   |                          |\r
-                               |                          |\r
-                               +--------------------------+\r
-\r
-</pre></code>\r
-\r
-  To minimize the number of buffer copies, the data is not copied until the\r
-  application makes a receive call.  At this point socket performs a single copy\r
-  in the receive path to move the data from the buffer filled by the network layer\r
-  into the application's buffer.\r
-\r
-  The IP4 and UDP4 drivers go one step further to reduce buffer copies.  They\r
-  allow the socket layer to hold on to the actual receive buffer until the\r
-  application has performed a receive operation or closes the socket.  Both\r
-  of theses operations return the buffer to the lower layer network driver\r
-  by calling ESL_PROTOCOL_API::pfnPacketFree.\r
-\r
-  When a socket application wants to receive data it indirectly calls\r
-  ::EslSocketReceive to remove data from one of the receive data queues.  This routine\r
-  removes the next available packet from ESL_SOCKET::pRxOobPacketListHead or\r
-  ESL_SOCKET::pRxPacketListHead and copies the data from the packet\r
-  into the application's buffer.  For SOCK_STREAM sockets, if the packet\r
-  contains more data then the ESL_PACKET structures remains at the head of the\r
-  receive queue for the next application receive\r
-  operation.  For SOCK_DGRAM, SOCK_RAW and SOCK_SEQ_PACKET sockets, the ::ESL_PACKET\r
-  structure is removed from the head of the receive queue and any remaining data is\r
-  discarded as the packet is placed on the free queue.\r
-\r
-  During socket layer shutdown, ::EslSocketShutdown calls ::EslSocketRxCancel to\r
-  cancel any pending receive operations.  EslSocketRxCancel calls the network specific\r
-  cancel routine using ESL_PORT::pfnRxCancel.\r
-\r
-\r
-  \section TransmitEngine Transmit Engine\r
-\r
-  Application calls to ::EslSocketTransmit cause data to be copied into a buffer.\r
-  The buffer exists as an extension to an ESL_PACKET structure and the structure\r
-  is placed at the end of the transmit queue.\r
-\r
-<code><pre>\r
-\r
-     *ppQueueHead: pSocket->pRxPacketListHead or pSocket->pRxOobPacketListHead\r
-          |\r
-          V\r
-        +------------+   +------------+   +------------+\r
-  Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL\r
-        +------------+   +------------+   +------------+\r
-                                                     ^\r
-                                                     |\r
-     *ppQueueTail: pSocket->pRxPacketListTail or pSocket->pRxOobPacketListTail\r
-\r
-</pre></code>\r
-\r
-  There are actually two transmit queues the normal or low priority queue which is\r
-  the default and the urgent or high priority queue which is addressed by specifying\r
-  the MSG_OOB flag during the transmit request.  Associated with each queue is a\r
-  transmit engine which is responsible for sending the data in that queue.\r
-\r
-  The transmit engine is the state machine which removes entries from the head\r
-  of the transmit queue and causes the data to be sent over the network.\r
-\r
-<code><pre>\r
-\r
-      +--------------------+   +--------------------+\r
-      | ESL_IO_MGMT        |   | ESL_PACKET         |\r
-      |                    |   |                    |\r
-      |    +---------------+   +----------------+   |\r
-      |    | Token         |   | Buffer Length  |   |\r
-      |    |        TxData --> | Buffer Address |   |\r
-      |    |               |   +----------------+---+\r
-      |    |        Event  |   | Data Buffer        |\r
-      +----+---------------+   |                    |\r
-                               +--------------------+\r
-</pre></code>\r
-\r
-  At a high level, the transmit engine uses a couple of data structures\r
-  to manage the data flow.  The ::ESL_IO_MGMT structures manage the tokens and\r
-  events for the interface to the UEFI network stack.  The ::ESL_PACKET\r
-  structures manage the data buffers that get sent.  The transmit\r
-  engine connects these two structures prior to transmission and disconnects\r
-  them upon completion.\r
-\r
-<code><pre>\r
-\r
-         pPort->pTxActive or pTxOobActive\r
-                |\r
-                V\r
-          +-------------+   +-------------+   +-------------+\r
-  Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-          +-------------+   +-------------+   +-------------+\r
-\r
-          +-------------+   +-------------+   +-------------+\r
-  Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-          +-------------+   +-------------+   +-------------+\r
-                ^\r
-                |\r
-          pPort->pTxFree or pTxOobFree\r
-\r
-</pre></code>\r
-\r
-  The transmit engine manages multiple transmit operations using the\r
-  active and free lists shown above.  ::EslSocketPortAllocate allocates the\r
-  ::ESL_IO_MGMT structures as an extension to the ::ESL_PORT structure.\r
-  This routine places the ESL_IO_MGMT structures on the free list by calling\r
-  ::EslSocketIoInit.  During their lifetime, the ESL_IO_MGMT structures\r
-  will move from the free list to the active list and back again.  The\r
-  active list contains the packets that are actively being processed by\r
-  the UEFI network stack.  Eventually the ESL_IO_MGMT structures will be\r
-  removed from the free list and be deallocated by the EslSocketPortClose\r
-  routine.\r
-\r
-  The network specific code calls the ::EslSocketTxStart routine\r
-  to hand a packet to the network stack.  EslSocketTxStart connects\r
-  the transmit packet (::ESL_PACKET) to an ::ESL_IO_MGMT structure\r
-  and then queues the result to one of the active lists:\r
-  ESL_PORT::pTxActive or ESL_PORT::pTxOobActive.  The routine then\r
-  hands the packet to the network stack.\r
-\r
-  Upon completion, the network specific TxComplete routine calls\r
-  ::EslSocketTxComplete to disconnect the transmit packet from the\r
-  ESL_IO_MGMT structure and frees the ::ESL_PACKET structure by calling\r
-  ::EslSocketPacketFree.  The routine places the ::ESL_IO_MGMT structure\r
-  into the free list either ESL_PORT::pTxFree or ESL_PORT::pTxOobFree.\r
-  EslSocketTxComplete then starts the next transmit operation while\r
-  the socket is active or calls the ::EslSocketPortCloseTxDone routine\r
-  when the socket is shutting down.\r
-\r
-**/\r
-\r
-#include "Socket.h"\r
-\r
-\r
-/** Socket driver connection points\r
-\r
-  List the network stack connection points for the socket driver.\r
-**/\r
-CONST ESL_SOCKET_BINDING cEslSocketBinding[] = {\r
-  { L"Ip4",\r
-    &gEfiIp4ServiceBindingProtocolGuid,\r
-    &gEfiIp4ProtocolGuid,\r
-    &mEslIp4ServiceGuid,\r
-    OFFSET_OF ( ESL_LAYER, pIp4List ),\r
-    4,    //  RX buffers\r
-    4,    //  TX buffers\r
-    0 },  //  TX Oob buffers\r
-  { L"Tcp4",\r
-    &gEfiTcp4ServiceBindingProtocolGuid,\r
-    &gEfiTcp4ProtocolGuid,\r
-    &mEslTcp4ServiceGuid,\r
-    OFFSET_OF ( ESL_LAYER, pTcp4List ),\r
-    4,    //  RX buffers\r
-    4,    //  TX buffers\r
-    4 },  //  TX Oob buffers\r
-  { L"Tcp6",\r
-    &gEfiTcp6ServiceBindingProtocolGuid,\r
-    &gEfiTcp6ProtocolGuid,\r
-    &mEslTcp6ServiceGuid,\r
-    OFFSET_OF ( ESL_LAYER, pTcp6List ),\r
-    4,    //  RX buffers\r
-    4,    //  TX buffers\r
-    4 },  //  TX Oob buffers\r
-  { L"Udp4",\r
-    &gEfiUdp4ServiceBindingProtocolGuid,\r
-    &gEfiUdp4ProtocolGuid,\r
-    &mEslUdp4ServiceGuid,\r
-    OFFSET_OF ( ESL_LAYER, pUdp4List ),\r
-    4,    //  RX buffers\r
-    4,    //  TX buffers\r
-    0 },  //  TX Oob buffers\r
-  { L"Udp6",\r
-    &gEfiUdp6ServiceBindingProtocolGuid,\r
-    &gEfiUdp6ProtocolGuid,\r
-    &mEslUdp6ServiceGuid,\r
-    OFFSET_OF ( ESL_LAYER, pUdp6List ),\r
-    4,    //  RX buffers\r
-    4,    //  TX buffers\r
-    0 }   //  TX Oob buffers\r
-};\r
-\r
-CONST UINTN cEslSocketBindingEntries = DIM ( cEslSocketBinding );\r
-\r
-/// APIs to support the various socket types for the v4 network stack.\r
-CONST ESL_PROTOCOL_API * cEslAfInetApi[] = {\r
-  NULL,             //  0\r
-  &cEslTcp4Api,     //  SOCK_STREAM\r
-  &cEslUdp4Api,     //  SOCK_DGRAM\r
-  &cEslIp4Api,      //  SOCK_RAW\r
-  NULL,             //  SOCK_RDM\r
-  &cEslTcp4Api      //  SOCK_SEQPACKET\r
-};\r
-\r
-/// Number of entries in the v4 API array ::cEslAfInetApi.\r
-CONST int cEslAfInetApiSize = DIM ( cEslAfInetApi );\r
-\r
-\r
-/// APIs to support the various socket types for the v6 network stack.\r
-CONST ESL_PROTOCOL_API * cEslAfInet6Api[] = {\r
-  NULL,             //  0\r
-  &cEslTcp6Api,     //  SOCK_STREAM\r
-  &cEslUdp6Api,     //  SOCK_DGRAM\r
-  NULL,             //  SOCK_RAW\r
-  NULL,             //  SOCK_RDM\r
-  &cEslTcp6Api      //  SOCK_SEQPACKET\r
-};\r
-\r
-/// Number of entries in the v6 API array ::cEslAfInet6Api.\r
-CONST int cEslAfInet6ApiSize = DIM ( cEslAfInet6Api );\r
-\r
-\r
-/// Global management structure for the socket layer.\r
-ESL_LAYER mEslLayer;\r
-\r
-\r
-/** Initialize an endpoint for network communication.\r
-\r
-  This routine initializes the communication endpoint.\r
-\r
-  The ::socket routine calls this routine indirectly to create\r
-  the communication endpoint.\r
-\r
-  @param[in] pSocketProtocol Address of the socket protocol structure.\r
-  @param[in]  domain   Select the family of protocols for the client or server\r
-                       application.  See the ::socket documentation for values.\r
-  @param[in]  type     Specifies how to make the network connection.\r
-                       See the ::socket documentation for values.\r
-  @param[in]  protocol Specifies the lower layer protocol to use.\r
-                       See the ::socket documentation for values.\r
-  @param[out] pErrno   Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS - Socket successfully created\r
-  @retval EFI_INVALID_PARAMETER - Invalid domain value, errno = EAFNOSUPPORT\r
-  @retval EFI_INVALID_PARAMETER - Invalid type value, errno = EINVAL\r
-  @retval EFI_INVALID_PARAMETER - Invalid protocol value, errno = EINVAL\r
- **/\r
-EFI_STATUS\r
-EslSocket (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN int domain,\r
-  IN int type,\r
-  IN int protocol,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  CONST ESL_PROTOCOL_API * pApi;\r
-  CONST ESL_PROTOCOL_API ** ppApiArray;\r
-  CONST ESL_PROTOCOL_API ** ppApiArrayEnd;\r
-  int ApiArraySize;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  int errno;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //  Locate the socket\r
-  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
-  //  Set the default domain if necessary\r
-  if ( AF_UNSPEC == domain ) {\r
-    domain = AF_INET;\r
-  }\r
-\r
-  //  Assume success\r
-  errno = 0;\r
-  Status = EFI_SUCCESS;\r
-\r
-  //  Use break instead of goto\r
-  for ( ; ; ) {\r
-    //  Validate the domain value\r
-    if (( AF_INET != domain )\r
-      && ( AF_INET6 != domain )\r
-      && ( AF_LOCAL != domain )) {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r
-                "ERROR - Invalid domain value\r\n" ));\r
-      Status = EFI_INVALID_PARAMETER;\r
-      errno = EAFNOSUPPORT;\r
-      break;\r
-    }\r
-\r
-    //  Determine the protocol APIs\r
-    ppApiArray = NULL;\r
-    ApiArraySize = 0;\r
-    if (( AF_INET == domain )\r
-      || ( AF_LOCAL == domain )) {\r
-      ppApiArray = &cEslAfInetApi[0];\r
-      ApiArraySize = cEslAfInetApiSize;\r
-    }\r
-    else {\r
-      ppApiArray = &cEslAfInet6Api[0];\r
-      ApiArraySize = cEslAfInet6ApiSize;\r
-    }\r
-\r
-    //  Set the default type if necessary\r
-    if ( 0 == type ) {\r
-      type = SOCK_STREAM;\r
-    }\r
-\r
-    //  Validate the type value\r
-    if (( type >= ApiArraySize )\r
-      || ( NULL == ppApiArray )\r
-      || ( NULL == ppApiArray[ type ])) {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r
-                "ERROR - Invalid type value\r\n" ));\r
-      //  The socket type is not supported\r
-      Status = EFI_INVALID_PARAMETER;\r
-      errno = EPROTOTYPE;\r
-      break;\r
-    }\r
-\r
-    //  Set the default protocol if necessary\r
-    pApi = ppApiArray[ type ];\r
-    if ( 0 == protocol ) {\r
-      protocol = pApi->DefaultProtocol;\r
-    }\r
-\r
-    //  Validate the protocol value\r
-    if (( pApi->DefaultProtocol != protocol )\r
-      && ( SOCK_RAW != type )) {\r
-      Status = EFI_INVALID_PARAMETER;\r
-\r
-      //  Assume that the driver supports this protocol\r
-      ppApiArray = &cEslAfInetApi[0];\r
-      ppApiArrayEnd = &ppApiArray [ cEslAfInetApiSize ];\r
-      while ( ppApiArrayEnd > ppApiArray ) {\r
-        pApi = *ppApiArray;\r
-        if ( protocol == pApi->DefaultProtocol ) {\r
-          break;\r
-        }\r
-        ppApiArray += 1;\r
-      }\r
-      if ( ppApiArrayEnd <= ppApiArray ) {\r
-        //  Verify against the IPv6 table\r
-        ppApiArray = &cEslAfInet6Api[0];\r
-        ppApiArrayEnd = &ppApiArray [ cEslAfInet6ApiSize ];\r
-        while ( ppApiArrayEnd > ppApiArray ) {\r
-          pApi = *ppApiArray;\r
-          if ( protocol == pApi->DefaultProtocol ) {\r
-            break;\r
-          }\r
-          ppApiArray += 1;\r
-        }\r
-      }\r
-      if ( ppApiArrayEnd <= ppApiArray ) {\r
-        DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r
-                  "ERROR - The protocol is not supported!\r\n" ));\r
-        errno = EPROTONOSUPPORT;\r
-        break;\r
-      }\r
-\r
-      //  The driver does not support this protocol\r
-      DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r
-                "ERROR - The protocol does not support this socket type!\r\n" ));\r
-      errno = EPROTONOSUPPORT;\r
-      errno = EPROTOTYPE;\r
-      break;\r
-    }\r
-    //  Save the socket attributes\r
-    pSocket->pApi = pApi;\r
-    pSocket->Domain = domain;\r
-    pSocket->Type = type;\r
-    pSocket->Protocol = protocol;\r
-\r
-    //  Done\r
-    break;\r
-  }\r
-  //  Return the operation status\r
-  if ( NULL != pErrno ) {\r
-    *pErrno = errno;\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Accept a network connection.\r
-\r
-  This routine calls the network specific layer to remove the next\r
-  connection from the FIFO.\r
-\r
-  The ::accept calls this routine to poll for a network\r
-  connection to the socket.  When a connection is available\r
-  this routine returns the ::EFI_SOCKET_PROTOCOL structure address\r
-  associated with the new socket and the remote network address\r
-  if requested.\r
-\r
-  @param[in]      pSocketProtocol   Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[in]      pSockAddr         Address of a buffer to receive the remote\r
-                                    network address.\r
-  @param[in,out]  pSockAddrLength   Length in bytes of the address buffer.\r
-                                    On output specifies the length of the\r
-                                    remote network address.\r
-  @param[out]     ppSocketProtocol  Address of a buffer to receive the\r
-                                    ::EFI_SOCKET_PROTOCOL instance\r
-                                    associated with the new socket.\r
-  @param[out]     pErrno            Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS   New connection successfully created\r
-  @retval EFI_NOT_READY No connection is available\r
- **/\r
-EFI_STATUS\r
-EslSocketAccept (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN struct sockaddr * pSockAddr,\r
-  IN OUT socklen_t * pSockAddrLength,\r
-  IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  ESL_SOCKET * pNewSocket;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Validate the socket\r
-  //\r
-  pSocket = NULL;\r
-  pNewSocket = NULL;\r
-  if ( NULL != pSocketProtocol ) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
-    //\r
-    //  Verify the API\r
-    //\r
-    if ( NULL == pSocket->pApi->pfnAccept ) {\r
-      Status = EFI_UNSUPPORTED;\r
-      pSocket->errno = ENOTSUP;\r
-    }\r
-    else {\r
-      //\r
-      //  Validate the sockaddr\r
-      //\r
-      if (( NULL != pSockAddr )\r
-        && ( NULL == pSockAddrLength )) {\r
-        DEBUG (( DEBUG_ACCEPT,\r
-                  "ERROR - pSockAddr is NULL!\r\n" ));\r
-        Status = EFI_INVALID_PARAMETER;\r
-        pSocket->errno = EFAULT;\r
-      }\r
-      else {\r
-        //\r
-        //  Synchronize with the socket layer\r
-        //\r
-        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-        //\r
-        //  Verify that the socket is in the listen state\r
-        //\r
-        if ( SOCKET_STATE_LISTENING != pSocket->State ) {\r
-          DEBUG (( DEBUG_ACCEPT,\r
-                    "ERROR - Socket is not listening!\r\n" ));\r
-          if ( NULL == pSocket->pApi->pfnAccept ) {\r
-            //\r
-            //  Socket does not support listen\r
-            //\r
-            pSocket->errno = EOPNOTSUPP;\r
-            Status = EFI_UNSUPPORTED;\r
-          }\r
-          else {\r
-            //\r
-            //  Socket supports listen, but not in listen state\r
-            //\r
-            pSocket->errno = EINVAL;\r
-            Status = EFI_NOT_STARTED;\r
-          }\r
-        }\r
-        else {\r
-          //\r
-          //  Determine if a socket is available\r
-          //\r
-          if ( 0 == pSocket->FifoDepth ) {\r
-            //\r
-            //  No connections available\r
-            //  Determine if any ports are available\r
-            //\r
-            if ( NULL == pSocket->pPortList ) {\r
-              //\r
-              //  No ports available\r
-              //\r
-              Status = EFI_DEVICE_ERROR;\r
-              pSocket->errno = EINVAL;\r
-\r
-              //\r
-              //  Update the socket state\r
-              //\r
-              pSocket->State = SOCKET_STATE_NO_PORTS;\r
-            }\r
-            else {\r
-              //\r
-              //  Ports are available\r
-              //  No connection requests at this time\r
-              //\r
-              Status = EFI_NOT_READY;\r
-              pSocket->errno = EAGAIN;\r
-            }\r
-          }\r
-          else {\r
-\r
-            //\r
-            //  Attempt to accept the connection and\r
-            //  get the remote network address\r
-            //\r
-            pNewSocket = pSocket->pFifoHead;\r
-            ASSERT ( NULL != pNewSocket );\r
-            Status = pSocket->pApi->pfnAccept ( pNewSocket,\r
-                                                pSockAddr,\r
-                                                pSockAddrLength );\r
-            if ( !EFI_ERROR ( Status )) {\r
-              //\r
-              //  Remove the new socket from the list\r
-              //\r
-              pSocket->pFifoHead = pNewSocket->pNextConnection;\r
-              if ( NULL == pSocket->pFifoHead ) {\r
-                pSocket->pFifoTail = NULL;\r
-              }\r
-\r
-              //\r
-              //  Account for this socket\r
-              //\r
-              pSocket->FifoDepth -= 1;\r
-\r
-              //\r
-              //  Update the new socket's state\r
-              //\r
-              pNewSocket->State = SOCKET_STATE_CONNECTED;\r
-              pNewSocket->bConfigured = TRUE;\r
-              DEBUG (( DEBUG_ACCEPT,\r
-                        "0x%08x: Socket connected\r\n",\r
-                        pNewSocket ));\r
-            }\r
-          }\r
-        }\r
-\r
-        //\r
-        //  Release the socket layer synchronization\r
-        //\r
-        RESTORE_TPL ( TplPrevious );\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the new socket\r
-  //\r
-  if (( NULL != ppSocketProtocol )\r
-    && ( NULL != pNewSocket )) {\r
-    *ppSocketProtocol = &pNewSocket->SocketProtocol;\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    if ( NULL != pSocket ) {\r
-      *pErrno = pSocket->errno;\r
-    }\r
-    else {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = ENOTSOCK;\r
-    }\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Allocate and initialize a ESL_SOCKET structure.\r
-\r
-  This support function allocates an ::ESL_SOCKET structure\r
-  and installs a protocol on ChildHandle.  If pChildHandle is a\r
-  pointer to NULL, then a new handle is created and returned in\r
-  pChildHandle.  If pChildHandle is not a pointer to NULL, then\r
-  the protocol installs on the existing pChildHandle.\r
-\r
-  @param[in,out]  pChildHandle  Pointer to the handle of the child to create.\r
-                                If it is NULL, then a new handle is created.\r
-                                If it is a pointer to an existing UEFI handle,\r
-                                then the protocol is added to the existing UEFI\r
-                                handle.\r
-  @param[in]      DebugFlags    Flags for debug messages\r
-  @param[in,out]  ppSocket      The buffer to receive an ::ESL_SOCKET structure address.\r
-\r
-  @retval EFI_SUCCESS           The protocol was added to ChildHandle.\r
-  @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
-  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to create\r
-                                the child\r
-  @retval other                 The child handle was not created\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-EslSocketAllocate (\r
-  IN OUT EFI_HANDLE * pChildHandle,\r
-  IN     UINTN DebugFlags,\r
-  IN OUT ESL_SOCKET ** ppSocket\r
-  )\r
-{\r
-  UINTN LengthInBytes;\r
-  ESL_LAYER * pLayer;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Create a socket structure\r
-  //\r
-  LengthInBytes = sizeof ( *pSocket );\r
-  pSocket = (ESL_SOCKET *) AllocateZeroPool ( LengthInBytes );\r
-  if ( NULL != pSocket ) {\r
-    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
-              "0x%08x: Allocate pSocket, %d bytes\r\n",\r
-              pSocket,\r
-              LengthInBytes ));\r
-\r
-    //\r
-    //  Initialize the socket protocol\r
-    //\r
-    pSocket->Signature = SOCKET_SIGNATURE;\r
-    pSocket->SocketProtocol.pfnAccept = EslSocketAccept;\r
-    pSocket->SocketProtocol.pfnBind = EslSocketBind;\r
-    pSocket->SocketProtocol.pfnClosePoll = EslSocketClosePoll;\r
-    pSocket->SocketProtocol.pfnCloseStart = EslSocketCloseStart;\r
-    pSocket->SocketProtocol.pfnConnect = EslSocketConnect;\r
-    pSocket->SocketProtocol.pfnGetLocal = EslSocketGetLocalAddress;\r
-    pSocket->SocketProtocol.pfnGetPeer = EslSocketGetPeerAddress;\r
-    pSocket->SocketProtocol.pfnListen = EslSocketListen;\r
-    pSocket->SocketProtocol.pfnOptionGet = EslSocketOptionGet;\r
-    pSocket->SocketProtocol.pfnOptionSet = EslSocketOptionSet;\r
-    pSocket->SocketProtocol.pfnPoll = EslSocketPoll;\r
-    pSocket->SocketProtocol.pfnReceive = EslSocketReceive;\r
-    pSocket->SocketProtocol.pfnShutdown = EslSocketShutdown;\r
-    pSocket->SocketProtocol.pfnSocket = EslSocket;\r
-    pSocket->SocketProtocol.pfnTransmit = EslSocketTransmit;\r
-\r
-    pSocket->MaxRxBuf = MAX_RX_DATA;\r
-    pSocket->MaxTxBuf = MAX_TX_DATA;\r
-\r
-    //\r
-    //  Install the socket protocol on the specified handle\r
-    //\r
-    Status = gBS->InstallMultipleProtocolInterfaces (\r
-                    pChildHandle,\r
-                    &gEfiSocketProtocolGuid,\r
-                    &pSocket->SocketProtocol,\r
-                    NULL\r
-                    );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
-                "Installed: gEfiSocketProtocolGuid on   0x%08x\r\n",\r
-                *pChildHandle ));\r
-      pSocket->SocketProtocol.SocketHandle = *pChildHandle;\r
-\r
-      //\r
-      //  Synchronize with the socket layer\r
-      //\r
-      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-      //\r
-      //  Add this socket to the list\r
-      //\r
-      pLayer = &mEslLayer;\r
-      pSocket->pNext = pLayer->pSocketList;\r
-      pLayer->pSocketList = pSocket;\r
-\r
-      //\r
-      //  Release the socket layer synchronization\r
-      //\r
-      RESTORE_TPL ( TplPrevious );\r
-\r
-      //\r
-      //  Return the socket structure address\r
-      //\r
-      *ppSocket = pSocket;\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
-                "ERROR - Failed to install gEfiSocketProtocolGuid on 0x%08x, Status: %r\r\n",\r
-                *pChildHandle,\r
-                Status ));\r
-    }\r
-\r
-    //\r
-    //  Release the socket if necessary\r
-    //\r
-    if ( EFI_ERROR ( Status )) {\r
-      gBS->FreePool ( pSocket );\r
-      DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
-                "0x%08x: Free pSocket, %d bytes\r\n",\r
-                pSocket,\r
-                sizeof ( *pSocket )));\r
-      pSocket = NULL;\r
-    }\r
-  }\r
-  else {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Bind a name to a socket.\r
-\r
-  This routine calls the network specific layer to save the network\r
-  address of the local connection point.\r
-\r
-  The ::bind routine calls this routine to connect a name\r
-  (network address and port) to a socket on the local machine.\r
-\r
-  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[in]  pSockAddr       Address of a sockaddr structure that contains the\r
-                              connection point on the local machine.  An IPv4 address\r
-                              of INADDR_ANY specifies that the connection is made to\r
-                              all of the network stacks on the platform.  Specifying a\r
-                              specific IPv4 address restricts the connection to the\r
-                              network stack supporting that address.  Specifying zero\r
-                              for the port causes the network layer to assign a port\r
-                              number from the dynamic range.  Specifying a specific\r
-                              port number causes the network layer to use that port.\r
-  @param[in]  SockAddrLength  Specifies the length in bytes of the sockaddr structure.\r
-  @param[out] pErrno          Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS - Socket successfully created\r
-**/\r
-EFI_STATUS\r
-EslSocketBind (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN CONST struct sockaddr * pSockAddr,\r
-  IN socklen_t SockAddrLength,\r
-  OUT int * pErrno\r
-  )\r
-{\r
-  EFI_HANDLE ChildHandle;\r
-  UINT8 * pBuffer;\r
-  ESL_PORT * pPort;\r
-  ESL_SERVICE ** ppServiceListHead;\r
-  ESL_SOCKET * pSocket;\r
-  ESL_SERVICE * pService;\r
-  EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Validate the socket\r
-  //\r
-  pSocket = NULL;\r
-  if ( NULL != pSocketProtocol ) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
-    //\r
-    //  Validate the structure pointer\r
-    //\r
-    pSocket->errno = 0;\r
-    if ( NULL == pSockAddr ) {\r
-      DEBUG (( DEBUG_BIND,\r
-                "ERROR - pSockAddr is NULL!\r\n" ));\r
-      Status = EFI_INVALID_PARAMETER;\r
-      pSocket->errno = EFAULT;\r
-    }\r
-\r
-    //\r
-    //  Validate the local address length\r
-    //\r
-    else if ( SockAddrLength < pSocket->pApi->MinimumAddressLength ) {\r
-      DEBUG (( DEBUG_BIND,\r
-                "ERROR - Invalid bind name length: %d\r\n",\r
-                SockAddrLength ));\r
-      Status = EFI_INVALID_PARAMETER;\r
-      pSocket->errno = EINVAL;\r
-    }\r
-\r
-    //\r
-    //  Validate the shutdown state\r
-    //\r
-    else if ( pSocket->bRxDisable || pSocket->bTxDisable ) {\r
-      DEBUG (( DEBUG_BIND,\r
-                "ERROR - Shutdown has been called on socket 0x%08x\r\n",\r
-                pSocket ));\r
-      pSocket->errno = EINVAL;\r
-      Status = EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    //\r
-    //  Verify the socket state\r
-    //\r
-    else if ( SOCKET_STATE_NOT_CONFIGURED != pSocket->State ) {\r
-      DEBUG (( DEBUG_BIND,\r
-                "ERROR - The socket 0x%08x is already configured!\r\n",\r
-                pSocket ));\r
-      pSocket->errno = EINVAL;\r
-      Status = EFI_ALREADY_STARTED;\r
-    }\r
-    else {\r
-      //\r
-      //  Synchronize with the socket layer\r
-      //\r
-      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-      //\r
-      //  Assume no ports are available\r
-      //\r
-      pSocket->errno = EADDRNOTAVAIL;\r
-      Status = EFI_INVALID_PARAMETER;\r
-\r
-      //\r
-      //  Walk the list of services\r
-      //\r
-      pBuffer = (UINT8 *)&mEslLayer;\r
-      pBuffer = &pBuffer[ pSocket->pApi->ServiceListOffset ];\r
-      ppServiceListHead = (ESL_SERVICE **)pBuffer;\r
-      pService = *ppServiceListHead;\r
-      while ( NULL != pService ) {\r
-        //\r
-        //  Create the port\r
-        //\r
-        pServiceBinding = pService->pServiceBinding;\r
-        ChildHandle = NULL;\r
-        Status = pServiceBinding->CreateChild ( pServiceBinding,\r
-                                                &ChildHandle );\r
-        if ( !EFI_ERROR ( Status )) {\r
-          DEBUG (( DEBUG_BIND | DEBUG_POOL,\r
-                    "0x%08x: %s port handle created\r\n",\r
-                    ChildHandle,\r
-                    pService->pSocketBinding->pName ));\r
-\r
-          //\r
-          //  Open the port\r
-          //\r
-          Status = EslSocketPortAllocate ( pSocket,\r
-                                           pService,\r
-                                           ChildHandle,\r
-                                           pSockAddr,\r
-                                           TRUE,\r
-                                           DEBUG_BIND,\r
-                                           &pPort );\r
-        }\r
-        else {\r
-          DEBUG (( DEBUG_BIND | DEBUG_POOL,\r
-                    "ERROR - Failed to open %s port handle, Status: %r\r\n",\r
-                    pService->pSocketBinding->pName,\r
-                    Status ));\r
-        }\r
-\r
-        //\r
-        //  Set the next service\r
-        //\r
-        pService = pService->pNext;\r
-      }\r
-\r
-      //\r
-      //  Verify that at least one network connection was found\r
-      //\r
-      if ( NULL != pSocket->pPortList ) {\r
-        Status = EFI_SUCCESS;\r
-      }\r
-      else {\r
-        if ( EADDRNOTAVAIL == pSocket->errno ) {\r
-          DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,\r
-                    "ERROR - Socket address is not available!\r\n" ));\r
-        }\r
-        if ( EADDRINUSE == pSocket->errno ) {\r
-          DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,\r
-                    "ERROR - Socket address is in use!\r\n" ));\r
-        }\r
-        Status = EFI_INVALID_PARAMETER;\r
-      }\r
-\r
-      //\r
-      //  Mark this socket as bound if successful\r
-      //\r
-      if ( !EFI_ERROR ( Status )) {\r
-        pSocket->State = SOCKET_STATE_BOUND;\r
-        pSocket->errno = 0;\r
-      }\r
-\r
-      //\r
-      //  Release the socket layer synchronization\r
-      //\r
-      RESTORE_TPL ( TplPrevious );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    if ( NULL != pSocket ) {\r
-      *pErrno = pSocket->errno;\r
-    }\r
-    else {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = ENOTSOCK;\r
-    }\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Test the bind configuration.\r
-\r
-  @param[in] pPort        Address of the ::ESL_PORT structure.\r
-  @param[in] ErrnoValue   errno value if test fails\r
-\r
-  @retval EFI_SUCCESS   The connection was successfully established.\r
-  @retval Others        The connection attempt failed.\r
-**/\r
-EFI_STATUS\r
-EslSocketBindTest (\r
-  IN ESL_PORT * pPort,\r
-  IN int ErrnoValue\r
-  )\r
-{\r
-  UINT8 * pBuffer;\r
-  VOID * pConfigData;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Locate the configuration data\r
-  //\r
-  pBuffer = (UINT8 *)pPort;\r
-  pBuffer = &pBuffer [ pPort->pSocket->pApi->ConfigDataOffset ];\r
-  pConfigData = (VOID *)pBuffer;\r
-\r
-  //\r
-  //  Validate that the port is connected\r
-  //\r
-  Status = pPort->pSocket->pApi->pfnVerifyLocalIpAddress ( pPort, pBuffer );\r
-  if ( EFI_ERROR ( Status )) {\r
-    DEBUG (( DEBUG_WARN | DEBUG_BIND,\r
-              "WARNING - Port 0x%08x invalid IP address: %r\r\n",\r
-              pPort,\r
-              Status ));\r
-    pPort->pSocket->errno = ErrnoValue;\r
-  }\r
-  else {\r
-    //\r
-    //  Attempt to use this configuration\r
-    //\r
-    Status = pPort->pfnConfigure ( pPort->pProtocol.v, pConfigData );\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_WARN | DEBUG_BIND,\r
-                "WARNING - Port 0x%08x failed configuration, Status: %r\r\n",\r
-                pPort,\r
-                Status ));\r
-      pPort->pSocket->errno = ErrnoValue;\r
-    }\r
-    else {\r
-      //\r
-      //  Reset the port\r
-      //\r
-      Status = pPort->pfnConfigure ( pPort->pProtocol.v, NULL );\r
-      if ( EFI_ERROR ( Status )) {\r
-        DEBUG (( DEBUG_ERROR | DEBUG_BIND,\r
-                  "ERROR - Port 0x%08x failed configuration reset, Status: %r\r\n",\r
-                  pPort,\r
-                  Status ));\r
-        ASSERT ( EFI_SUCCESS == Status );\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Determine if the socket is closed.\r
-\r
-  This routine checks the state of the socket to determine if\r
-  the network specific layer has completed the close operation.\r
-\r
-  The ::close routine polls this routine to determine when the\r
-  close operation is complete.  The close operation needs to\r
-  reverse the operations of the ::EslSocketAllocate routine.\r
-\r
-  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[out] pErrno          Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS     Socket successfully closed\r
-  @retval EFI_NOT_READY   Close still in progress\r
-  @retval EFI_ALREADY     Close operation already in progress\r
-  @retval Other           Failed to close the socket\r
-**/\r
-EFI_STATUS\r
-EslSocketClosePoll (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  int errno;\r
-  ESL_LAYER * pLayer;\r
-  ESL_SOCKET * pNextSocket;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  errno = 0;\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Synchronize with the socket layer\r
-  //\r
-  RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-  //\r
-  //  Locate the socket\r
-  //\r
-  pLayer = &mEslLayer;\r
-  pNextSocket = pLayer->pSocketList;\r
-  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-  while ( NULL != pNextSocket ) {\r
-    if ( pNextSocket == pSocket ) {\r
-      //\r
-      //  Determine if the socket is in the closing state\r
-      //\r
-      if ( SOCKET_STATE_CLOSED == pSocket->State ) {\r
-        //\r
-        //  Walk the list of ports\r
-        //\r
-        if ( NULL == pSocket->pPortList ) {\r
-          //\r
-          //  All the ports are closed\r
-          //  Close the WaitAccept event if necessary\r
-          //\r
-          if ( NULL != pSocket->WaitAccept ) {\r
-            Status = gBS->CloseEvent ( pSocket->WaitAccept );\r
-            if ( !EFI_ERROR ( Status )) {\r
-              DEBUG (( DEBUG_SOCKET | DEBUG_CLOSE | DEBUG_POOL,\r
-                        "0x%08x: Closed WaitAccept event\r\n",\r
-                        pSocket->WaitAccept ));\r
-              //\r
-              //  Return the transmit status\r
-              //\r
-              Status = pSocket->TxError;\r
-              if ( EFI_ERROR ( Status )) {\r
-                pSocket->errno = EIO;\r
-              }\r
-            }\r
-            else {\r
-              DEBUG (( DEBUG_ERROR | DEBUG_SOCKET | DEBUG_CLOSE | DEBUG_POOL,\r
-                        "ERROR - Failed to close the WaitAccept event, Status: %r\r\n",\r
-                        Status ));\r
-              ASSERT ( EFI_SUCCESS == Status );\r
-            }\r
-          }\r
-        }\r
-        else {\r
-          //\r
-          //  At least one port is still open\r
-          //\r
-          Status = EFI_NOT_READY;\r
-          errno = EAGAIN;\r
-        }\r
-      }\r
-      else {\r
-        //\r
-        //  SocketCloseStart was not called\r
-        //\r
-        Status = EFI_NOT_STARTED;\r
-        errno = EPERM;\r
-      }\r
-      break;\r
-    }\r
-\r
-    //\r
-    //  Set the next socket\r
-    //\r
-    pNextSocket = pNextSocket->pNext;\r
-  }\r
-\r
-  //\r
-  //  Handle the error case where the socket was already closed\r
-  //\r
-  if ( NULL == pSocket ) {\r
-    //\r
-    //  Socket not found\r
-    //\r
-    Status = EFI_NOT_FOUND;\r
-    errno = ENOTSOCK;\r
-  }\r
-\r
-  //\r
-  //  Release the socket layer synchronization\r
-  //\r
-  RESTORE_TPL ( TplPrevious );\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    *pErrno = errno;\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Start the close operation on the socket.\r
-\r
-  This routine calls the network specific layer to initiate the\r
-  close state machine.  This routine then calls the network\r
-  specific layer to determine if the close state machine has gone\r
-  to completion.  The result from this poll is returned to the\r
-  caller.\r
-\r
-  The ::close routine calls this routine to start the close\r
-  operation which reverses the operations of the\r
-  ::EslSocketAllocate routine.  The close routine then polls\r
-  the ::EslSocketClosePoll routine to determine when the\r
-  socket is closed.\r
-\r
-  @param[in] pSocketProtocol  Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[in] bCloseNow        Boolean to control close behavior\r
-  @param[out] pErrno          Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS     Socket successfully closed\r
-  @retval EFI_NOT_READY   Close still in progress\r
-  @retval EFI_ALREADY     Close operation already in progress\r
-  @retval Other           Failed to close the socket\r
-**/\r
-EFI_STATUS\r
-EslSocketCloseStart (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN BOOLEAN bCloseNow,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  int errno;\r
-  ESL_PORT * pNextPort;\r
-  ESL_PORT * pPort;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-  errno = 0;\r
-\r
-  //\r
-  //  Synchronize with the socket layer\r
-  //\r
-  RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-  //\r
-  //  Determine if the socket is already closed\r
-  //\r
-  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-  if ( SOCKET_STATE_CLOSED > pSocket->State ) {\r
-    //\r
-    //  Update the socket state\r
-    //\r
-    pSocket->State = SOCKET_STATE_CLOSED;\r
-\r
-    //\r
-    //  Walk the list of ports\r
-    //\r
-    pPort = pSocket->pPortList;\r
-    while ( NULL != pPort ) {\r
-      //\r
-      //  Start closing the ports\r
-      //\r
-      pNextPort = pPort->pLinkSocket;\r
-      Status = EslSocketPortCloseStart ( pPort,\r
-                                         bCloseNow,\r
-                                         DEBUG_CLOSE | DEBUG_LISTEN | DEBUG_CONNECTION );\r
-      if (( EFI_SUCCESS != Status )\r
-        && ( EFI_NOT_READY != Status )) {\r
-        errno = EIO;\r
-        break;\r
-      }\r
-\r
-      //\r
-      //  Set the next port\r
-      //\r
-      pPort = pNextPort;\r
-    }\r
-\r
-    //\r
-    //  Attempt to finish closing the socket\r
-    //\r
-    if ( NULL == pPort ) {\r
-      Status = EslSocketClosePoll ( pSocketProtocol, &errno );\r
-    }\r
-  }\r
-  else {\r
-    Status = EFI_NOT_READY;\r
-    errno = EAGAIN;\r
-  }\r
-\r
-  //\r
-  //  Release the socket layer synchronization\r
-  //\r
-  RESTORE_TPL ( TplPrevious );\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    *pErrno = errno;\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Connect to a remote system via the network.\r
-\r
-  This routine calls the network specific layer to establish\r
-  the remote system address and establish the connection to\r
-  the remote system.\r
-\r
-  The ::connect routine calls this routine to establish a\r
-  connection with the specified remote system.  This routine\r
-  is designed to be polled by the connect routine for completion\r
-  of the network connection.\r
-\r
-  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[in]  pSockAddr       Network address of the remote system.\r
-  @param[in]  SockAddrLength  Length in bytes of the network address.\r
-  @param[out] pErrno          Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS     The connection was successfully established.\r
-  @retval EFI_NOT_READY   The connection is in progress, call this routine again.\r
-  @retval Others          The connection attempt failed.\r
- **/\r
-EFI_STATUS\r
-EslSocketConnect (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN const struct sockaddr * pSockAddr,\r
-  IN socklen_t SockAddrLength,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  struct sockaddr_in6 LocalAddress;\r
-  ESL_PORT * pPort;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DEBUG (( DEBUG_CONNECT, "Entering SocketConnect\r\n" ));\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Validate the socket\r
-  //\r
-  pSocket = NULL;\r
-  if ( NULL != pSocketProtocol ) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
-    //\r
-    //  Validate the name length\r
-    //\r
-    if ( SockAddrLength < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data ))) {\r
-      DEBUG (( DEBUG_CONNECT,\r
-                "ERROR - Invalid bind name length: %d\r\n",\r
-                SockAddrLength ));\r
-      Status = EFI_INVALID_PARAMETER;\r
-      pSocket->errno = EINVAL;\r
-    }\r
-    else {\r
-      //\r
-      //  Assume success\r
-      //\r
-      pSocket->errno = 0;\r
-\r
-      //\r
-      //  Synchronize with the socket layer\r
-      //\r
-      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-      //\r
-      //  Validate the socket state\r
-      //\r
-      switch ( pSocket->State ) {\r
-      default:\r
-        //\r
-        //  Wrong socket state\r
-        //\r
-        pSocket->errno = EIO;\r
-        Status = EFI_DEVICE_ERROR;\r
-        break;\r
-\r
-      case SOCKET_STATE_NOT_CONFIGURED:\r
-      case SOCKET_STATE_BOUND:\r
-        //\r
-        //  Validate the address length\r
-        //\r
-        if ( SockAddrLength >= pSocket->pApi->MinimumAddressLength ) {\r
-          //\r
-          //  Verify the API\r
-          //\r
-          if ( NULL == pSocket->pApi->pfnRemoteAddrSet ) {\r
-            //\r
-            //  Already connected\r
-            //\r
-            pSocket->errno = ENOTSUP;\r
-            Status = EFI_UNSUPPORTED;\r
-          }\r
-          else {\r
-            //\r
-            //  Determine if BIND was already called\r
-            //\r
-            if ( NULL == pSocket->pPortList ) {\r
-              //\r
-              //  Allow any local port\r
-              //\r
-              ZeroMem ( &LocalAddress, sizeof ( LocalAddress ));\r
-              LocalAddress.sin6_len = (uint8_t)pSocket->pApi->MinimumAddressLength;\r
-              LocalAddress.sin6_family = pSocket->pApi->AddressFamily;\r
-              Status = EslSocketBind ( &pSocket->SocketProtocol,\r
-                                       (struct sockaddr *)&LocalAddress,\r
-                                       LocalAddress.sin6_len,\r
-                                       &pSocket->errno );\r
-            }\r
-            if ( NULL != pSocket->pPortList ) {\r
-              //\r
-              //  Walk the list of ports\r
-              //\r
-              pPort = pSocket->pPortList;\r
-              while ( NULL != pPort ) {\r
-                //\r
-                //  Set the remote address\r
-                //\r
-                Status = pSocket->pApi->pfnRemoteAddrSet ( pPort,\r
-                                                           pSockAddr,\r
-                                                           SockAddrLength );\r
-                if ( EFI_ERROR ( Status )) {\r
-                  break;\r
-                }\r
-\r
-                //\r
-                //  Set the next port\r
-                //\r
-                pPort = pPort->pLinkSocket;\r
-              }\r
-\r
-              //\r
-              //  Verify the API\r
-              //\r
-              if (( !EFI_ERROR ( Status ))\r
-                && ( NULL != pSocket->pApi->pfnConnectStart )) {\r
-                //\r
-                //  Initiate the connection with the remote system\r
-                //\r
-                Status = pSocket->pApi->pfnConnectStart ( pSocket );\r
-\r
-                //\r
-                //  Set the next state if connecting\r
-                //\r
-                if ( EFI_NOT_READY == Status ) {\r
-                  pSocket->State = SOCKET_STATE_CONNECTING;\r
-                }\r
-              }\r
-            }\r
-          }\r
-        }\r
-        else {\r
-          DEBUG (( DEBUG_CONNECT,\r
-                    "ERROR - Invalid address length: %d\r\n",\r
-                    SockAddrLength ));\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EINVAL;\r
-        }\r
-        break;\r
-\r
-      case SOCKET_STATE_CONNECTING:\r
-        //\r
-        //  Poll the network adapter\r
-        //\r
-        EslSocketRxPoll ( pSocket );\r
-\r
-        //\r
-        //  Poll for connection completion\r
-        //\r
-        if ( NULL == pSocket->pApi->pfnConnectPoll ) {\r
-          //\r
-          //  Already connected\r
-          //\r
-          pSocket->errno = EISCONN;\r
-          Status = EFI_ALREADY_STARTED;\r
-        }\r
-        else {\r
-          Status = pSocket->pApi->pfnConnectPoll ( pSocket );\r
-\r
-          //\r
-          //  Set the next state if connected\r
-          //\r
-          if ( EFI_NOT_READY != Status ) {\r
-            if ( EFI_ERROR ( Status )) {\r
-              pSocket->State = SOCKET_STATE_BOUND;\r
-            }\r
-          }\r
-        }\r
-        break;\r
-\r
-      case SOCKET_STATE_CONNECTED:\r
-        //\r
-        //  Connected\r
-        //\r
-        Status = EFI_SUCCESS;\r
-        break;\r
-      }\r
-\r
-      //\r
-      //  Release the socket layer synchronization\r
-      //\r
-      RESTORE_TPL ( TplPrevious );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    if ( NULL != pSocket ) {\r
-      *pErrno = pSocket->errno;\r
-    }\r
-    else {\r
-      //\r
-      //  Bad socket protocol\r
-      //\r
-      DEBUG (( DEBUG_ERROR | DEBUG_CONNECT,\r
-                "ERROR - pSocketProtocol invalid!\r\n" ));\r
-      Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = ENOTSOCK;\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DEBUG (( DEBUG_CONNECT, "Exiting SocketConnect, Status: %r\r\n", Status ));\r
-  return Status;\r
-}\r
-\r
-\r
-/** Copy a fragmented buffer into a destination buffer.\r
-\r
-  This support routine copies a fragmented buffer to the caller specified buffer.\r
-\r
-  This routine is called by ::EslIp4Receive and ::EslUdp4Receive.\r
-\r
-  @param[in]  FragmentCount   Number of fragments in the table\r
-  @param[in]  pFragmentTable  Address of an EFI_IP4_FRAGMENT_DATA structure\r
-  @param[in]  BufferLength    Length of the the buffer\r
-  @param[in]  pBuffer         Address of a buffer to receive the data.\r
-  @param[in]  pDataLength     Number of received data bytes in the buffer.\r
-\r
-  @return   Returns the address of the next free byte in the buffer.\r
-**/\r
-UINT8 *\r
-EslSocketCopyFragmentedBuffer (\r
-  IN UINT32 FragmentCount,\r
-  IN EFI_IP4_FRAGMENT_DATA * pFragmentTable,\r
-  IN size_t BufferLength,\r
-  IN UINT8 * pBuffer,\r
-  OUT size_t * pDataLength\r
-  )\r
-{\r
-  size_t BytesToCopy;\r
-  UINT32 Fragment;\r
-  UINT8 * pBufferEnd;\r
-  UINT8 * pData;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Validate the IP and UDP structures are identical\r
-  //\r
-  ASSERT ( OFFSET_OF ( EFI_IP4_FRAGMENT_DATA, FragmentLength )\r
-           == OFFSET_OF ( EFI_UDP4_FRAGMENT_DATA, FragmentLength ));\r
-  ASSERT ( OFFSET_OF ( EFI_IP4_FRAGMENT_DATA, FragmentBuffer )\r
-           == OFFSET_OF ( EFI_UDP4_FRAGMENT_DATA, FragmentBuffer ));\r
-\r
-  //\r
-  //  Copy the received data\r
-  //\r
-  Fragment = 0;\r
-  pBufferEnd = &pBuffer [ BufferLength ];\r
-  while (( pBufferEnd > pBuffer ) && ( FragmentCount > Fragment )) {\r
-    //\r
-    //  Determine the amount of received data\r
-    //\r
-    pData = pFragmentTable[Fragment].FragmentBuffer;\r
-    BytesToCopy = pFragmentTable[Fragment].FragmentLength;\r
-    if (((size_t)( pBufferEnd - pBuffer )) < BytesToCopy ) {\r
-      BytesToCopy = pBufferEnd - pBuffer;\r
-    }\r
-\r
-    //\r
-    //  Move the data into the buffer\r
-    //\r
-    DEBUG (( DEBUG_RX,\r
-              "0x%08x --> 0x%08x: Copy data 0x%08x bytes\r\n",\r
-              pData,\r
-              pBuffer,\r
-              BytesToCopy ));\r
-    CopyMem ( pBuffer, pData, BytesToCopy );\r
-    pBuffer += BytesToCopy;\r
-    Fragment += 1;\r
-  }\r
-\r
-  //\r
-  //  Return the data length and the buffer address\r
-  //\r
-  *pDataLength = BufferLength - ( pBufferEnd - pBuffer );\r
-  DBG_EXIT_HEX ( pBuffer );\r
-  return pBuffer;\r
-}\r
-\r
-\r
-/** Free the socket.\r
-\r
-  This routine frees the socket structure and handle resources.\r
-\r
-  The ::close routine calls EslServiceFreeProtocol which then calls\r
-  this routine to free the socket context structure and close the\r
-  handle.\r
-\r
-  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[out] pErrno          Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS   The socket resources were returned successfully.\r
-**/\r
-EFI_STATUS\r
-EslSocketFree (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  EFI_HANDLE ChildHandle;\r
-  int errno;\r
-  ESL_LAYER * pLayer;\r
-  ESL_SOCKET * pSocket;\r
-  ESL_SOCKET * pSocketPrevious;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume failure\r
-  //\r
-  errno = EIO;\r
-  pSocket = NULL;\r
-  Status = EFI_INVALID_PARAMETER;\r
-\r
-  //\r
-  //  Validate the socket\r
-  //\r
-  pLayer = &mEslLayer;\r
-  if ( NULL != pSocketProtocol ) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
-    //\r
-    //  Synchronize with the socket layer\r
-    //\r
-    RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-    //\r
-    //  Walk the socket list\r
-    //\r
-    pSocketPrevious = pLayer->pSocketList;\r
-    if ( NULL != pSocketPrevious ) {\r
-      if ( pSocket == pSocketPrevious ) {\r
-        //\r
-        //  Remove the socket from the head of the list\r
-        //\r
-        pLayer->pSocketList = pSocket->pNext;\r
-      }\r
-      else {\r
-        //\r
-        //  Find the socket in the middle of the list\r
-        //\r
-        while (( NULL != pSocketPrevious )\r
-          && ( pSocket != pSocketPrevious->pNext )) {\r
-          //\r
-          //  Set the next socket\r
-          //\r
-          pSocketPrevious = pSocketPrevious->pNext;\r
-        }\r
-        if ( NULL != pSocketPrevious ) {\r
-          //\r
-          //  Remove the socket from the middle of the list\r
-          //\r
-          pSocketPrevious = pSocket->pNext;\r
-        }\r
-      }\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
-                "ERROR - Socket list is empty!\r\n" ));\r
-    }\r
-\r
-    //\r
-    //  Release the socket layer synchronization\r
-    //\r
-    RESTORE_TPL ( TplPrevious );\r
-\r
-    //\r
-    //  Determine if the socket was found\r
-    //\r
-    if ( NULL != pSocketPrevious ) {\r
-      pSocket->pNext = NULL;\r
-\r
-      //\r
-      //  Remove the socket protocol\r
-      //\r
-      ChildHandle = pSocket->SocketProtocol.SocketHandle;\r
-      Status = gBS->UninstallMultipleProtocolInterfaces (\r
-                ChildHandle,\r
-                &gEfiSocketProtocolGuid,\r
-                &pSocket->SocketProtocol,\r
-                NULL );\r
-      if ( !EFI_ERROR ( Status )) {\r
-        DEBUG (( DEBUG_POOL | DEBUG_INFO,\r
-                    "Removed:   gEfiSocketProtocolGuid from 0x%08x\r\n",\r
-                    ChildHandle ));\r
-\r
-        //\r
-        //  Free the socket structure\r
-        //\r
-        Status = gBS->FreePool ( pSocket );\r
-        if ( !EFI_ERROR ( Status )) {\r
-          DEBUG (( DEBUG_POOL,\r
-                    "0x%08x: Free pSocket, %d bytes\r\n",\r
-                    pSocket,\r
-                    sizeof ( *pSocket )));\r
-          errno = 0;\r
-        }\r
-        else {\r
-          DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
-                    "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",\r
-                    pSocket,\r
-                    Status ));\r
-        }\r
-      }\r
-      else {\r
-        DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,\r
-                    "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",\r
-                    ChildHandle,\r
-                    Status ));\r
-      }\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r
-                "ERROR - The socket was not in the socket list!\r\n" ));\r
-      Status = EFI_NOT_FOUND;\r
-    }\r
-  }\r
-  else {\r
-    DEBUG (( DEBUG_ERROR,\r
-              "ERROR - Invalid parameter pSocketProtocol is NULL\r\n" ));\r
-  }\r
-\r
-  //\r
-  //  Return the errno value if possible\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    *pErrno = errno;\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Get the local address.\r
-\r
-  This routine calls the network specific layer to get the network\r
-  address of the local host connection point.\r
-\r
-  The ::getsockname routine calls this routine to obtain the network\r
-  address associated with the local host connection point.\r
-\r
-  @param[in]      pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[out]     pAddress        Network address to receive the local system address\r
-  @param[in,out]  pAddressLength  Length of the local network address structure\r
-  @param[out]     pErrno          Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS - Local address successfully returned\r
- **/\r
-EFI_STATUS\r
-EslSocketGetLocalAddress (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  OUT struct sockaddr * pAddress,\r
-  IN OUT socklen_t * pAddressLength,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  socklen_t LengthInBytes;\r
-  ESL_PORT * pPort;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Validate the socket\r
-  //\r
-  pSocket = NULL;\r
-  if ( NULL != pSocketProtocol ) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
-    //\r
-    //  Verify the socket state\r
-    //\r
-    EslSocketIsConfigured ( pSocket );\r
-    if ( pSocket->bAddressSet ) {\r
-      //\r
-      //  Verify the address buffer and length address\r
-      //\r
-      if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r
-        //\r
-        //  Verify the API\r
-        //\r
-        if ( NULL == pSocket->pApi->pfnLocalAddrGet ) {\r
-          Status = EFI_UNSUPPORTED;\r
-          pSocket->errno = ENOTSUP;\r
-        }\r
-        else {\r
-          //\r
-          //  Synchronize with the socket layer\r
-          //\r
-          RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-          //\r
-          //  Verify that there is just a single connection\r
-          //\r
-          pPort = pSocket->pPortList;\r
-          if ( NULL != pPort ) {\r
-            //\r
-            //  Verify the address length\r
-            //\r
-            LengthInBytes = pSocket->pApi->AddressLength;\r
-            if (( LengthInBytes <= *pAddressLength )\r
-              && ( 255 >= LengthInBytes )) {\r
-              //\r
-              //  Return the local address and address length\r
-              //\r
-              ZeroMem ( pAddress, LengthInBytes );\r
-              pAddress->sa_len = (uint8_t)LengthInBytes;\r
-              *pAddressLength = pAddress->sa_len;\r
-              pSocket->pApi->pfnLocalAddrGet ( pPort, pAddress );\r
-              pSocket->errno = 0;\r
-              Status = EFI_SUCCESS;\r
-            }\r
-            else {\r
-              pSocket->errno = EINVAL;\r
-              Status = EFI_INVALID_PARAMETER;\r
-            }\r
-          }\r
-          else {\r
-            pSocket->errno = ENOTCONN;\r
-            Status = EFI_NOT_STARTED;\r
-          }\r
-\r
-          //\r
-          //  Release the socket layer synchronization\r
-          //\r
-          RESTORE_TPL ( TplPrevious );\r
-        }\r
-      }\r
-      else {\r
-        pSocket->errno = EINVAL;\r
-        Status = EFI_INVALID_PARAMETER;\r
-      }\r
-    }\r
-    else {\r
-      //\r
-      //  Address not set\r
-      //\r
-      Status = EFI_NOT_STARTED;\r
-      pSocket->errno = EADDRNOTAVAIL;\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    if ( NULL != pSocket ) {\r
-      *pErrno = pSocket->errno;\r
-    }\r
-    else {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = ENOTSOCK;\r
-    }\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Get the peer address.\r
-\r
-  This routine calls the network specific layer to get the remote\r
-  system connection point.\r
-\r
-  The ::getpeername routine calls this routine to obtain the network\r
-  address of the remote connection point.\r
-\r
-  @param[in]      pSocketProtocol   Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[out]     pAddress          Network address to receive the remote system address\r
-  @param[in,out]  pAddressLength    Length of the remote network address structure\r
-  @param[out]     pErrno            Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS - Remote address successfully returned\r
- **/\r
-EFI_STATUS\r
-EslSocketGetPeerAddress (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  OUT struct sockaddr * pAddress,\r
-  IN OUT socklen_t * pAddressLength,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  socklen_t LengthInBytes;\r
-  ESL_PORT * pPort;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Validate the socket\r
-  //\r
-  pSocket = NULL;\r
-  if ( NULL != pSocketProtocol ) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
-    //\r
-    //  Verify the socket state\r
-    //\r
-    Status = EslSocketIsConfigured ( pSocket );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      //\r
-      //  Verify the API\r
-      //\r
-      if ( NULL == pSocket->pApi->pfnRemoteAddrGet ) {\r
-        Status = EFI_UNSUPPORTED;\r
-        pSocket->errno = ENOTSUP;\r
-      }\r
-      else {\r
-        //\r
-        //  Verify the address buffer and length address\r
-        //\r
-        if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r
-          //\r
-          //  Verify the socket state\r
-          //\r
-          if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
-            //\r
-            //  Synchronize with the socket layer\r
-            //\r
-            RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-            //\r
-            //  Verify that there is just a single connection\r
-            //\r
-            pPort = pSocket->pPortList;\r
-            if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {\r
-              //\r
-              //  Verify the address length\r
-              //\r
-              LengthInBytes = pSocket->pApi->AddressLength;\r
-              if ( LengthInBytes <= *pAddressLength ) {\r
-                //\r
-                //  Return the local address\r
-                //\r
-                ZeroMem ( pAddress, LengthInBytes );\r
-                pAddress->sa_len = (uint8_t)LengthInBytes;\r
-                *pAddressLength = pAddress->sa_len;\r
-                pSocket->pApi->pfnRemoteAddrGet ( pPort, pAddress );\r
-                pSocket->errno = 0;\r
-                Status = EFI_SUCCESS;\r
-              }\r
-              else {\r
-                pSocket->errno = EINVAL;\r
-                Status = EFI_INVALID_PARAMETER;\r
-              }\r
-            }\r
-            else {\r
-              pSocket->errno = ENOTCONN;\r
-              Status = EFI_NOT_STARTED;\r
-            }\r
-\r
-            //\r
-            //  Release the socket layer synchronization\r
-            //\r
-            RESTORE_TPL ( TplPrevious );\r
-          }\r
-          else {\r
-            pSocket->errno = ENOTCONN;\r
-            Status = EFI_NOT_STARTED;\r
-          }\r
-        }\r
-        else {\r
-          pSocket->errno = EINVAL;\r
-          Status = EFI_INVALID_PARAMETER;\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    if ( NULL != pSocket ) {\r
-      *pErrno = pSocket->errno;\r
-    }\r
-    else {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = ENOTSOCK;\r
-    }\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Free the ESL_IO_MGMT event and structure.\r
-\r
-  This support routine walks the free list to close the event in\r
-  the ESL_IO_MGMT structure and remove the structure from the free\r
-  list.\r
-\r
-  See the \ref TransmitEngine section.\r
-\r
-  @param[in]  pPort         Address of an ::ESL_PORT structure\r
-  @param[in]  ppFreeQueue   Address of the free queue head\r
-  @param[in]  DebugFlags    Flags for debug messages\r
-  @param[in]  pEventName    Zero terminated string containing the event name\r
-\r
-  @retval EFI_SUCCESS - The structures were properly initialized\r
-**/\r
-EFI_STATUS\r
-EslSocketIoFree (\r
-  IN ESL_PORT * pPort,\r
-  IN ESL_IO_MGMT ** ppFreeQueue,\r
-  IN UINTN DebugFlags,\r
-  IN CHAR8 * pEventName\r
-  )\r
-{\r
-  UINT8 * pBuffer;\r
-  EFI_EVENT * pEvent;\r
-  ESL_IO_MGMT * pIo;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Walk the list of IO structures\r
-  //\r
-  pSocket = pPort->pSocket;\r
-  while ( *ppFreeQueue ) {\r
-    //\r
-    //  Free the event for this structure\r
-    //\r
-    pIo = *ppFreeQueue;\r
-    pBuffer = (UINT8 *)pIo;\r
-    pBuffer = &pBuffer[ pSocket->TxTokenEventOffset ];\r
-    pEvent = (EFI_EVENT *)pBuffer;\r
-    Status = gBS->CloseEvent ( *pEvent );\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to close the %a event, Status: %r\r\n",\r
-                pEventName,\r
-                Status ));\r
-      pSocket->errno = ENOMEM;\r
-      break;\r
-    }\r
-    DEBUG (( DebugFlags,\r
-              "0x%08x: Closed %a event 0x%08x\r\n",\r
-              pIo,\r
-              pEventName,\r
-              *pEvent ));\r
-\r
-    //\r
-    //  Remove this structure from the queue\r
-    //\r
-    *ppFreeQueue = pIo->pNext;\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Initialize the ESL_IO_MGMT structures.\r
-\r
-  This support routine initializes the ESL_IO_MGMT structure and\r
-  places them on to a free list.\r
-\r
-  This routine is called by ::EslSocketPortAllocate routines to prepare\r
-  the transmit engines.  See the \ref TransmitEngine section.\r
-\r
-  @param[in]        pPort         Address of an ::ESL_PORT structure\r
-  @param[in, out]   ppIo          Address containing the first structure address.  Upon\r
-                                  return this buffer contains the next structure address.\r
-  @param[in]        TokenCount    Number of structures to initialize\r
-  @param[in]        ppFreeQueue   Address of the free queue head\r
-  @param[in]        DebugFlags    Flags for debug messages\r
-  @param[in]        pEventName    Zero terminated string containing the event name\r
-  @param[in]        pfnCompletion Completion routine address\r
-\r
-  @retval EFI_SUCCESS - The structures were properly initialized\r
-**/\r
-EFI_STATUS\r
-EslSocketIoInit (\r
-  IN ESL_PORT * pPort,\r
-  IN ESL_IO_MGMT ** ppIo,\r
-  IN UINTN TokenCount,\r
-  IN ESL_IO_MGMT ** ppFreeQueue,\r
-  IN UINTN DebugFlags,\r
-  IN CHAR8 * pEventName,\r
-  IN PFN_API_IO_COMPLETE pfnCompletion\r
-  )\r
-{\r
-  ESL_IO_MGMT * pEnd;\r
-  EFI_EVENT * pEvent;\r
-  ESL_IO_MGMT * pIo;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Walk the list of IO structures\r
-  //\r
-  pSocket = pPort->pSocket;\r
-  pIo = *ppIo;\r
-  pEnd = &pIo [ TokenCount ];\r
-  while ( pEnd > pIo ) {\r
-    //\r
-    //  Initialize the IO structure\r
-    //\r
-    pIo->pPort = pPort;\r
-    pIo->pPacket = NULL;\r
-\r
-    //\r
-    //  Allocate the event for this structure\r
-    //\r
-    pEvent = (EFI_EVENT *)&(((UINT8 *)pIo)[ pSocket->TxTokenEventOffset ]);\r
-    Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,\r
-                                TPL_SOCKETS,\r
-                                (EFI_EVENT_NOTIFY)pfnCompletion,\r
-                                pIo,\r
-                                pEvent );\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to create the %a event, Status: %r\r\n",\r
-                pEventName,\r
-                Status ));\r
-      pSocket->errno = ENOMEM;\r
-      break;\r
-    }\r
-    DEBUG (( DebugFlags,\r
-              "0x%08x: Created %a event 0x%08x\r\n",\r
-              pIo,\r
-              pEventName,\r
-              *pEvent ));\r
-\r
-    //\r
-    //  Add this structure to the queue\r
-    //\r
-    pIo->pNext = *ppFreeQueue;\r
-    *ppFreeQueue = pIo;\r
-\r
-    //\r
-    //  Set the next structure\r
-    //\r
-    pIo += 1;\r
-  }\r
-\r
-  //\r
-  //  Save the next structure\r
-  //\r
-  *ppIo = pIo;\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Determine if the socket is configured.\r
-\r
-  This support routine is called to determine if the socket if the\r
-  configuration call was made to the network layer.  The following\r
-  routines call this routine to verify that they may be successful\r
-  in their operations:\r
-  <ul>\r
-    <li>::EslSocketGetLocalAddress</li>\r
-    <li>::EslSocketGetPeerAddress</li>\r
-    <li>::EslSocketPoll</li>\r
-    <li>::EslSocketReceive</li>\r
-    <li>::EslSocketTransmit</li>\r
-  </ul>\r
-\r
-  @param[in]  pSocket       Address of an ::ESL_SOCKET structure\r
-\r
-  @retval EFI_SUCCESS - The socket is configured\r
-**/\r
-EFI_STATUS\r
-EslSocketIsConfigured (\r
-  IN ESL_SOCKET * pSocket\r
-  )\r
-{\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Verify the socket state\r
-  //\r
-  if ( !pSocket->bConfigured ) {\r
-    DBG_ENTER ( );\r
-\r
-    //\r
-    //  Verify the API\r
-    //\r
-    if ( NULL == pSocket->pApi->pfnIsConfigured ) {\r
-      Status = EFI_UNSUPPORTED;\r
-      pSocket->errno = ENOTSUP;\r
-    }\r
-    else {\r
-      //\r
-      //  Synchronize with the socket layer\r
-      //\r
-      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-      //\r
-      //  Determine if the socket is configured\r
-      //\r
-      Status = pSocket->pApi->pfnIsConfigured ( pSocket );\r
-\r
-      //\r
-      //  Release the socket layer synchronization\r
-      //\r
-      RESTORE_TPL ( TplPrevious );\r
-\r
-      //\r
-      //  Set errno if a failure occurs\r
-      //\r
-      if ( EFI_ERROR ( Status )) {\r
-        pSocket->errno = EADDRNOTAVAIL;\r
-      }\r
-    }\r
-\r
-    DBG_EXIT_STATUS ( Status );\r
-  }\r
-\r
-  //\r
-  //  Return the configuration status\r
-  //\r
-  return Status;\r
-}\r
-\r
-\r
-/** Establish the known port to listen for network connections.\r
-\r
-  This routine calls into the network protocol layer to establish\r
-  a handler that is called upon connection completion.  The handler\r
-  is responsible for inserting the connection into the FIFO.\r
-\r
-  The ::listen routine indirectly calls this routine to place the\r
-  socket into a state that enables connection attempts.  Connections\r
-  are placed in a FIFO that is serviced by the application.  The\r
-  application calls the ::accept (::EslSocketAccept) routine to\r
-  remove the next connection from the FIFO and get the associated\r
-  socket and address.\r
-\r
-  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[in]  Backlog         Backlog specifies the maximum FIFO depth for\r
-                              the connections waiting for the application\r
-                              to call accept.  Connection attempts received\r
-                              while the queue is full are refused.\r
-  @param[out] pErrno          Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS - Socket successfully created\r
-  @retval Other - Failed to enable the socket for listen\r
-**/\r
-EFI_STATUS\r
-EslSocketListen (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN INT32 Backlog,\r
-  OUT int * pErrno\r
-  )\r
-{\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  EFI_STATUS TempStatus;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Validate the socket\r
-  //\r
-  pSocket = NULL;\r
-  if ( NULL != pSocketProtocol ) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
-    //\r
-    //  Verify the API\r
-    //\r
-    if ( NULL == pSocket->pApi->pfnListen ) {\r
-      Status = EFI_UNSUPPORTED;\r
-      pSocket->errno = ENOTSUP;\r
-    }\r
-    else {\r
-      //\r
-      //  Assume success\r
-      //\r
-      pSocket->Status = EFI_SUCCESS;\r
-      pSocket->errno = 0;\r
-\r
-      //\r
-      //  Verify that the bind operation was successful\r
-      //\r
-      if ( SOCKET_STATE_BOUND == pSocket->State ) {\r
-        //\r
-        //  Synchronize with the socket layer\r
-        //\r
-        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-        //\r
-        //  Create the event for SocketAccept completion\r
-        //\r
-        Status = gBS->CreateEvent ( 0,\r
-                                    TPL_SOCKETS,\r
-                                    NULL,\r
-                                    NULL,\r
-                                    &pSocket->WaitAccept );\r
-        if ( !EFI_ERROR ( Status )) {\r
-          DEBUG (( DEBUG_POOL,\r
-                    "0x%08x: Created WaitAccept event\r\n",\r
-                    pSocket->WaitAccept ));\r
-          //\r
-          //  Set the maximum FIFO depth\r
-          //\r
-          if ( 0 >= Backlog ) {\r
-            Backlog = MAX_PENDING_CONNECTIONS;\r
-          }\r
-          else {\r
-            if ( SOMAXCONN < Backlog ) {\r
-              Backlog = SOMAXCONN;\r
-            }\r
-            else {\r
-              pSocket->MaxFifoDepth = Backlog;\r
-            }\r
-          }\r
-\r
-          //\r
-          //  Initiate the connection attempt listen\r
-          //\r
-          Status = pSocket->pApi->pfnListen ( pSocket );\r
-\r
-          //\r
-          //  Place the socket in the listen state if successful\r
-          //\r
-          if ( !EFI_ERROR ( Status )) {\r
-            pSocket->State = SOCKET_STATE_LISTENING;\r
-            pSocket->bListenCalled = TRUE;\r
-          }\r
-          else {\r
-            //\r
-            //  Not waiting for SocketAccept to complete\r
-            //\r
-            TempStatus = gBS->CloseEvent ( pSocket->WaitAccept );\r
-            if ( !EFI_ERROR ( TempStatus )) {\r
-              DEBUG (( DEBUG_POOL,\r
-                        "0x%08x: Closed WaitAccept event\r\n",\r
-                        pSocket->WaitAccept ));\r
-              pSocket->WaitAccept = NULL;\r
-            }\r
-            else {\r
-              DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
-                        "ERROR - Failed to close WaitAccept event, Status: %r\r\n",\r
-                        TempStatus ));\r
-              ASSERT ( EFI_SUCCESS == TempStatus );\r
-            }\r
-          }\r
-        }\r
-        else {\r
-          DEBUG (( DEBUG_ERROR | DEBUG_LISTEN,\r
-                    "ERROR - Failed to create the WaitAccept event, Status: %r\r\n",\r
-                    Status ));\r
-          pSocket->errno = ENOMEM;\r
-        }\r
-\r
-        //\r
-        //  Release the socket layer synchronization\r
-        //\r
-        RESTORE_TPL ( TplPrevious );\r
-      }\r
-      else {\r
-        DEBUG (( DEBUG_ERROR | DEBUG_LISTEN,\r
-                  "ERROR - Bind operation must be performed first!\r\n" ));\r
-        pSocket->errno = ( SOCKET_STATE_NOT_CONFIGURED == pSocket->State ) ? EDESTADDRREQ\r
-                                                                           : EINVAL;\r
-        Status = EFI_NO_MAPPING;\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    if ( NULL != pSocket ) {\r
-      *pErrno = pSocket->errno;\r
-    }\r
-    else {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = ENOTSOCK;\r
-    }\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Get the socket options.\r
-\r
-  This routine handles the socket level options and passes the\r
-  others to the network specific layer.\r
-\r
-  The ::getsockopt routine calls this routine to retrieve the\r
-  socket options one at a time by name.\r
-\r
-  @param[in]      pSocketProtocol   Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[in]      level             Option protocol level\r
-  @param[in]      OptionName        Name of the option\r
-  @param[out]     pOptionValue      Buffer to receive the option value\r
-  @param[in,out]  pOptionLength     Length of the buffer in bytes,\r
-                                    upon return length of the option value in bytes\r
-  @param[out]     pErrno            Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS - Socket data successfully received\r
- **/\r
-EFI_STATUS\r
-EslSocketOptionGet (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN int level,\r
-  IN int OptionName,\r
-  OUT void * __restrict pOptionValue,\r
-  IN OUT socklen_t * __restrict pOptionLength,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  int errno;\r
-  socklen_t LengthInBytes;\r
-  socklen_t MaxBytes;\r
-  CONST UINT8 * pOptionData;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume failure\r
-  //\r
-  errno = EINVAL;\r
-  Status = EFI_INVALID_PARAMETER;\r
-\r
-  //\r
-  //  Validate the socket\r
-  //\r
-  pSocket = NULL;\r
-  if ( NULL == pSocketProtocol ) {\r
-    DEBUG (( DEBUG_OPTION, "ERROR - pSocketProtocol is NULL!\r\n" ));\r
-  }\r
-  else if ( NULL == pOptionValue ) {\r
-    DEBUG (( DEBUG_OPTION, "ERROR - No option buffer specified\r\n" ));\r
-  }\r
-  else if ( NULL == pOptionLength ) {\r
-    DEBUG (( DEBUG_OPTION, "ERROR - Option length not specified!\r\n" ));\r
-  }\r
-  else {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-    LengthInBytes = 0;\r
-    MaxBytes = *pOptionLength;\r
-    pOptionData = NULL;\r
-    switch ( level ) {\r
-    default:\r
-      //\r
-      //  See if the protocol will handle the option\r
-      //\r
-      if ( NULL != pSocket->pApi->pfnOptionGet ) {\r
-        if ( pSocket->pApi->DefaultProtocol == level ) {\r
-          Status = pSocket->pApi->pfnOptionGet ( pSocket,\r
-                                                 OptionName,\r
-                                                 (CONST void ** __restrict)&pOptionData,\r
-                                                 &LengthInBytes );\r
-          errno = pSocket->errno;\r
-          break;\r
-        }\r
-        else {\r
-          //\r
-          //  Protocol not supported\r
-          //\r
-          DEBUG (( DEBUG_OPTION,\r
-                    "ERROR - The socket does not support this protocol!\r\n" ));\r
-        }\r
-      }\r
-      else {\r
-        //\r
-        //  Protocol level not supported\r
-        //\r
-        DEBUG (( DEBUG_OPTION,\r
-                  "ERROR - %a does not support any options!\r\n",\r
-                  pSocket->pApi->pName ));\r
-      }\r
-      errno = ENOPROTOOPT;\r
-      Status = EFI_INVALID_PARAMETER;\r
-      break;\r
-\r
-    case SOL_SOCKET:\r
-      switch ( OptionName ) {\r
-      default:\r
-        //\r
-        //  Socket option not supported\r
-        //\r
-        DEBUG (( DEBUG_INFO | DEBUG_OPTION, "ERROR - Invalid socket option!\r\n" ));\r
-        errno = EINVAL;\r
-        Status = EFI_INVALID_PARAMETER;\r
-        break;\r
-\r
-      case SO_ACCEPTCONN:\r
-        //\r
-        //  Return the listen flag\r
-        //\r
-        pOptionData = (CONST UINT8 *)&pSocket->bListenCalled;\r
-        LengthInBytes = sizeof ( pSocket->bListenCalled );\r
-        break;\r
-\r
-      case SO_DEBUG:\r
-        //\r
-        //  Return the debug flags\r
-        //\r
-        pOptionData = (CONST UINT8 *)&pSocket->bOobInLine;\r
-        LengthInBytes = sizeof ( pSocket->bOobInLine );\r
-        break;\r
-\r
-      case SO_OOBINLINE:\r
-        //\r
-        //  Return the out-of-band inline flag\r
-        //\r
-        pOptionData = (CONST UINT8 *)&pSocket->bOobInLine;\r
-        LengthInBytes = sizeof ( pSocket->bOobInLine );\r
-        break;\r
-\r
-      case SO_RCVTIMEO:\r
-        //\r
-        //  Return the receive timeout\r
-        //\r
-        pOptionData = (CONST UINT8 *)&pSocket->RxTimeout;\r
-        LengthInBytes = sizeof ( pSocket->RxTimeout );\r
-        break;\r
-\r
-      case SO_RCVBUF:\r
-        //\r
-        //  Return the maximum receive buffer size\r
-        //\r
-        pOptionData = (CONST UINT8 *)&pSocket->MaxRxBuf;\r
-        LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r
-        break;\r
-\r
-      case SO_REUSEADDR:\r
-        //\r
-        //  Return the address reuse flag\r
-        //\r
-        pOptionData = (UINT8 *)&pSocket->bReUseAddr;\r
-        LengthInBytes = sizeof ( pSocket->bReUseAddr );\r
-        break;\r
-\r
-      case SO_SNDBUF:\r
-        //\r
-        //  Return the maximum transmit buffer size\r
-        //\r
-        pOptionData = (CONST UINT8 *)&pSocket->MaxTxBuf;\r
-        LengthInBytes = sizeof ( pSocket->MaxTxBuf );\r
-        break;\r
-\r
-      case SO_TYPE:\r
-        //\r
-        //  Return the socket type\r
-        //\r
-        pOptionData = (CONST UINT8 *)&pSocket->Type;\r
-        LengthInBytes = sizeof ( pSocket->Type );\r
-        break;\r
-      }\r
-      break;\r
-    }\r
-\r
-    //\r
-    //  Return the option length\r
-    //\r
-    *pOptionLength = LengthInBytes;\r
-\r
-    //\r
-    //  Determine if the option is present\r
-    //\r
-    if ( 0 != LengthInBytes ) {\r
-      //\r
-      //  Silently truncate the value length\r
-      //\r
-      if ( LengthInBytes > MaxBytes ) {\r
-        DEBUG (( DEBUG_OPTION,\r
-                  "INFO - Truncating option from %d to %d bytes\r\n",\r
-                  LengthInBytes,\r
-                  MaxBytes ));\r
-        LengthInBytes = MaxBytes;\r
-      }\r
-\r
-      //\r
-      //  Return the value\r
-      //\r
-      CopyMem ( pOptionValue, pOptionData, LengthInBytes );\r
-\r
-      //\r
-      //  Zero fill any remaining space\r
-      //\r
-      if ( LengthInBytes < MaxBytes ) {\r
-        ZeroMem ( &((UINT8 *)pOptionValue)[LengthInBytes], MaxBytes - LengthInBytes );\r
-      }\r
-      errno = 0;\r
-      Status = EFI_SUCCESS;\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    *pErrno = errno;\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Set the socket options.\r
-\r
-  This routine handles the socket level options and passes the\r
-  others to the network specific layer.\r
-\r
-  The ::setsockopt routine calls this routine to adjust the socket\r
-  options one at a time by name.\r
-\r
-  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[in]  level           Option protocol level\r
-  @param[in]  OptionName      Name of the option\r
-  @param[in]  pOptionValue    Buffer containing the option value\r
-  @param[in]  OptionLength    Length of the buffer in bytes\r
-  @param[out] pErrno          Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS - Option successfully set\r
-**/\r
-EFI_STATUS\r
-EslSocketOptionSet (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN int level,\r
-  IN int OptionName,\r
-  IN CONST void * pOptionValue,\r
-  IN socklen_t OptionLength,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  BOOLEAN bTrueFalse;\r
-  int errno;\r
-  socklen_t LengthInBytes;\r
-  UINT8 * pOptionData;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume failure\r
-  //\r
-  errno = EINVAL;\r
-  Status = EFI_INVALID_PARAMETER;\r
-\r
-  //\r
-  //  Validate the socket\r
-  //\r
-  pSocket = NULL;\r
-  if ( NULL == pSocketProtocol ) {\r
-    DEBUG (( DEBUG_OPTION, "ERROR - pSocketProtocol is NULL!\r\n" ));\r
-  }\r
-  else if ( NULL == pOptionValue ) {\r
-    DEBUG (( DEBUG_OPTION, "ERROR - No option buffer specified\r\n" ));\r
-  }\r
-  else\r
-  {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-    if ( pSocket->bRxDisable || pSocket->bTxDisable ) {\r
-      DEBUG (( DEBUG_OPTION, "ERROR - Socket has been shutdown!\r\n" ));\r
-    }\r
-    else {\r
-      LengthInBytes = 0;\r
-      pOptionData = NULL;\r
-      switch ( level ) {\r
-      default:\r
-        //\r
-        //  See if the protocol will handle the option\r
-        //\r
-        if ( NULL != pSocket->pApi->pfnOptionSet ) {\r
-          if ( pSocket->pApi->DefaultProtocol == level ) {\r
-            Status = pSocket->pApi->pfnOptionSet ( pSocket,\r
-                                                   OptionName,\r
-                                                   pOptionValue,\r
-                                                   OptionLength );\r
-            errno = pSocket->errno;\r
-            break;\r
-          }\r
-          else {\r
-            //\r
-            //  Protocol not supported\r
-            //\r
-            DEBUG (( DEBUG_OPTION,\r
-                      "ERROR - The socket does not support this protocol!\r\n" ));\r
-          }\r
-        }\r
-        else {\r
-          //\r
-          //  Protocol level not supported\r
-          //\r
-          DEBUG (( DEBUG_OPTION,\r
-                    "ERROR - %a does not support any options!\r\n",\r
-                    pSocket->pApi->pName ));\r
-        }\r
-        errno = ENOPROTOOPT;\r
-        Status = EFI_INVALID_PARAMETER;\r
-        break;\r
-\r
-      case SOL_SOCKET:\r
-        switch ( OptionName ) {\r
-        default:\r
-          //\r
-          //  Option not supported\r
-          //\r
-          DEBUG (( DEBUG_OPTION,\r
-                    "ERROR - Sockets does not support this option!\r\n" ));\r
-          errno = EINVAL;\r
-          Status = EFI_INVALID_PARAMETER;\r
-          break;\r
-\r
-        case SO_DEBUG:\r
-          //\r
-          //  Set the debug flags\r
-          //\r
-          pOptionData = (UINT8 *)&pSocket->bOobInLine;\r
-          LengthInBytes = sizeof ( pSocket->bOobInLine );\r
-          break;\r
-\r
-        case SO_OOBINLINE:\r
-          pOptionData = (UINT8 *)&pSocket->bOobInLine;\r
-          LengthInBytes = sizeof ( pSocket->bOobInLine );\r
-\r
-          //\r
-          //  Validate the option length\r
-          //\r
-          if ( sizeof ( UINT32 ) == OptionLength ) {\r
-            //\r
-            //  Restrict the input to TRUE or FALSE\r
-            //\r
-            bTrueFalse = TRUE;\r
-            if ( 0 == *(UINT32 *)pOptionValue ) {\r
-              bTrueFalse = FALSE;\r
-            }\r
-            pOptionValue = &bTrueFalse;\r
-          }\r
-          else {\r
-            //\r
-            //  Force an invalid option length error\r
-            //\r
-            OptionLength = LengthInBytes - 1;\r
-          }\r
-          break;\r
-\r
-        case SO_RCVTIMEO:\r
-          //\r
-          //  Return the receive timeout\r
-          //\r
-          pOptionData = (UINT8 *)&pSocket->RxTimeout;\r
-          LengthInBytes = sizeof ( pSocket->RxTimeout );\r
-          break;\r
-\r
-        case SO_RCVBUF:\r
-          //\r
-          //  Return the maximum receive buffer size\r
-          //\r
-          pOptionData = (UINT8 *)&pSocket->MaxRxBuf;\r
-          LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r
-          break;\r
-\r
-        case SO_REUSEADDR:\r
-          //\r
-          //  Return the address reuse flag\r
-          //\r
-          pOptionData = (UINT8 *)&pSocket->bReUseAddr;\r
-          LengthInBytes = sizeof ( pSocket->bReUseAddr );\r
-          break;\r
-\r
-        case SO_SNDBUF:\r
-          //\r
-          //  Send buffer size\r
-          //\r
-          //\r
-          //  Return the maximum transmit buffer size\r
-          //\r
-          pOptionData = (UINT8 *)&pSocket->MaxTxBuf;\r
-          LengthInBytes = sizeof ( pSocket->MaxTxBuf );\r
-          break;\r
-        }\r
-        break;\r
-      }\r
-\r
-      //\r
-      //  Determine if an option was found\r
-      //\r
-      if ( 0 != LengthInBytes ) {\r
-        //\r
-        //  Validate the option length\r
-        //\r
-        if ( LengthInBytes <= OptionLength ) {\r
-          //\r
-          //  Set the option value\r
-          //\r
-          CopyMem ( pOptionData, pOptionValue, LengthInBytes );\r
-          errno = 0;\r
-          Status = EFI_SUCCESS;\r
-        }\r
-        else {\r
-          DEBUG (( DEBUG_OPTION,\r
-                    "ERROR - Buffer to small, %d bytes < %d bytes!\r\n",\r
-                    OptionLength,\r
-                    LengthInBytes ));\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    *pErrno = errno;\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**  Allocate a packet for a receive or transmit operation.\r
-\r
-  This support routine is called by ::EslSocketRxStart and the\r
-  network specific TxBuffer routines to get buffer space for the\r
-  next operation.\r
-\r
-  @param[in]  ppPacket      Address to receive the ::ESL_PACKET structure\r
-  @param[in]  LengthInBytes Length of the packet structure\r
-  @param[in]  ZeroBytes     Length of packet to zero\r
-  @param[in]  DebugFlags    Flags for debug messages\r
-\r
-  @retval EFI_SUCCESS - The packet was allocated successfully\r
-**/\r
-EFI_STATUS\r
-EslSocketPacketAllocate (\r
-  IN ESL_PACKET ** ppPacket,\r
-  IN size_t LengthInBytes,\r
-  IN size_t ZeroBytes,\r
-  IN UINTN DebugFlags\r
-  )\r
-{\r
-  ESL_PACKET * pPacket;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Allocate a packet structure\r
-  //\r
-  LengthInBytes += sizeof ( *pPacket )\r
-                - sizeof ( pPacket->Op );\r
-  Status = gBS->AllocatePool ( EfiRuntimeServicesData,\r
-                               LengthInBytes,\r
-                               (VOID **)&pPacket );\r
-  if ( !EFI_ERROR ( Status )) {\r
-    DEBUG (( DebugFlags | DEBUG_POOL,\r
-              "0x%08x: Allocate pPacket, %d bytes\r\n",\r
-              pPacket,\r
-              LengthInBytes ));\r
-    if ( 0 != ZeroBytes ) {\r
-      ZeroMem ( &pPacket->Op, ZeroBytes );\r
-    }\r
-    pPacket->PacketSize = LengthInBytes;\r
-  }\r
-  else {\r
-    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INFO,\r
-              "ERROR - Packet allocation failed for %d bytes, Status: %r\r\n",\r
-              LengthInBytes,\r
-              Status ));\r
-    pPacket = NULL;\r
-  }\r
-\r
-  //\r
-  //  Return the packet\r
-  //\r
-  *ppPacket = pPacket;\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Free a packet used for receive or transmit operation.\r
-\r
-  This support routine is called by the network specific Close\r
-  and TxComplete routines and during error cases in RxComplete\r
-  and TxBuffer.  Note that the network layers typically place\r
-  receive packets on the ESL_SOCKET::pRxFree list for reuse.\r
-\r
-  @param[in]  pPacket     Address of an ::ESL_PACKET structure\r
-  @param[in]  DebugFlags  Flags for debug messages\r
-\r
-  @retval EFI_SUCCESS - The packet was allocated successfully\r
-**/\r
-EFI_STATUS\r
-EslSocketPacketFree (\r
-  IN ESL_PACKET * pPacket,\r
-  IN UINTN DebugFlags\r
-  )\r
-{\r
-  UINTN LengthInBytes;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Free a packet structure\r
-  //\r
-  LengthInBytes = pPacket->PacketSize;\r
-  Status = gBS->FreePool ( pPacket );\r
-  if ( !EFI_ERROR ( Status )) {\r
-    DEBUG (( DebugFlags | DEBUG_POOL,\r
-              "0x%08x: Free pPacket, %d bytes\r\n",\r
-              pPacket,\r
-              LengthInBytes ));\r
-  }\r
-  else {\r
-    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INFO,\r
-              "ERROR - Failed to free packet 0x%08x, Status: %r\r\n",\r
-              pPacket,\r
-              Status ));\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Poll a socket for pending activity.\r
-\r
-  This routine builds a detected event mask which is returned to\r
-  the caller in the buffer provided.\r
-\r
-  The ::poll routine calls this routine to determine if the socket\r
-  needs to be serviced as a result of connection, error, receive or\r
-  transmit activity.\r
-\r
-  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[in]  Events          Events of interest for this socket\r
-  @param[in]  pEvents         Address to receive the detected events\r
-  @param[out] pErrno          Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS - Socket successfully polled\r
-  @retval EFI_INVALID_PARAMETER - When pEvents is NULL\r
-**/\r
-EFI_STATUS\r
-EslSocketPoll (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN short Events,\r
-  IN short * pEvents,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  short DetectedEvents;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-  short ValidEvents;\r
-  int   _errno = EINVAL;\r
-\r
-  DEBUG (( DEBUG_POLL, "Entering SocketPoll\r\n" ));\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-  DetectedEvents = 0;\r
-  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-  pSocket->errno = 0;\r
-\r
-  //\r
-  //  Verify the socket state\r
-  //\r
-  Status = EslSocketIsConfigured ( pSocket );\r
-  if ( !EFI_ERROR ( Status )) {\r
-    //\r
-    //  Check for invalid events\r
-    //\r
-    ValidEvents = POLLIN\r
-                | POLLPRI\r
-                | POLLOUT | POLLWRNORM\r
-                | POLLERR\r
-                | POLLHUP\r
-                | POLLNVAL\r
-                | POLLRDNORM\r
-                | POLLRDBAND\r
-                | POLLWRBAND ;\r
-    if ( 0 != ( Events & ( ~ValidEvents ))) {\r
-      DetectedEvents |= POLLNVAL;\r
-      DEBUG (( DEBUG_INFO | DEBUG_POLL,\r
-                "ERROR - Invalid event mask, Valid Events: 0x%04x, Invalid Events: 0x%04x\r\n",\r
-                Events & ValidEvents,\r
-                Events & ( ~ValidEvents )));\r
-    }\r
-    else {\r
-      //\r
-      //  Synchronize with the socket layer\r
-      //\r
-      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-      //\r
-      //  Increase the network performance by extending the\r
-      //  polling (idle) loop down into the LAN driver\r
-      //\r
-      EslSocketRxPoll ( pSocket );\r
-\r
-      //\r
-      //  Release the socket layer synchronization\r
-      //\r
-      RESTORE_TPL ( TplPrevious );\r
-\r
-      //\r
-      //  Check for pending connections\r
-      //\r
-      if ( 0 != pSocket->FifoDepth ) {\r
-        //\r
-        //  A connection is waiting for an accept call\r
-        //  See posix connect documentation at\r
-        //  http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.htm\r
-        //\r
-        DetectedEvents |= POLLIN | POLLRDNORM;\r
-      }\r
-      if ( pSocket->bConnected ) {\r
-        //\r
-        //  A connection is present\r
-        //  See posix connect documentation at\r
-        //  http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.htm\r
-        //\r
-        DetectedEvents |= POLLOUT | POLLWRNORM;\r
-      }\r
-\r
-      //\r
-      //  The following bits are set based upon the POSIX poll documentation at\r
-      //  http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html\r
-      //\r
-\r
-      //\r
-      //  Check for urgent receive data\r
-      //\r
-      if ( 0 < pSocket->RxOobBytes ) {\r
-        DetectedEvents |= POLLRDBAND | POLLPRI | POLLIN;\r
-      }\r
-\r
-      //\r
-      //  Check for normal receive data\r
-      //\r
-      if (( 0 < pSocket->RxBytes )\r
-        || ( EFI_SUCCESS != pSocket->RxError )) {\r
-        DetectedEvents |= POLLRDNORM | POLLIN;\r
-      }\r
-\r
-      //\r
-      //  Handle the receive errors\r
-      //\r
-      if (( EFI_SUCCESS != pSocket->RxError )\r
-        && ( 0 == ( DetectedEvents & POLLIN ))) {\r
-        DetectedEvents |= POLLERR | POLLIN | POLLRDNORM | POLLRDBAND;\r
-      }\r
-\r
-      //\r
-      //  Check for urgent transmit data buffer space\r
-      //\r
-      if (( MAX_TX_DATA > pSocket->TxOobBytes )\r
-        || ( EFI_SUCCESS != pSocket->TxError )) {\r
-        DetectedEvents |= POLLWRBAND;\r
-      }\r
-\r
-      //\r
-      //  Check for normal transmit data buffer space\r
-      //\r
-      if (( MAX_TX_DATA > pSocket->TxBytes )\r
-        || ( EFI_SUCCESS != pSocket->TxError )) {\r
-        DetectedEvents |= POLLWRNORM;\r
-      }\r
-\r
-      //\r
-      //  Handle the transmit error\r
-      //\r
-      if ( EFI_ERROR ( pSocket->TxError )) {\r
-        DetectedEvents |= POLLERR;\r
-      }\r
-      _errno = pSocket->errno;\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the detected events\r
-  //\r
-  *pEvents = DetectedEvents & ( Events\r
-                              | POLLERR\r
-                              | POLLHUP\r
-                              | POLLNVAL );\r
-  if ( NULL != pErrno ) {\r
-    *pErrno = _errno;\r
-  }\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DEBUG (( DEBUG_POLL, "Exiting SocketPoll, Status: %r\r\n", Status ));\r
-  return Status;\r
-}\r
-\r
-\r
-/** Allocate and initialize a ESL_PORT structure.\r
-\r
-  This routine initializes an ::ESL_PORT structure for use by\r
-  the socket.  This routine calls a routine via\r
-  ESL_PROTOCOL_API::pfnPortAllocate to initialize the network\r
-  specific resources.  The resources are released later by the\r
-  \ref PortCloseStateMachine.\r
-\r
-  This support routine is called by:\r
-  <ul>\r
-    <li>::EslSocketBind</li>\r
-    <li>::EslTcp4ListenComplete</li>\r
-  </ul>\r
-  to connect the socket with the underlying network adapter\r
-  to the socket.\r
-\r
-  @param[in]  pSocket     Address of an ::ESL_SOCKET structure.\r
-  @param[in]  pService    Address of an ::ESL_SERVICE structure.\r
-  @param[in]  ChildHandle Network protocol child handle\r
-  @param[in]  pSockAddr   Address of a sockaddr structure that contains the\r
-                          connection point on the local machine.  An IPv4 address\r
-                          of INADDR_ANY specifies that the connection is made to\r
-                          all of the network stacks on the platform.  Specifying a\r
-                          specific IPv4 address restricts the connection to the\r
-                          network stack supporting that address.  Specifying zero\r
-                          for the port causes the network layer to assign a port\r
-                          number from the dynamic range.  Specifying a specific\r
-                          port number causes the network layer to use that port.\r
-  @param[in]  bBindTest   TRUE if EslSocketBindTest should be called\r
-  @param[in]  DebugFlags  Flags for debug messages\r
-  @param[out] ppPort      Buffer to receive new ::ESL_PORT structure address\r
-\r
-  @retval EFI_SUCCESS - Socket successfully created\r
-**/\r
-EFI_STATUS\r
-EslSocketPortAllocate (\r
-  IN ESL_SOCKET * pSocket,\r
-  IN ESL_SERVICE * pService,\r
-  IN EFI_HANDLE ChildHandle,\r
-  IN CONST struct sockaddr * pSockAddr,\r
-  IN BOOLEAN bBindTest,\r
-  IN UINTN DebugFlags,\r
-  OUT ESL_PORT ** ppPort\r
-  )\r
-{\r
-  UINTN LengthInBytes;\r
-  UINT8 * pBuffer;\r
-  ESL_IO_MGMT * pIo;\r
-  ESL_LAYER * pLayer;\r
-  ESL_PORT * pPort;\r
-  EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;\r
-  CONST ESL_SOCKET_BINDING * pSocketBinding;\r
-  EFI_STATUS Status;\r
-  EFI_STATUS TempStatus;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  Use for/break instead of goto\r
-  pSocketBinding = pService->pSocketBinding;\r
-  for ( ; ; ) {\r
-    //\r
-    //  Allocate a port structure\r
-    //\r
-    pLayer = &mEslLayer;\r
-    LengthInBytes = sizeof ( *pPort )\r
-                  + ESL_STRUCTURE_ALIGNMENT_BYTES\r
-                  + (( pSocketBinding->RxIo\r
-                       + pSocketBinding->TxIoNormal\r
-                       + pSocketBinding->TxIoUrgent )\r
-                     * sizeof ( ESL_IO_MGMT ));\r
-    pPort = (ESL_PORT *) AllocateZeroPool ( LengthInBytes );\r
-    if ( NULL == pPort ) {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      pSocket->errno = ENOMEM;\r
-      break;\r
-    }\r
-    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
-              "0x%08x: Allocate pPort, %d bytes\r\n",\r
-              pPort,\r
-              LengthInBytes ));\r
-\r
-    //\r
-    //  Initialize the port\r
-    //\r
-    pPort->DebugFlags = DebugFlags;\r
-    pPort->Handle = ChildHandle;\r
-    pPort->pService = pService;\r
-    pPort->pServiceBinding = pService->pServiceBinding;\r
-    pPort->pSocket = pSocket;\r
-    pPort->pSocketBinding = pService->pSocketBinding;\r
-    pPort->Signature = PORT_SIGNATURE;\r
-\r
-    //\r
-    //  Open the port protocol\r
-    //\r
-    Status = gBS->OpenProtocol ( pPort->Handle,\r
-                                 pSocketBinding->pNetworkProtocolGuid,\r
-                                 &pPort->pProtocol.v,\r
-                                 pLayer->ImageHandle,\r
-                                 NULL,\r
-                                 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to open network protocol GUID on controller 0x%08x\r\n",\r
-                pPort->Handle ));\r
-      pSocket->errno = EEXIST;\r
-      break;\r
-    }\r
-    DEBUG (( DebugFlags,\r
-              "0x%08x: Network protocol GUID opened on controller 0x%08x\r\n",\r
-              pPort->pProtocol.v,\r
-              pPort->Handle ));\r
-\r
-    //\r
-    //  Initialize the port specific resources\r
-    //\r
-    Status = pSocket->pApi->pfnPortAllocate ( pPort,\r
-                                              DebugFlags );\r
-    if ( EFI_ERROR ( Status )) {\r
-      break;\r
-    }\r
-\r
-    //\r
-    //  Set the local address\r
-    //\r
-    Status = pSocket->pApi->pfnLocalAddrSet ( pPort, pSockAddr, bBindTest );\r
-    if ( EFI_ERROR ( Status )) {\r
-      break;\r
-    }\r
-\r
-    //\r
-    //  Test the address/port configuration\r
-    //\r
-    if ( bBindTest ) {\r
-      Status = EslSocketBindTest ( pPort, pSocket->pApi->BindTestErrno );\r
-      if ( EFI_ERROR ( Status )) {\r
-        break;\r
-      }\r
-    }\r
-\r
-    //\r
-    //  Initialize the receive structures\r
-    //\r
-    pBuffer = (UINT8 *)&pPort[ 1 ];\r
-    pBuffer = &pBuffer[ ESL_STRUCTURE_ALIGNMENT_BYTES ];\r
-    pBuffer = (UINT8 *)( ESL_STRUCTURE_ALIGNMENT_MASK & (UINTN)pBuffer );\r
-    pIo = (ESL_IO_MGMT *)pBuffer;\r
-    if (( 0 != pSocketBinding->RxIo )\r
-      && ( NULL != pSocket->pApi->pfnRxComplete )) {\r
-      Status = EslSocketIoInit ( pPort,\r
-                                 &pIo,\r
-                                 pSocketBinding->RxIo,\r
-                                 &pPort->pRxFree,\r
-                                 DebugFlags | DEBUG_POOL,\r
-                                 "receive",\r
-                                 pSocket->pApi->pfnRxComplete );\r
-      if ( EFI_ERROR ( Status )) {\r
-        break;\r
-      }\r
-    }\r
-\r
-    //\r
-    //  Initialize the urgent transmit structures\r
-    //\r
-    if (( 0 != pSocketBinding->TxIoUrgent )\r
-      && ( NULL != pSocket->pApi->pfnTxOobComplete )) {\r
-      Status = EslSocketIoInit ( pPort,\r
-                                 &pIo,\r
-                                 pSocketBinding->TxIoUrgent,\r
-                                 &pPort->pTxOobFree,\r
-                                 DebugFlags | DEBUG_POOL,\r
-                                 "urgent transmit",\r
-                                 pSocket->pApi->pfnTxOobComplete );\r
-      if ( EFI_ERROR ( Status )) {\r
-        break;\r
-      }\r
-    }\r
-\r
-    //\r
-    //  Initialize the normal transmit structures\r
-    //\r
-    if (( 0 != pSocketBinding->TxIoNormal )\r
-      && ( NULL != pSocket->pApi->pfnTxComplete )) {\r
-      Status = EslSocketIoInit ( pPort,\r
-                                 &pIo,\r
-                                 pSocketBinding->TxIoNormal,\r
-                                 &pPort->pTxFree,\r
-                                 DebugFlags | DEBUG_POOL,\r
-                                 "normal transmit",\r
-                                 pSocket->pApi->pfnTxComplete );\r
-      if ( EFI_ERROR ( Status )) {\r
-        break;\r
-      }\r
-    }\r
-\r
-    //\r
-    //  Add this port to the socket\r
-    //\r
-    pPort->pLinkSocket = pSocket->pPortList;\r
-    pSocket->pPortList = pPort;\r
-    DEBUG (( DebugFlags,\r
-              "0x%08x: Socket adding port: 0x%08x\r\n",\r
-              pSocket,\r
-              pPort ));\r
-\r
-    //\r
-    //  Add this port to the service\r
-    //\r
-    pPort->pLinkService = pService->pPortList;\r
-    pService->pPortList = pPort;\r
-\r
-    //\r
-    //  Return the port\r
-    //\r
-    *ppPort = pPort;\r
-    break;\r
-  }\r
-\r
-  //\r
-  //  Clean up after the error if necessary\r
-  //\r
-  if ( EFI_ERROR ( Status )) {\r
-    if ( NULL != pPort ) {\r
-      //\r
-      //  Close the port\r
-      //\r
-      EslSocketPortClose ( pPort );\r
-    }\r
-    else {\r
-      //\r
-      //  Close the port if necessary\r
-      //\r
-      pServiceBinding = pService->pServiceBinding;\r
-      TempStatus = pServiceBinding->DestroyChild ( pServiceBinding,\r
-                                                   ChildHandle );\r
-      if ( !EFI_ERROR ( TempStatus )) {\r
-        DEBUG (( DEBUG_BIND | DEBUG_POOL,\r
-                  "0x%08x: %s port handle destroyed\r\n",\r
-                  ChildHandle,\r
-                  pSocketBinding->pName ));\r
-      }\r
-      else {\r
-        DEBUG (( DEBUG_ERROR | DEBUG_BIND | DEBUG_POOL,\r
-                  "ERROR - Failed to destroy the %s port handle 0x%08x, Status: %r\r\n",\r
-                  pSocketBinding->pName,\r
-                  ChildHandle,\r
-                  TempStatus ));\r
-        ASSERT ( EFI_SUCCESS == TempStatus );\r
-      }\r
-    }\r
-  }\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Close a port.\r
-\r
-  This routine releases the resources allocated by ::EslSocketPortAllocate.\r
-  This routine calls ESL_PROTOCOL_API::pfnPortClose to release the network\r
-  specific resources.\r
-\r
-  This routine is called by:\r
-  <ul>\r
-    <li>::EslSocketPortAllocate - Port initialization failure</li>\r
-    <li>::EslSocketPortCloseRxDone - Last step of close processing</li>\r
-    <li>::EslTcp4ConnectComplete - Connection failure and reducing the port list to a single port</li>\r
-  </ul>\r
-  See the \ref PortCloseStateMachine section.\r
-\r
-  @param[in]  pPort       Address of an ::ESL_PORT structure.\r
-\r
-  @retval EFI_SUCCESS     The port is closed\r
-  @retval other           Port close error\r
-**/\r
-EFI_STATUS\r
-EslSocketPortClose (\r
-  IN ESL_PORT * pPort\r
-  )\r
-{\r
-  UINTN DebugFlags;\r
-  ESL_LAYER * pLayer;\r
-  ESL_PACKET * pPacket;\r
-  ESL_PORT * pPreviousPort;\r
-  ESL_SERVICE * pService;\r
-  EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;\r
-  CONST ESL_SOCKET_BINDING * pSocketBinding;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  Locate the port in the socket list\r
-  //\r
-  Status = EFI_SUCCESS;\r
-  pLayer = &mEslLayer;\r
-  DebugFlags = pPort->DebugFlags;\r
-  pSocket = pPort->pSocket;\r
-  pPreviousPort = pSocket->pPortList;\r
-  if ( pPreviousPort == pPort ) {\r
-    //\r
-    //  Remove this port from the head of the socket list\r
-    //\r
-    pSocket->pPortList = pPort->pLinkSocket;\r
-  }\r
-  else {\r
-    //\r
-    //  Locate the port in the middle of the socket list\r
-    //\r
-    while (( NULL != pPreviousPort )\r
-      && ( pPreviousPort->pLinkSocket != pPort )) {\r
-      pPreviousPort = pPreviousPort->pLinkSocket;\r
-    }\r
-    if ( NULL != pPreviousPort ) {\r
-      //\r
-      //  Remove the port from the middle of the socket list\r
-      //\r
-      pPreviousPort->pLinkSocket = pPort->pLinkSocket;\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Locate the port in the service list\r
-  //  Note that the port may not be in the service list\r
-  //  if the service has been shutdown.\r
-  //\r
-  pService = pPort->pService;\r
-  if ( NULL != pService ) {\r
-    pPreviousPort = pService->pPortList;\r
-    if ( pPreviousPort == pPort ) {\r
-      //\r
-      //  Remove this port from the head of the service list\r
-      //\r
-      pService->pPortList = pPort->pLinkService;\r
-    }\r
-    else {\r
-      //\r
-      //  Locate the port in the middle of the service list\r
-      //\r
-      while (( NULL != pPreviousPort )\r
-        && ( pPreviousPort->pLinkService != pPort )) {\r
-        pPreviousPort = pPreviousPort->pLinkService;\r
-      }\r
-      if ( NULL != pPreviousPort ) {\r
-        //\r
-        //  Remove the port from the middle of the service list\r
-        //\r
-        pPreviousPort->pLinkService = pPort->pLinkService;\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Empty the urgent receive queue\r
-  //\r
-  while ( NULL != pSocket->pRxOobPacketListHead ) {\r
-    pPacket = pSocket->pRxOobPacketListHead;\r
-    pSocket->pRxOobPacketListHead = pPacket->pNext;\r
-    pSocket->pApi->pfnPacketFree ( pPacket, &pSocket->RxOobBytes );\r
-    EslSocketPacketFree ( pPacket, DEBUG_RX );\r
-  }\r
-  pSocket->pRxOobPacketListTail = NULL;\r
-  ASSERT ( 0 == pSocket->RxOobBytes );\r
-\r
-  //\r
-  //  Empty the receive queue\r
-  //\r
-  while ( NULL != pSocket->pRxPacketListHead ) {\r
-    pPacket = pSocket->pRxPacketListHead;\r
-    pSocket->pRxPacketListHead = pPacket->pNext;\r
-    pSocket->pApi->pfnPacketFree ( pPacket, &pSocket->RxBytes );\r
-    EslSocketPacketFree ( pPacket, DEBUG_RX );\r
-  }\r
-  pSocket->pRxPacketListTail = NULL;\r
-  ASSERT ( 0 == pSocket->RxBytes );\r
-\r
-  //\r
-  //  Empty the receive free queue\r
-  //\r
-  while ( NULL != pSocket->pRxFree ) {\r
-    pPacket = pSocket->pRxFree;\r
-    pSocket->pRxFree = pPacket->pNext;\r
-    EslSocketPacketFree ( pPacket, DEBUG_RX );\r
-  }\r
-\r
-  //\r
-  //  Release the network specific resources\r
-  //\r
-  if ( NULL != pSocket->pApi->pfnPortClose ) {\r
-    Status = pSocket->pApi->pfnPortClose ( pPort );\r
-  }\r
-\r
-  //\r
-  //  Done with the normal transmit events\r
-  //\r
-  Status = EslSocketIoFree ( pPort,\r
-                             &pPort->pTxFree,\r
-                             DebugFlags | DEBUG_POOL,\r
-                             "normal transmit" );\r
-\r
-  //\r
-  //  Done with the urgent transmit events\r
-  //\r
-  Status = EslSocketIoFree ( pPort,\r
-                             &pPort->pTxOobFree,\r
-                             DebugFlags | DEBUG_POOL,\r
-                             "urgent transmit" );\r
-\r
-  //\r
-  //  Done with the receive events\r
-  //\r
-  Status = EslSocketIoFree ( pPort,\r
-                             &pPort->pRxFree,\r
-                             DebugFlags | DEBUG_POOL,\r
-                             "receive" );\r
-\r
-  //\r
-  //  Done with the lower layer network protocol\r
-  //\r
-  pSocketBinding = pPort->pSocketBinding;\r
-  if ( NULL != pPort->pProtocol.v ) {\r
-    Status = gBS->CloseProtocol ( pPort->Handle,\r
-                                  pSocketBinding->pNetworkProtocolGuid,\r
-                                  pLayer->ImageHandle,\r
-                                  NULL );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DebugFlags,\r
-                "0x%08x: Network protocol GUID closed on controller 0x%08x\r\n",\r
-                pPort->pProtocol.v,\r
-                pPort->Handle ));\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to close network protocol GUID on controller 0x%08x, Status: %r\r\n",\r
-                pPort->Handle,\r
-                Status ));\r
-      ASSERT ( EFI_SUCCESS == Status );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Done with the network port\r
-  //\r
-  pServiceBinding = pPort->pServiceBinding;\r
-  if ( NULL != pPort->Handle ) {\r
-    Status = pServiceBinding->DestroyChild ( pServiceBinding,\r
-                                             pPort->Handle );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DebugFlags | DEBUG_POOL,\r
-                "0x%08x: %s port handle destroyed\r\n",\r
-                pPort->Handle,\r
-                pSocketBinding->pName ));\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,\r
-                "ERROR - Failed to destroy the %s port handle, Status: %r\r\n",\r
-                pSocketBinding->pName,\r
-                Status ));\r
-      ASSERT ( EFI_SUCCESS == Status );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Release the port structure\r
-  //\r
-  Status = gBS->FreePool ( pPort );\r
-  if ( !EFI_ERROR ( Status )) {\r
-    DEBUG (( DebugFlags | DEBUG_POOL,\r
-              "0x%08x: Free pPort, %d bytes\r\n",\r
-              pPort,\r
-              sizeof ( *pPort )));\r
-  }\r
-  else {\r
-    DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,\r
-              "ERROR - Failed to free pPort: 0x%08x, Status: %r\r\n",\r
-              pPort,\r
-              Status ));\r
-    ASSERT ( EFI_SUCCESS == Status );\r
-  }\r
-\r
-  //\r
-  //  Mark the socket as closed if necessary\r
-  //\r
-  if ( NULL == pSocket->pPortList ) {\r
-    pSocket->State = SOCKET_STATE_CLOSED;\r
-    DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-              "0x%08x: Socket State: SOCKET_STATE_CLOSED\r\n",\r
-              pSocket ));\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Port close state 3.\r
-\r
-  This routine attempts to complete the port close operation.\r
-\r
-  This routine is called by the TCP layer upon completion of\r
-  the close operation and by ::EslSocketPortCloseTxDone.\r
-  See the \ref PortCloseStateMachine section.\r
-\r
-  @param[in]  Event     The close completion event\r
-  @param[in]  pPort     Address of an ::ESL_PORT structure.\r
-**/\r
-VOID\r
-EslSocketPortCloseComplete (\r
-  IN EFI_EVENT Event,\r
-  IN ESL_PORT * pPort\r
-  )\r
-{\r
-  ESL_IO_MGMT * pIo;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-  VERIFY_AT_TPL ( TPL_SOCKETS );\r
-\r
-  //  Update the port state\r
-  pPort->State = PORT_STATE_CLOSE_DONE;\r
-  DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-            "0x%08x: Port Close State: PORT_STATE_CLOSE_DONE\r\n",\r
-            pPort ));\r
-\r
-  //  Shutdown the receive operation on the port\r
-  if ( NULL != pPort->pfnRxCancel ) {\r
-    pIo = pPort->pRxActive;\r
-    while ( NULL != pIo ) {\r
-      EslSocketRxCancel ( pPort, pIo );\r
-      pIo = pIo->pNext;\r
-    }\r
-  }\r
-\r
-  //  Determine if the receive operation is pending\r
-  Status = EslSocketPortCloseRxDone ( pPort );\r
-  DBG_EXIT_STATUS ( Status );\r
-  --Status;\r
-}\r
-\r
-\r
-/** Port close state 4.\r
-\r
-  This routine determines the state of the receive operations and\r
-  continues the close operation after the pending receive operations\r
-  are cancelled.\r
-\r
-  This routine is called by\r
-  <ul>\r
-    <li>::EslSocketPortCloseComplete</li>\r
-    <li>::EslSocketPortCloseTxDone</li>\r
-    <li>::EslSocketRxComplete</li>\r
-  </ul>\r
-  to determine the state of the receive operations.\r
-  See the \ref PortCloseStateMachine section.\r
-\r
-  @param[in]  pPort       Address of an ::ESL_PORT structure.\r
-\r
-  @retval EFI_SUCCESS         The port is closed\r
-  @retval EFI_NOT_READY       The port is still closing\r
-  @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,\r
-                              most likely the routine was called already.\r
-**/\r
-EFI_STATUS\r
-EslSocketPortCloseRxDone (\r
-  IN ESL_PORT * pPort\r
-  )\r
-{\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  Verify that the port is closing\r
-  //\r
-  Status = EFI_ALREADY_STARTED;\r
-  if ( PORT_STATE_CLOSE_DONE == pPort->State ) {\r
-    //\r
-    //  Determine if the receive operation is pending\r
-    //\r
-    Status = EFI_NOT_READY;\r
-    if ( NULL == pPort->pRxActive ) {\r
-      //\r
-      //  The receive operation is complete\r
-      //  Update the port state\r
-      //\r
-      pPort->State = PORT_STATE_CLOSE_RX_DONE;\r
-      DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                "0x%08x: Port Close State: PORT_STATE_CLOSE_RX_DONE\r\n",\r
-                pPort ));\r
-\r
-      //\r
-      //  Complete the port close operation\r
-      //\r
-      Status = EslSocketPortClose ( pPort );\r
-    }\r
-    else {\r
-      DEBUG_CODE_BEGIN ();\r
-      {\r
-        ESL_IO_MGMT * pIo;\r
-        //\r
-        //  Display the outstanding receive operations\r
-        //\r
-        DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                  "0x%08x: Port Close: Receive still pending!\r\n",\r
-                  pPort ));\r
-        pIo = pPort->pRxActive;\r
-        while ( NULL != pIo ) {\r
-          DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                    "0x%08x: Packet pending on network adapter\r\n",\r
-                    pIo->pPacket ));\r
-          pIo = pIo->pNext;\r
-        }\r
-      }\r
-      DEBUG_CODE_END ( );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Start the close operation on a port, state 1.\r
-\r
-  This routine marks the port as closed and initiates the \ref\r
-  PortCloseStateMachine. The first step is to allow the \ref\r
-  TransmitEngine to run down.\r
-\r
-  This routine is called by ::EslSocketCloseStart to initiate the socket\r
-  network specific close operation on the socket.\r
-\r
-  @param[in]  pPort       Address of an ::ESL_PORT structure.\r
-  @param[in]  bCloseNow   Set TRUE to abort active transfers\r
-  @param[in]  DebugFlags  Flags for debug messages\r
-\r
-  @retval EFI_SUCCESS         The port is closed, not normally returned\r
-  @retval EFI_NOT_READY       The port has started the closing process\r
-  @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,\r
-                              most likely the routine was called already.\r
-**/\r
-EFI_STATUS\r
-EslSocketPortCloseStart (\r
-  IN ESL_PORT * pPort,\r
-  IN BOOLEAN bCloseNow,\r
-  IN UINTN DebugFlags\r
-  )\r
-{\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  Mark the port as closing\r
-  //\r
-  Status = EFI_ALREADY_STARTED;\r
-  pSocket = pPort->pSocket;\r
-  pSocket->errno = EALREADY;\r
-  if ( PORT_STATE_CLOSE_STARTED > pPort->State ) {\r
-\r
-    //\r
-    //  Update the port state\r
-    //\r
-    pPort->State = PORT_STATE_CLOSE_STARTED;\r
-    DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-              "0x%08x: Port Close State: PORT_STATE_CLOSE_STARTED\r\n",\r
-              pPort ));\r
-    pPort->bCloseNow = bCloseNow;\r
-    pPort->DebugFlags = DebugFlags;\r
-\r
-    //\r
-    //  Determine if transmits are complete\r
-    //\r
-    Status = EslSocketPortCloseTxDone ( pPort );\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Port close state 2.\r
-\r
-  This routine determines the state of the transmit engine and\r
-  continue the close operation after the transmission is complete.\r
-  The next step is to stop the \ref ReceiveEngine.\r
-  See the \ref PortCloseStateMachine section.\r
-\r
-  This routine is called by ::EslSocketPortCloseStart to determine\r
-  if the transmission is complete.\r
-\r
-  @param[in]  pPort           Address of an ::ESL_PORT structure.\r
-\r
-  @retval EFI_SUCCESS         The port is closed, not normally returned\r
-  @retval EFI_NOT_READY       The port is still closing\r
-  @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,\r
-                              most likely the routine was called already.\r
-\r
-**/\r
-EFI_STATUS\r
-EslSocketPortCloseTxDone (\r
-  IN ESL_PORT * pPort\r
-  )\r
-{\r
-  ESL_IO_MGMT * pIo;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  All transmissions are complete or must be stopped\r
-  //  Mark the port as TX complete\r
-  //\r
-  Status = EFI_ALREADY_STARTED;\r
-  if ( PORT_STATE_CLOSE_STARTED == pPort->State ) {\r
-    //\r
-    //  Verify that the transmissions are complete\r
-    //\r
-    pSocket = pPort->pSocket;\r
-    if ( pPort->bCloseNow\r
-         || ( EFI_SUCCESS != pSocket->TxError )\r
-         || (( NULL == pPort->pTxActive )\r
-                && ( NULL == pPort->pTxOobActive ))) {\r
-      //\r
-      //  Update the port state\r
-      //\r
-      pPort->State = PORT_STATE_CLOSE_TX_DONE;\r
-      DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                "0x%08x: Port Close State: PORT_STATE_CLOSE_TX_DONE\r\n",\r
-                pPort ));\r
-\r
-      //\r
-      //  Close the port\r
-      //  Skip the close operation if the port is not configured\r
-      //\r
-      Status = EFI_SUCCESS;\r
-      pSocket = pPort->pSocket;\r
-      if (( pPort->bConfigured )\r
-        && ( NULL != pSocket->pApi->pfnPortCloseOp )) {\r
-          //\r
-          //  Start the close operation\r
-          //\r
-          Status = pSocket->pApi->pfnPortCloseOp ( pPort );\r
-          DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                    "0x%08x: Port Close: Close operation still pending!\r\n",\r
-                    pPort ));\r
-          ASSERT ( EFI_SUCCESS == Status );\r
-      }\r
-      else {\r
-        //\r
-        //  The receive operation is complete\r
-        //  Update the port state\r
-        //\r
-        EslSocketPortCloseComplete ( NULL, pPort );\r
-      }\r
-    }\r
-    else {\r
-      //\r
-      //  Transmissions are still active, exit\r
-      //\r
-      Status = EFI_NOT_READY;\r
-      pSocket->errno = EAGAIN;\r
-      DEBUG_CODE_BEGIN ( );\r
-      {\r
-        ESL_PACKET * pPacket;\r
-\r
-        DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                  "0x%08x: Port Close: Transmits are still pending!\r\n",\r
-                  pPort ));\r
-\r
-        //\r
-        //  Display the pending urgent transmit packets\r
-        //\r
-        pPacket = pSocket->pTxOobPacketListHead;\r
-        while ( NULL != pPacket ) {\r
-          DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                    "0x%08x: Packet pending on urgent TX list, %d bytes\r\n",\r
-                    pPacket,\r
-                    pPacket->PacketSize ));\r
-          pPacket = pPacket->pNext;\r
-        }\r
-\r
-        pIo = pPort->pTxOobActive;\r
-        while ( NULL != pIo ) {\r
-          pPacket = pIo->pPacket;\r
-          DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                    "0x%08x: Packet active %d bytes, pIo: 0x%08x\r\n",\r
-                    pPacket,\r
-                    pPacket->PacketSize,\r
-                    pIo ));\r
-          pIo = pIo->pNext;\r
-        }\r
-\r
-        //\r
-        //  Display the pending normal transmit packets\r
-        //\r
-        pPacket = pSocket->pTxPacketListHead;\r
-        while ( NULL != pPacket ) {\r
-          DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                    "0x%08x: Packet pending on normal TX list, %d bytes\r\n",\r
-                    pPacket,\r
-                    pPacket->PacketSize ));\r
-          pPacket = pPacket->pNext;\r
-        }\r
-\r
-        pIo = pPort->pTxActive;\r
-        while ( NULL != pIo ) {\r
-          pPacket = pIo->pPacket;\r
-          DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                    "0x%08x: Packet active %d bytes, pIo: 0x%08x\r\n",\r
-                    pPacket,\r
-                    pPacket->PacketSize,\r
-                    pIo ));\r
-          pIo = pIo->pNext;\r
-        }\r
-      }\r
-      DEBUG_CODE_END ();\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Receive data from a network connection.\r
-\r
-  This routine calls the network specific routine to remove the\r
-  next portion of data from the receive queue and return it to the\r
-  caller.\r
-\r
-  The ::recvfrom routine calls this routine to determine if any data\r
-  is received from the remote system.  Note that the other routines\r
-  ::recv and ::read are layered on top of ::recvfrom.\r
-\r
-  @param[in]      pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[in]      Flags           Message control flags\r
-  @param[in]      BufferLength    Length of the the buffer\r
-  @param[in]      pBuffer         Address of a buffer to receive the data.\r
-  @param[in]      pDataLength     Number of received data bytes in the buffer.\r
-  @param[out]     pAddress        Network address to receive the remote system address\r
-  @param[in,out]  pAddressLength  Length of the remote network address structure\r
-  @param[out]     pErrno          Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS - Socket data successfully received\r
-**/\r
-EFI_STATUS\r
-EslSocketReceive (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN INT32 Flags,\r
-  IN size_t BufferLength,\r
-  IN UINT8 * pBuffer,\r
-  OUT size_t * pDataLength,\r
-  OUT struct sockaddr * pAddress,\r
-  IN OUT socklen_t * pAddressLength,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  union {\r
-    struct sockaddr_in v4;\r
-    struct sockaddr_in6 v6;\r
-  } Addr;\r
-  socklen_t AddressLength;\r
-  BOOLEAN bConsumePacket;\r
-  BOOLEAN bUrgentQueue;\r
-  size_t DataLength;\r
-  ESL_PACKET * pNextPacket;\r
-  ESL_PACKET * pPacket;\r
-  ESL_PORT * pPort;\r
-  ESL_PACKET ** ppQueueHead;\r
-  ESL_PACKET ** ppQueueTail;\r
-  struct sockaddr * pRemoteAddress;\r
-  size_t * pRxDataBytes;\r
-  ESL_SOCKET * pSocket;\r
-  size_t SkipBytes;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Validate the socket\r
-  //\r
-  pSocket = NULL;\r
-  if ( NULL != pSocketProtocol ) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
-    //\r
-    //  Validate the return address parameters\r
-    //\r
-    if (( NULL == pAddress ) || ( NULL != pAddressLength )) {\r
-      //\r
-      //  Return the transmit error if necessary\r
-      //\r
-      if ( EFI_SUCCESS != pSocket->TxError ) {\r
-        pSocket->errno = EIO;\r
-        Status = pSocket->TxError;\r
-        pSocket->TxError = EFI_SUCCESS;\r
-      }\r
-      else {\r
-        //\r
-        //  Verify the socket state\r
-        //\r
-        Status = EslSocketIsConfigured ( pSocket );\r
-        if ( !EFI_ERROR ( Status )) {\r
-          //\r
-          //  Validate the buffer length\r
-          //\r
-          if (( NULL == pDataLength )\r
-            || ( NULL == pBuffer )) {\r
-            if ( NULL == pDataLength ) {\r
-              DEBUG (( DEBUG_RX,\r
-                        "ERROR - pDataLength is NULL!\r\n" ));\r
-            }\r
-            else {\r
-              DEBUG (( DEBUG_RX,\r
-                        "ERROR - pBuffer is NULL!\r\n" ));\r
-            }\r
-            Status = EFI_INVALID_PARAMETER;\r
-            pSocket->errno = EFAULT;\r
-          }\r
-          else {\r
-            //\r
-            //  Verify the API\r
-            //\r
-            if ( NULL == pSocket->pApi->pfnReceive ) {\r
-              Status = EFI_UNSUPPORTED;\r
-              pSocket->errno = ENOTSUP;\r
-            }\r
-            else {\r
-              //\r
-              //  Zero the receive address if being returned\r
-              //\r
-              pRemoteAddress = NULL;\r
-              if ( NULL != pAddress ) {\r
-                pRemoteAddress = (struct sockaddr *)&Addr;\r
-                ZeroMem ( pRemoteAddress, sizeof ( Addr ));\r
-                pRemoteAddress->sa_family = pSocket->pApi->AddressFamily;\r
-                pRemoteAddress->sa_len = (UINT8)pSocket->pApi->AddressLength;\r
-              }\r
-\r
-              //\r
-              //  Synchronize with the socket layer\r
-              //\r
-              RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-              //\r
-              //  Assume failure\r
-              //\r
-              Status = EFI_UNSUPPORTED;\r
-              pSocket->errno = ENOTCONN;\r
-\r
-              //\r
-              //  Verify that the socket is connected\r
-              //\r
-              if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
-                //\r
-                //  Poll the network to increase performance\r
-                //\r
-                EslSocketRxPoll ( pSocket );\r
-\r
-                //\r
-                //  Locate the port\r
-                //\r
-                pPort = pSocket->pPortList;\r
-                if ( NULL != pPort ) {\r
-                  //\r
-                  //  Determine the queue head\r
-                  //\r
-                  bUrgentQueue = (BOOLEAN)( 0 != ( Flags & MSG_OOB ));\r
-                  if ( bUrgentQueue ) {\r
-                    ppQueueHead = &pSocket->pRxOobPacketListHead;\r
-                    ppQueueTail = &pSocket->pRxOobPacketListTail;\r
-                    pRxDataBytes = &pSocket->RxOobBytes;\r
-                  }\r
-                  else {\r
-                    ppQueueHead = &pSocket->pRxPacketListHead;\r
-                    ppQueueTail = &pSocket->pRxPacketListTail;\r
-                    pRxDataBytes = &pSocket->RxBytes;\r
-                  }\r
-\r
-                  //\r
-                  //  Determine if there is any data on the queue\r
-                  //\r
-                  *pDataLength = 0;\r
-                  pPacket = *ppQueueHead;\r
-                  if ( NULL != pPacket ) {\r
-                    //\r
-                    //  Copy the received data\r
-                    //\r
-                    do {\r
-                      //\r
-                      //  Attempt to receive a packet\r
-                      //\r
-                      SkipBytes = 0;\r
-                      bConsumePacket = (BOOLEAN)( 0 == ( Flags & MSG_PEEK ));\r
-                      pBuffer = pSocket->pApi->pfnReceive ( pPort,\r
-                                                            pPacket,\r
-                                                            &bConsumePacket,\r
-                                                            BufferLength,\r
-                                                            pBuffer,\r
-                                                            &DataLength,\r
-                                                            (struct sockaddr *)&Addr,\r
-                                                            &SkipBytes );\r
-                      *pDataLength += DataLength;\r
-                      BufferLength -= DataLength;\r
-\r
-                      //\r
-                      //  Determine if the data is being read\r
-                      //\r
-                      pNextPacket = pPacket->pNext;\r
-                      if ( bConsumePacket ) {\r
-                        //\r
-                        //  All done with this packet\r
-                        //  Account for any discarded data\r
-                        //\r
-                        pSocket->pApi->pfnPacketFree ( pPacket, pRxDataBytes );\r
-                        if ( 0 != SkipBytes ) {\r
-                          DEBUG (( DEBUG_RX,\r
-                                    "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n",\r
-                                    pPort,\r
-                                    SkipBytes ));\r
-                        }\r
-\r
-                        //\r
-                        //  Remove this packet from the queue\r
-                        //\r
-                        *ppQueueHead = pPacket->pNext;\r
-                        if ( NULL == *ppQueueHead ) {\r
-                          *ppQueueTail = NULL;\r
-                        }\r
-\r
-                        //\r
-                        //  Move the packet to the free queue\r
-                        //\r
-                        pPacket->pNext = pSocket->pRxFree;\r
-                        pSocket->pRxFree = pPacket;\r
-                        DEBUG (( DEBUG_RX,\r
-                                  "0x%08x: Port freeing packet 0x%08x\r\n",\r
-                                  pPort,\r
-                                  pPacket ));\r
-\r
-                        //\r
-                        //  Restart the receive operation if necessary\r
-                        //\r
-                        if (( NULL != pPort->pRxFree )\r
-                          && ( MAX_RX_DATA > pSocket->RxBytes )) {\r
-                            EslSocketRxStart ( pPort );\r
-                        }\r
-                      }\r
-\r
-                      //\r
-                      //  Get the next packet\r
-                      //\r
-                      pPacket = pNextPacket;\r
-                    } while (( SOCK_STREAM == pSocket->Type )\r
-                          && ( NULL != pPacket )\r
-                          && ( 0 < BufferLength ));\r
-\r
-                    //\r
-                    //  Successful operation\r
-                    //\r
-                    Status = EFI_SUCCESS;\r
-                    pSocket->errno = 0;\r
-                  }\r
-                  else {\r
-                    //\r
-                    //  The queue is empty\r
-                    //  Determine if it is time to return the receive error\r
-                    //\r
-                    if ( EFI_ERROR ( pSocket->RxError )\r
-                      && ( NULL == pSocket->pRxPacketListHead )\r
-                      && ( NULL == pSocket->pRxOobPacketListHead )) {\r
-                      Status = pSocket->RxError;\r
-                      pSocket->RxError = EFI_SUCCESS;\r
-                      switch ( Status ) {\r
-                      default:\r
-                        pSocket->errno = EIO;\r
-                        break;\r
-\r
-                      case EFI_CONNECTION_FIN:\r
-                        //\r
-                        //  Continue to return zero bytes received when the\r
-                        //  peer has successfully closed the connection\r
-                        //\r
-                        pSocket->RxError = EFI_CONNECTION_FIN;\r
-                        *pDataLength = 0;\r
-                        pSocket->errno = 0;\r
-                        Status = EFI_SUCCESS;\r
-                        break;\r
-\r
-                      case EFI_CONNECTION_REFUSED:\r
-                        pSocket->errno = ECONNREFUSED;\r
-                        break;\r
-\r
-                      case EFI_CONNECTION_RESET:\r
-                        pSocket->errno = ECONNRESET;\r
-                        break;\r
-\r
-                      case EFI_HOST_UNREACHABLE:\r
-                        pSocket->errno = EHOSTUNREACH;\r
-                        break;\r
-\r
-                      case EFI_NETWORK_UNREACHABLE:\r
-                        pSocket->errno = ENETUNREACH;\r
-                        break;\r
-\r
-                      case EFI_PORT_UNREACHABLE:\r
-                        pSocket->errno = EPROTONOSUPPORT;\r
-                        break;\r
-\r
-                      case EFI_PROTOCOL_UNREACHABLE:\r
-                        pSocket->errno = ENOPROTOOPT;\r
-                        break;\r
-                      }\r
-                    }\r
-                    else {\r
-                      Status = EFI_NOT_READY;\r
-                      pSocket->errno = EAGAIN;\r
-                    }\r
-                  }\r
-                }\r
-              }\r
-\r
-              //\r
-              //  Release the socket layer synchronization\r
-              //\r
-              RESTORE_TPL ( TplPrevious );\r
-\r
-              if (( !EFI_ERROR ( Status )) && ( NULL != pAddress )) {\r
-                //\r
-                //  Return the remote address if requested, truncate if necessary\r
-                //\r
-                AddressLength = pRemoteAddress->sa_len;\r
-                if ( AddressLength > *pAddressLength ) {\r
-                  AddressLength = *pAddressLength;\r
-                }\r
-                DEBUG (( DEBUG_RX,\r
-                          "Returning the remote address, 0x%016x bytes --> 0x%16x\r\n", *pAddressLength, pAddress ));\r
-                ZeroMem ( pAddress, *pAddressLength );\r
-                CopyMem ( pAddress, &Addr, AddressLength );\r
-\r
-                //\r
-                //  Update the address length\r
-                //\r
-                *pAddressLength = pRemoteAddress->sa_len;\r
-              }\r
-            }\r
-          }\r
-        }\r
-      }\r
-\r
-\r
-    }\r
-    else {\r
-      //\r
-      //  Bad return address pointer and length\r
-      //\r
-      Status = EFI_INVALID_PARAMETER;\r
-      pSocket->errno = EINVAL;\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    if ( NULL != pSocket ) {\r
-      *pErrno = pSocket->errno;\r
-    }\r
-    else {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = ENOTSOCK;\r
-    }\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Cancel the receive operations.\r
-\r
-  This routine cancels a pending receive operation.\r
-  See the \ref ReceiveEngine section.\r
-\r
-  This routine is called by ::EslSocketShutdown when the socket\r
-  layer is being shutdown.\r
-\r
-  @param[in]  pPort     Address of an ::ESL_PORT structure\r
-  @param[in]  pIo       Address of an ::ESL_IO_MGMT structure\r
-**/\r
-VOID\r
-EslSocketRxCancel (\r
-  IN ESL_PORT * pPort,\r
-  IN ESL_IO_MGMT * pIo\r
-  )\r
-{\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Cancel the outstanding receive\r
-  //\r
-  Status = pPort->pfnRxCancel ( pPort->pProtocol.v,\r
-                                &pIo->Token );\r
-  if ( !EFI_ERROR ( Status )) {\r
-    DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,\r
-              "0x%08x: Packet receive aborted on port: 0x%08x\r\n",\r
-              pIo->pPacket,\r
-              pPort ));\r
-  }\r
-  else {\r
-    DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,\r
-              "0x%08x: Packet receive pending on Port 0x%08x, Status: %r\r\n",\r
-              pIo->pPacket,\r
-              pPort,\r
-              Status ));\r
-  }\r
-  DBG_EXIT ( );\r
-}\r
-\r
-\r
-/** Process the receive completion.\r
-\r
-  This routine queues the data in FIFO order in either the urgent\r
-  or normal data queues depending upon the type of data received.\r
-  See the \ref ReceiveEngine section.\r
-\r
-  This routine is called when some data is received by:\r
-  <ul>\r
-    <li>::EslIp4RxComplete</li>\r
-    <li>::EslTcp4RxComplete</li>\r
-    <li>::EslUdp4RxComplete</li>\r
-  </ul>\r
-\r
-  @param[in]  pIo           Address of an ::ESL_IO_MGMT structure\r
-  @param[in]  Status        Receive status\r
-  @param[in]  LengthInBytes Length of the receive data\r
-  @param[in]  bUrgent       TRUE if urgent data is received and FALSE\r
-                            for normal data.\r
-**/\r
-VOID\r
-EslSocketRxComplete (\r
-  IN ESL_IO_MGMT * pIo,\r
-  IN EFI_STATUS Status,\r
-  IN UINTN LengthInBytes,\r
-  IN BOOLEAN bUrgent\r
-  )\r
-{\r
-  BOOLEAN bUrgentQueue;\r
-  ESL_IO_MGMT * pIoNext;\r
-  ESL_PACKET * pPacket;\r
-  ESL_PORT * pPort;\r
-  ESL_PACKET * pPrevious;\r
-  ESL_PACKET ** ppQueueHead;\r
-  ESL_PACKET ** ppQueueTail;\r
-  size_t * pRxBytes;\r
-  ESL_SOCKET * pSocket;\r
-\r
-  DBG_ENTER ( );\r
-  VERIFY_AT_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  Locate the active receive packet\r
-  //\r
-  pPacket = pIo->pPacket;\r
-  pPort = pIo->pPort;\r
-  pSocket = pPort->pSocket;\r
-\r
-  //\r
-  //         pPort->pRxActive\r
-  //                |\r
-  //                V\r
-  //          +-------------+   +-------------+   +-------------+\r
-  //  Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-  //          +-------------+   +-------------+   +-------------+\r
-  //\r
-  //          +-------------+   +-------------+   +-------------+\r
-  //  Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-  //          +-------------+   +-------------+   +-------------+\r
-  //                ^\r
-  //                |\r
-  //          pPort->pRxFree\r
-  //\r
-  //\r
-  //  Remove the IO structure from the active list\r
-  //  The following code searches for the entry in the list and does not\r
-  //  assume that the receive operations complete in the order they were\r
-  //  issued to the UEFI network layer.\r
-  //\r
-  pIoNext = pPort->pRxActive;\r
-  while (( NULL != pIoNext ) && ( pIoNext != pIo ) && ( pIoNext->pNext != pIo ))\r
-  {\r
-    pIoNext = pIoNext->pNext;\r
-  }\r
-  ASSERT ( NULL != pIoNext );\r
-  if ( pIoNext == pIo ) {\r
-    pPort->pRxActive = pIo->pNext;  //  Beginning of list\r
-  }\r
-  else {\r
-    pIoNext->pNext = pIo->pNext;    //  Middle of list\r
-  }\r
-\r
-  //\r
-  //  Free the IO structure\r
-  //\r
-  pIo->pNext = pPort->pRxFree;\r
-  pPort->pRxFree = pIo;\r
-\r
-  //\r
-  //            pRxOobPacketListHead              pRxOobPacketListTail\r
-  //                      |                                 |\r
-  //                      V                                 V\r
-  //               +------------+   +------------+   +------------+\r
-  //  Urgent Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL\r
-  //               +------------+   +------------+   +------------+\r
-  //\r
-  //               +------------+   +------------+   +------------+\r
-  //  Normal Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL\r
-  //               +------------+   +------------+   +------------+\r
-  //                      ^                                 ^\r
-  //                      |                                 |\r
-  //              pRxPacketListHead                pRxPacketListTail\r
-  //\r
-  //\r
-  //  Determine the queue to use\r
-  //\r
-  bUrgentQueue = (BOOLEAN)( bUrgent\r
-               && pSocket->pApi->bOobSupported\r
-               && ( !pSocket->bOobInLine ));\r
-  if ( bUrgentQueue ) {\r
-    ppQueueHead = &pSocket->pRxOobPacketListHead;\r
-    ppQueueTail = &pSocket->pRxOobPacketListTail;\r
-    pRxBytes = &pSocket->RxOobBytes;\r
-  }\r
-  else {\r
-    ppQueueHead = &pSocket->pRxPacketListHead;\r
-    ppQueueTail = &pSocket->pRxPacketListTail;\r
-    pRxBytes = &pSocket->RxBytes;\r
-  }\r
-\r
-  //\r
-  //  Determine if this receive was successful\r
-  //\r
-  if (( !EFI_ERROR ( Status ))\r
-    && ( PORT_STATE_CLOSE_STARTED > pPort->State )\r
-    && ( !pSocket->bRxDisable )) {\r
-    //\r
-    //  Account for the received data\r
-    //\r
-    *pRxBytes += LengthInBytes;\r
-\r
-    //\r
-    //  Log the received data\r
-    //\r
-    DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-              "0x%08x: Packet queued on %s queue of port 0x%08x with 0x%08x bytes of %s data\r\n",\r
-              pPacket,\r
-              bUrgentQueue ? L"urgent" : L"normal",\r
-              pPort,\r
-              LengthInBytes,\r
-              bUrgent ? L"urgent" : L"normal" ));\r
-\r
-    //\r
-    //  Add the packet to the list tail.\r
-    //\r
-    pPacket->pNext = NULL;\r
-    pPrevious = *ppQueueTail;\r
-    if ( NULL == pPrevious ) {\r
-      *ppQueueHead = pPacket;\r
-    }\r
-    else {\r
-      pPrevious->pNext = pPacket;\r
-    }\r
-    *ppQueueTail = pPacket;\r
-\r
-    //\r
-    //  Attempt to restart this receive operation\r
-    //\r
-    if ( pSocket->MaxRxBuf > pSocket->RxBytes ) {\r
-      EslSocketRxStart ( pPort );\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_RX,\r
-                "0x%08x: Port RX suspended, 0x%08x bytes queued\r\n",\r
-                pPort,\r
-                pSocket->RxBytes ));\r
-    }\r
-  }\r
-  else {\r
-    if ( EFI_ERROR ( Status )) {\r
-        DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-                  "ERROR - Receive error on port 0x%08x, packet 0x%08x, Status:%r\r\n",\r
-                  pPort,\r
-                  pPacket,\r
-                  Status ));\r
-    }\r
-\r
-    //\r
-    //  Account for the receive bytes and release the driver's buffer\r
-    //\r
-    if ( !EFI_ERROR ( Status )) {\r
-      *pRxBytes += LengthInBytes;\r
-      pSocket->pApi->pfnPacketFree ( pPacket, pRxBytes );\r
-    }\r
-\r
-    //\r
-    //  Receive error, free the packet save the error\r
-    //\r
-    EslSocketPacketFree ( pPacket, DEBUG_RX );\r
-    if ( !EFI_ERROR ( pSocket->RxError )) {\r
-      pSocket->RxError = Status;\r
-    }\r
-\r
-    //\r
-    //  Update the port state\r
-    //\r
-    if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {\r
-      if ( PORT_STATE_CLOSE_DONE == pPort->State ) {\r
-        EslSocketPortCloseRxDone ( pPort );\r
-      }\r
-    }\r
-    else {\r
-      if ( EFI_ERROR ( Status )) {\r
-        DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-                  "0x%08x: Port state: PORT_STATE_RX_ERROR, Status: %r\r\n",\r
-                  pPort,\r
-                  Status ));\r
-        pPort->State = PORT_STATE_RX_ERROR;\r
-      }\r
-    }\r
-  }\r
-\r
-  DBG_EXIT ( );\r
-}\r
-\r
-\r
-/** Poll a socket for pending receive activity.\r
-\r
-  This routine is called at elivated TPL and extends the idle\r
-  loop which polls a socket down into the LAN driver layer to\r
-  determine if there is any receive activity.\r
-\r
-  The ::EslSocketPoll, ::EslSocketReceive and ::EslSocketTransmit\r
-  routines call this routine when there is nothing to do.\r
-\r
-  @param[in]  pSocket   Address of an ::EFI_SOCKET structure.\r
- **/\r
-VOID\r
-EslSocketRxPoll (\r
-  IN ESL_SOCKET * pSocket\r
-  )\r
-{\r
-  ESL_PORT * pPort;\r
-\r
-  DEBUG (( DEBUG_POLL, "Entering EslSocketRxPoll\r\n" ));\r
-\r
-  //\r
-  //  Increase the network performance by extending the\r
-  //  polling (idle) loop down into the LAN driver\r
-  //\r
-  pPort = pSocket->pPortList;\r
-  while ( NULL != pPort ) {\r
-    //\r
-    //  Poll the LAN adapter\r
-    //\r
-    pPort->pfnRxPoll ( pPort->pProtocol.v );\r
-\r
-    //\r
-    //  Locate the next LAN adapter\r
-    //\r
-    pPort = pPort->pLinkSocket;\r
-  }\r
-\r
-  DEBUG (( DEBUG_POLL, "Exiting EslSocketRxPoll\r\n" ));\r
-}\r
-\r
-\r
-/** Start a receive operation.\r
-\r
-  This routine posts a receive buffer to the network adapter.\r
-  See the \ref ReceiveEngine section.\r
-\r
-  This support routine is called by:\r
-  <ul>\r
-    <li>::EslIp4Receive to restart the receive engine to release flow control.</li>\r
-    <li>::EslIp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>\r
-    <li>::EslIp4SocketIsConfigured to start the receive engine for the new socket.</li>\r
-    <li>::EslTcp4ListenComplete to start the recevie engine for the new socket.</li>\r
-    <li>::EslTcp4Receive to restart the receive engine to release flow control.</li>\r
-    <li>::EslTcp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>\r
-    <li>::EslUdp4Receive to restart the receive engine to release flow control.</li>\r
-    <li>::EslUdp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>\r
-    <li>::EslUdp4SocketIsConfigured to start the recevie engine for the new socket.</li>\r
-  </ul>\r
-\r
-  @param[in]  pPort       Address of an ::ESL_PORT structure.\r
-**/\r
-VOID\r
-EslSocketRxStart (\r
-  IN ESL_PORT * pPort\r
-  )\r
-{\r
-  UINT8 * pBuffer;\r
-  ESL_IO_MGMT * pIo;\r
-  ESL_PACKET * pPacket;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Determine if a receive is already pending\r
-  //\r
-  Status = EFI_SUCCESS;\r
-  pPacket = NULL;\r
-  pSocket = pPort->pSocket;\r
-  if ( !EFI_ERROR ( pPort->pSocket->RxError )) {\r
-    if (( NULL != pPort->pRxFree )\r
-      && ( !pSocket->bRxDisable )\r
-      && ( PORT_STATE_CLOSE_STARTED > pPort->State )) {\r
-      //\r
-      //  Start all of the pending receive operations\r
-      //\r
-      while ( NULL != pPort->pRxFree ) {\r
-        //\r
-        //  Determine if there are any free packets\r
-        //\r
-        pPacket = pSocket->pRxFree;\r
-        if ( NULL != pPacket ) {\r
-          //\r
-          //  Remove this packet from the free list\r
-          //\r
-          pSocket->pRxFree = pPacket->pNext;\r
-          DEBUG (( DEBUG_RX,\r
-                    "0x%08x: Port removed packet 0x%08x from free list\r\n",\r
-                    pPort,\r
-                    pPacket ));\r
-        }\r
-        else {\r
-          //\r
-          //  Allocate a packet structure\r
-          //\r
-          Status = EslSocketPacketAllocate ( &pPacket,\r
-                                             pSocket->pApi->RxPacketBytes,\r
-                                             pSocket->pApi->RxZeroBytes,\r
-                                             DEBUG_RX );\r
-          if ( EFI_ERROR ( Status )) {\r
-            pPacket = NULL;\r
-            DEBUG (( DEBUG_ERROR | DEBUG_RX,\r
-                      "0x%08x: Port failed to allocate RX packet, Status: %r\r\n",\r
-                      pPort,\r
-                      Status ));\r
-            break;\r
-          }\r
-        }\r
-\r
-        //\r
-        //  Connect the IO and packet structures\r
-        //\r
-        pIo = pPort->pRxFree;\r
-        pIo->pPacket = pPacket;\r
-\r
-        //\r
-        //  Eliminate the need for IP4 and UDP4 specific routines by\r
-        //  clearing the RX data pointer here.\r
-        //\r
-        //  No driver buffer for this packet\r
-        //\r
-        //    +--------------------+\r
-        //    | ESL_IO_MGMT        |\r
-        //    |                    |\r
-        //    |    +---------------+\r
-        //    |    | Token         |\r
-        //    |    |        RxData --> NULL\r
-        //    +----+---------------+\r
-        //\r
-        pBuffer = (UINT8 *)pIo;\r
-        pBuffer = &pBuffer[ pSocket->pApi->RxBufferOffset ];\r
-        *(VOID **)pBuffer = NULL;\r
-\r
-        //\r
-        //  Network specific receive packet initialization\r
-        //\r
-        if ( NULL != pSocket->pApi->pfnRxStart ) {\r
-          pSocket->pApi->pfnRxStart ( pPort, pIo );\r
-        }\r
-\r
-        //\r
-        //  Start the receive on the packet\r
-        //\r
-        Status = pPort->pfnRxStart ( pPort->pProtocol.v, &pIo->Token );\r
-        if ( !EFI_ERROR ( Status )) {\r
-          DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-                    "0x%08x: Packet receive pending on port 0x%08x\r\n",\r
-                    pPacket,\r
-                    pPort ));\r
-          //\r
-          //  Allocate the receive control structure\r
-          //\r
-          pPort->pRxFree = pIo->pNext;\r
-\r
-          //\r
-          //  Mark this receive as pending\r
-          //\r
-          pIo->pNext = pPort->pRxActive;\r
-          pPort->pRxActive = pIo;\r
-\r
-        }\r
-        else {\r
-          DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-                    "ERROR - Failed to post a receive on port 0x%08x, Status: %r\r\n",\r
-                    pPort,\r
-                    Status ));\r
-          if ( !EFI_ERROR ( pSocket->RxError )) {\r
-            //\r
-            //  Save the error status\r
-            //\r
-            pSocket->RxError = Status;\r
-          }\r
-\r
-          //\r
-          //  Free the packet\r
-          //\r
-          pIo->pPacket = NULL;\r
-          pPacket->pNext = pSocket->pRxFree;\r
-          pSocket->pRxFree = pPacket;\r
-          break;\r
-        }\r
-      }\r
-    }\r
-    else {\r
-      if ( NULL == pPort->pRxFree ) {\r
-        DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-                  "0x%08x: Port, no available ESL_IO_MGMT structures\r\n",\r
-                  pPort));\r
-      }\r
-      if ( pSocket->bRxDisable ) {\r
-        DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-                  "0x%08x: Port, receive disabled!\r\n",\r
-                  pPort ));\r
-      }\r
-      if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {\r
-        DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-                  "0x%08x: Port, is closing!\r\n",\r
-                  pPort ));\r
-      }\r
-    }\r
-  }\r
-  else {\r
-    DEBUG (( DEBUG_ERROR | DEBUG_RX,\r
-              "ERROR - Previous receive error, Status: %r\r\n",\r
-               pPort->pSocket->RxError ));\r
-  }\r
-\r
-  DBG_EXIT ( );\r
-}\r
-\r
-\r
-/** Shutdown the socket receive and transmit operations.\r
-\r
-  This routine sets a flag to stop future transmissions and calls\r
-  the network specific layer to cancel the pending receive operation.\r
-\r
-  The ::shutdown routine calls this routine to stop receive and transmit\r
-  operations on the socket.\r
-\r
-  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[in]  How             Which operations to stop\r
-  @param[out] pErrno          Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS - Socket operations successfully shutdown\r
-**/\r
-EFI_STATUS\r
-EslSocketShutdown (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN int How,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  ESL_IO_MGMT * pIo;\r
-  ESL_PORT * pPort;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Validate the socket\r
-  //\r
-  pSocket = NULL;\r
-  if ( NULL != pSocketProtocol ) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
-    //\r
-    //  Verify that the socket is connected\r
-    //\r
-    if ( pSocket->bConnected ) {\r
-      //\r
-      //  Validate the How value\r
-      //\r
-      if (( SHUT_RD <= How ) && ( SHUT_RDWR >= How )) {\r
-        //\r
-        //  Synchronize with the socket layer\r
-        //\r
-        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-        //\r
-        //  Disable the receiver if requested\r
-        //\r
-        if (( SHUT_RD == How ) || ( SHUT_RDWR == How )) {\r
-          pSocket->bRxDisable = TRUE;\r
-        }\r
-\r
-        //\r
-        //  Disable the transmitter if requested\r
-        //\r
-        if (( SHUT_WR == How ) || ( SHUT_RDWR == How )) {\r
-          pSocket->bTxDisable = TRUE;\r
-        }\r
-\r
-        //\r
-        //  Cancel the pending receive operations\r
-        //\r
-        if ( pSocket->bRxDisable ) {\r
-          //\r
-          //  Walk the list of ports\r
-          //\r
-          pPort = pSocket->pPortList;\r
-          while ( NULL != pPort ) {\r
-            //\r
-            //  Walk the list of active receive operations\r
-            //\r
-            pIo = pPort->pRxActive;\r
-            while ( NULL != pIo ) {\r
-              EslSocketRxCancel ( pPort, pIo );\r
-            }\r
-\r
-            //\r
-            //  Set the next port\r
-            //\r
-            pPort = pPort->pLinkSocket;\r
-          }\r
-        }\r
-\r
-        //\r
-        //  Release the socket layer synchronization\r
-        //\r
-        RESTORE_TPL ( TplPrevious );\r
-      }\r
-      else {\r
-        //\r
-        //  Invalid How value\r
-        //\r
-        pSocket->errno = EINVAL;\r
-        Status = EFI_INVALID_PARAMETER;\r
-      }\r
-    }\r
-    else {\r
-      //\r
-      //  The socket is not connected\r
-      //\r
-      pSocket->errno = ENOTCONN;\r
-      Status = EFI_NOT_STARTED;\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    if ( NULL != pSocket ) {\r
-      *pErrno = pSocket->errno;\r
-    }\r
-    else {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = ENOTSOCK;\r
-    }\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Send data using a network connection.\r
-\r
-  This routine calls the network specific layer to queue the data\r
-  for transmission.  Eventually the buffer will reach the head of\r
-  the queue and will get transmitted over the network by the\r
-  \ref TransmitEngine.  For datagram\r
-  sockets (SOCK_DGRAM and SOCK_RAW) there is no guarantee that\r
-  the data reaches the application running on the remote system.\r
-\r
-  The ::sendto routine calls this routine to send data to the remote\r
-  system.  Note that ::send and ::write are layered on top of ::sendto.\r
-\r
-  @param[in]  pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  @param[in]  Flags           Message control flags\r
-  @param[in]  BufferLength    Length of the the buffer\r
-  @param[in]  pBuffer         Address of a buffer containing the data to send\r
-  @param[in]  pDataLength     Address to receive the number of data bytes sent\r
-  @param[in]  pAddress        Network address of the remote system address\r
-  @param[in]  AddressLength   Length of the remote network address structure\r
-  @param[out] pErrno          Address to receive the errno value upon completion.\r
-\r
-  @retval EFI_SUCCESS - Socket data successfully queued for transmit\r
-**/\r
-EFI_STATUS\r
-EslSocketTransmit (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN int Flags,\r
-  IN size_t BufferLength,\r
-  IN CONST UINT8 * pBuffer,\r
-  OUT size_t * pDataLength,\r
-  IN const struct sockaddr * pAddress,\r
-  IN socklen_t AddressLength,\r
-  IN int * pErrno\r
-  )\r
-{\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Validate the socket\r
-  //\r
-  pSocket = NULL;\r
-  if ( NULL != pSocketProtocol ) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
-    //\r
-    //  Return the transmit error if necessary\r
-    //\r
-    if ( EFI_SUCCESS != pSocket->TxError ) {\r
-      pSocket->errno = EIO;\r
-      Status = pSocket->TxError;\r
-      pSocket->TxError = EFI_SUCCESS;\r
-    }\r
-    else {\r
-      //\r
-      //  Verify the socket state\r
-      //\r
-      Status = EslSocketIsConfigured ( pSocket );\r
-      if ( !EFI_ERROR ( Status )) {\r
-        //\r
-        //  Verify that transmit is still allowed\r
-        //\r
-        if ( !pSocket->bTxDisable ) {\r
-          //\r
-          //  Validate the buffer length\r
-          //\r
-          if (( NULL == pDataLength )\r
-            && ( 0 > pDataLength )\r
-            && ( NULL == pBuffer )) {\r
-            if ( NULL == pDataLength ) {\r
-              DEBUG (( DEBUG_RX,\r
-                        "ERROR - pDataLength is NULL!\r\n" ));\r
-            }\r
-            else if ( NULL == pBuffer ) {\r
-              DEBUG (( DEBUG_RX,\r
-                        "ERROR - pBuffer is NULL!\r\n" ));\r
-            }\r
-            else {\r
-              DEBUG (( DEBUG_RX,\r
-                        "ERROR - Data length < 0!\r\n" ));\r
-            }\r
-            Status = EFI_INVALID_PARAMETER;\r
-            pSocket->errno = EFAULT;\r
-          }\r
-          else {\r
-            //\r
-            //  Validate the remote network address\r
-            //\r
-            if (( NULL != pAddress )\r
-              && ( AddressLength < pAddress->sa_len )) {\r
-              DEBUG (( DEBUG_TX,\r
-                        "ERROR - Invalid sin_len field in address\r\n" ));\r
-              Status = EFI_INVALID_PARAMETER;\r
-              pSocket->errno = EFAULT;\r
-            }\r
-            else {\r
-              //\r
-              //  Verify the API\r
-              //\r
-              if ( NULL == pSocket->pApi->pfnTransmit ) {\r
-                Status = EFI_UNSUPPORTED;\r
-                pSocket->errno = ENOTSUP;\r
-              }\r
-              else {\r
-                //\r
-                //  Synchronize with the socket layer\r
-                //\r
-                RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-                //\r
-                //  Poll the network to increase performance\r
-                //\r
-                EslSocketRxPoll ( pSocket );\r
-\r
-                //\r
-                //  Attempt to buffer the packet for transmission\r
-                //\r
-                Status = pSocket->pApi->pfnTransmit ( pSocket,\r
-                                                      Flags,\r
-                                                      BufferLength,\r
-                                                      pBuffer,\r
-                                                      pDataLength,\r
-                                                      pAddress,\r
-                                                      AddressLength );\r
-\r
-                //\r
-                //  Release the socket layer synchronization\r
-                //\r
-                RESTORE_TPL ( TplPrevious );\r
-              }\r
-            }\r
-          }\r
-        }\r
-        else {\r
-          //\r
-          //  The transmitter was shutdown\r
-          //\r
-          pSocket->errno = EPIPE;\r
-          Status = EFI_NOT_STARTED;\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  if ( NULL != pErrno ) {\r
-    if ( NULL != pSocket ) {\r
-      *pErrno = pSocket->errno;\r
-    }\r
-    else {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = ENOTSOCK;\r
-    }\r
-  }\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/** Complete the transmit operation.\r
-\r
-  This support routine handles the transmit completion processing for\r
-  the various network layers.  It frees the ::ESL_IO_MGMT structure\r
-  and and frees packet resources by calling ::EslSocketPacketFree.\r
-  Transmit errors are logged in ESL_SOCKET::TxError.\r
-  See the \ref TransmitEngine section.\r
-\r
-  This routine is called by:\r
-  <ul>\r
-    <li>::EslIp4TxComplete</li>\r
-    <li>::EslTcp4TxComplete</li>\r
-    <li>::EslTcp4TxOobComplete</li>\r
-    <li>::EslUdp4TxComplete</li>\r
-  </ul>\r
-\r
-  @param[in]  pIo             Address of an ::ESL_IO_MGMT structure\r
-  @param[in]  LengthInBytes   Length of the data in bytes\r
-  @param[in]  Status          Transmit operation status\r
-  @param[in]  pQueueType      Zero terminated string describing queue type\r
-  @param[in]  ppQueueHead     Transmit queue head address\r
-  @param[in]  ppQueueTail     Transmit queue tail address\r
-  @param[in]  ppActive        Active transmit queue address\r
-  @param[in]  ppFree          Free transmit queue address\r
-**/\r
-VOID\r
-EslSocketTxComplete (\r
-  IN ESL_IO_MGMT * pIo,\r
-  IN UINT32 LengthInBytes,\r
-  IN EFI_STATUS Status,\r
-  IN CONST CHAR8 * pQueueType,\r
-  IN ESL_PACKET ** ppQueueHead,\r
-  IN ESL_PACKET ** ppQueueTail,\r
-  IN ESL_IO_MGMT ** ppActive,\r
-  IN ESL_IO_MGMT ** ppFree\r
-  )\r
-{\r
-  ESL_PACKET * pCurrentPacket;\r
-  ESL_IO_MGMT * pIoNext;\r
-  ESL_PACKET * pNextPacket;\r
-  ESL_PACKET * pPacket;\r
-  ESL_PORT * pPort;\r
-  ESL_SOCKET * pSocket;\r
-\r
-  DBG_ENTER ( );\r
-  VERIFY_AT_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  Locate the active transmit packet\r
-  //\r
-  pPacket = pIo->pPacket;\r
-  pPort = pIo->pPort;\r
-  pSocket = pPort->pSocket;\r
-\r
-  //\r
-  //  No more packet\r
-  //\r
-  pIo->pPacket = NULL;\r
-\r
-  //\r
-  //  Remove the IO structure from the active list\r
-  //\r
-  pIoNext = *ppActive;\r
-  while (( NULL != pIoNext ) && ( pIoNext != pIo ) && ( pIoNext->pNext != pIo ))\r
-  {\r
-    pIoNext = pIoNext->pNext;\r
-  }\r
-  ASSERT ( NULL != pIoNext );\r
-  if ( pIoNext == pIo ) {\r
-    *ppActive = pIo->pNext;       //  Beginning of list\r
-  }\r
-  else {\r
-    pIoNext->pNext = pIo->pNext;  //  Middle of list\r
-  }\r
-\r
-  //\r
-  //  Free the IO structure\r
-  //\r
-  pIo->pNext = *ppFree;\r
-  *ppFree = pIo;\r
-\r
-  //\r
-  //  Display the results\r
-  //\r
-  DEBUG (( DEBUG_TX | DEBUG_INFO,\r
-            "0x%08x: pIo Released\r\n",\r
-            pIo ));\r
-\r
-  //\r
-  //  Save any transmit error\r
-  //\r
-  if ( EFI_ERROR ( Status )) {\r
-    if ( !EFI_ERROR ( pSocket->TxError )) {\r
-      pSocket->TxError = Status;\r
-    }\r
-    DEBUG (( DEBUG_TX | DEBUG_INFO,\r
-              "ERROR - Transmit failure for %apacket 0x%08x, Status: %r\r\n",\r
-              pQueueType,\r
-              pPacket,\r
-              Status ));\r
-\r
-    //\r
-    //  Empty the normal transmit list\r
-    //\r
-    pCurrentPacket = pPacket;\r
-    pNextPacket = *ppQueueHead;\r
-    while ( NULL != pNextPacket ) {\r
-      pPacket = pNextPacket;\r
-      pNextPacket = pPacket->pNext;\r
-      EslSocketPacketFree ( pPacket, DEBUG_TX );\r
-    }\r
-    *ppQueueHead = NULL;\r
-    *ppQueueTail = NULL;\r
-    pPacket = pCurrentPacket;\r
-  }\r
-  else {\r
-    DEBUG (( DEBUG_TX | DEBUG_INFO,\r
-              "0x%08x: %apacket transmitted %d bytes successfully\r\n",\r
-              pPacket,\r
-              pQueueType,\r
-              LengthInBytes ));\r
-\r
-    //\r
-    //  Verify the transmit engine is still running\r
-    //\r
-    if ( !pPort->bCloseNow ) {\r
-      //\r
-      //  Start the next packet transmission\r
-      //\r
-      EslSocketTxStart ( pPort,\r
-                         ppQueueHead,\r
-                         ppQueueTail,\r
-                         ppActive,\r
-                         ppFree );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Release this packet\r
-  //\r
-  EslSocketPacketFree ( pPacket, DEBUG_TX );\r
-\r
-  //\r
-  //  Finish the close operation if necessary\r
-  //\r
-  if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {\r
-    //\r
-    //  Indicate that the transmit is complete\r
-    //\r
-    EslSocketPortCloseTxDone ( pPort );\r
-  }\r
-\r
-  DBG_EXIT ( );\r
-}\r
-\r
-\r
-/** Transmit data using a network connection.\r
-\r
-  This support routine starts a transmit operation on the\r
-  underlying network layer.\r
-\r
-  The network specific code calls this routine to start a\r
-  transmit operation.  See the \ref TransmitEngine section.\r
-\r
-  @param[in]  pPort           Address of an ::ESL_PORT structure\r
-  @param[in]  ppQueueHead     Transmit queue head address\r
-  @param[in]  ppQueueTail     Transmit queue tail address\r
-  @param[in]  ppActive        Active transmit queue address\r
-  @param[in]  ppFree          Free transmit queue address\r
-**/\r
-VOID\r
-EslSocketTxStart (\r
-  IN ESL_PORT * pPort,\r
-  IN ESL_PACKET ** ppQueueHead,\r
-  IN ESL_PACKET ** ppQueueTail,\r
-  IN ESL_IO_MGMT ** ppActive,\r
-  IN ESL_IO_MGMT ** ppFree\r
-  )\r
-{\r
-  UINT8 * pBuffer;\r
-  ESL_IO_MGMT * pIo;\r
-  ESL_PACKET * pNextPacket;\r
-  ESL_PACKET * pPacket;\r
-  VOID ** ppTokenData;\r
-  ESL_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Get the packet from the queue head\r
-  //\r
-  pPacket = *ppQueueHead;\r
-  pIo = *ppFree;\r
-  if (( NULL != pPacket ) && ( NULL != pIo )) {\r
-    pSocket = pPort->pSocket;\r
-    //\r
-    //     *ppQueueHead: pSocket->pRxPacketListHead or pSocket->pRxOobPacketListHead\r
-    //          |\r
-    //          V\r
-    //        +------------+   +------------+   +------------+\r
-    //  Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL\r
-    //        +------------+   +------------+   +------------+\r
-    //                                                     ^\r
-    //                                                     |\r
-    //     *ppQueueTail: pSocket->pRxPacketListTail or pSocket->pRxOobPacketListTail\r
-    //\r
-    //\r
-    //  Remove the packet from the queue\r
-    //\r
-    pNextPacket = pPacket->pNext;\r
-    *ppQueueHead = pNextPacket;\r
-    if ( NULL == pNextPacket ) {\r
-      *ppQueueTail = NULL;\r
-    }\r
-    pPacket->pNext = NULL;\r
-\r
-    //\r
-    //  Eliminate the need for IP4 and UDP4 specific routines by\r
-    //  connecting the token with the TX data control structure here.\r
-    //\r
-    //    +--------------------+   +--------------------+\r
-    //    | ESL_IO_MGMT        |   | ESL_PACKET         |\r
-    //    |                    |   |                    |\r
-    //    |    +---------------+   +----------------+   |\r
-    //    |    | Token         |   | Buffer Length  |   |\r
-    //    |    |        TxData --> | Buffer Address |   |\r
-    //    |    |               |   +----------------+---+\r
-    //    |    |        Event  |   | Data Buffer        |\r
-    //    +----+---------------+   |                    |\r
-    //                             +--------------------+\r
-    //\r
-    //  Compute the address of the TxData pointer in the token\r
-    //\r
-    pBuffer = (UINT8 *)&pIo->Token;\r
-    pBuffer = &pBuffer[ pSocket->TxTokenOffset ];\r
-    ppTokenData = (VOID **)pBuffer;\r
-\r
-    //\r
-    //  Compute the address of the TX data control structure in the packet\r
-    //\r
-    //      * EFI_IP4_TRANSMIT_DATA\r
-    //      * EFI_TCP4_TRANSMIT_DATA\r
-    //      * EFI_UDP4_TRANSMIT_DATA\r
-    //\r
-    pBuffer = (UINT8 *)pPacket;\r
-    pBuffer = &pBuffer[ pSocket->TxPacketOffset ];\r
-\r
-    //\r
-    //  Connect the token to the transmit data control structure\r
-    //\r
-    *ppTokenData = (VOID **)pBuffer;\r
-\r
-    //\r
-    //  Display the results\r
-    //\r
-    DEBUG (( DEBUG_TX | DEBUG_INFO,\r
-              "0x%08x: pIo allocated for pPacket: 0x%08x\r\n",\r
-              pIo,\r
-              pPacket ));\r
-\r
-    //\r
-    //  Start the transmit operation\r
-    //\r
-    Status = pPort->pfnTxStart ( pPort->pProtocol.v,\r
-                                 &pIo->Token );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      //\r
-      //  Connect the structures\r
-      //\r
-      pIo->pPacket = pPacket;\r
-\r
-      //\r
-      //          +-------------+   +-------------+   +-------------+\r
-      //  Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-      //          +-------------+   +-------------+   +-------------+\r
-      //              ^\r
-      //              |\r
-      //          *ppFree:  pPort->pTxFree or pTxOobFree\r
-      //\r
-      //\r
-      //  Remove the IO structure from the queue\r
-      //\r
-      *ppFree = pIo->pNext;\r
-\r
-      //\r
-      //         *ppActive:  pPort->pTxActive or pTxOobActive\r
-      //             |\r
-      //             V\r
-      //          +-------------+   +-------------+   +-------------+\r
-      //  Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-      //          +-------------+   +-------------+   +-------------+\r
-      //\r
-      //\r
-      //  Mark this packet as active\r
-      //\r
-      pIo->pPacket = pPacket;\r
-      pIo->pNext = *ppActive;\r
-      *ppActive = pIo;\r
-    }\r
-    else {\r
-      //\r
-      //  Display the transmit error\r
-      //\r
-      DEBUG (( DEBUG_TX | DEBUG_INFO,\r
-                "0x%08x, 0x%08x: pIo, pPacket transmit failure: %r\r\n",\r
-                pIo,\r
-                pPacket,\r
-                Status ));\r
-      if ( EFI_SUCCESS == pSocket->TxError ) {\r
-        pSocket->TxError = Status;\r
-      }\r
-\r
-      //\r
-      //  Free the IO structure\r
-      //\r
-      pIo->pNext = *ppFree;\r
-      *ppFree = pIo;\r
-\r
-      //\r
-      //  Discard the transmit buffer\r
-      //\r
-      EslSocketPacketFree ( pPacket, DEBUG_TX );\r
-    }\r
-  }\r
-\r
-  DBG_EXIT ( );\r
-}\r