]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/EfiSocketLib/Socket.c
Fix a bug about the iSCSI DHCP dependency issue.
[mirror_edk2.git] / StdLib / EfiSocketLib / Socket.c
index ebbc8df4d2ab2bc6fd567a3206dc0cfaa0f328c5..a74dcd07f60021f5a2f74a841438038079c504a2 100644 (file)
   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\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
   List the network stack connection points for the socket driver.\r
 **/\r
-CONST DT_SOCKET_BINDING cEslSocketBinding [] = {\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
-    EslTcpInitialize4,\r
-    EslTcpShutdown4 },\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
-    EslUdpInitialize4,\r
-    EslUdpShutdown4 }\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
-DT_LAYER mEslLayer;\r
+/**\r
+  APIs to support the various socket types for the v4 network stack.\r
+**/\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
+/**\r
+  Number of entries in the v4 API array ::cEslAfInetApi.\r
+**/\r
+CONST int cEslAfInetApiSize = DIM ( cEslAfInetApi );\r
+\r
+\r
+/**\r
+  APIs to support the various socket types for the v6 network stack.\r
+**/\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
+/**\r
+  Number of entries in the v6 API array ::cEslAfInet6Api.\r
+**/\r
+CONST int cEslAfInet6ApiSize = DIM ( cEslAfInet6Api );\r
+\r
+\r
+/**\r
+  Global management structure for the socket layer.\r
+**/\r
+ESL_LAYER mEslLayer;\r
 \r
 \r
 /**\r
   Initialize an endpoint for network communication.\r
 \r
-  The ::Socket routine initializes the communication endpoint by providing\r
-  the support for the socket library function ::socket.  The\r
-  <a href="http://www.linuxhowtos.org/manpages/2/socket.htm">Linux</a>,\r
-  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html">POSIX</a>\r
-  and <a href="http://msdn.microsoft.com/en-us/library/ms740506(v=VS.85).aspx">Windows</a>\r
-  documentation for the socket routine are available online for reference.\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.\r
-\r
-  @param [in] type      Specifies how to make the network connection.  The following values\r
-                        are supported:\r
-                        <ul>\r
-                          <li>\r
-                            SOCK_STREAM - Connect to TCP, provides a byte stream\r
-                            that is manipluated by read, recv, send and write.\r
-                          </li>\r
-                          <li>\r
-                            SOCK_SEQPACKET - Connect to TCP, provides sequenced packet stream\r
-                            that is manipulated by read, recv, send and write.\r
-                          </li>\r
-                          <li>\r
-                            SOCK_DGRAM - Connect to UDP, provides a datagram service that is\r
-                            manipulated by recvfrom and sendto.\r
-                          </li>\r
-                        </ul>\r
-\r
-  @param [in] protocol  Specifies the lower layer protocol to use.  The following\r
-                        values are supported:\r
-                        <ul>\r
-                          <li>IPPROTO_TCP</li> - This value must be combined with SOCK_STREAM.</li>\r
-                          <li>IPPROTO_UDP</li> - This value must be combined with SOCK_DGRAM.</li>\r
-                        </ul>\r
-\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
@@ -97,7 +583,11 @@ EslSocket (
   IN int * pErrno\r
   )\r
 {\r
-  DT_SOCKET * pSocket;\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
@@ -129,15 +619,30 @@ EslSocket (
     //  Validate the domain value\r
     //\r
     if (( AF_INET != domain )\r
-      && ( AF_LOCAL != domain ))\r
-    {\r
+      && ( AF_INET6 != domain )\r
+      && ( AF_LOCAL != domain )) {\r
       DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r
-                "ERROR - Invalid domain value" ));\r
+                "ERROR - Invalid domain value\r\n" ));\r
       Status = EFI_INVALID_PARAMETER;\r
       errno = EAFNOSUPPORT;\r
       break;\r
     }\r
 \r
+    //\r
+    //  Determine the protocol APIs\r
+    //\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
     //\r
     //  Set the default type if necessary\r
     //\r
@@ -148,46 +653,81 @@ EslSocket (
     //\r
     //  Validate the type value\r
     //\r
-    if (( SOCK_STREAM == type )\r
-      || ( SOCK_SEQPACKET == type )) {\r
-      //\r
-      //  Set the default protocol if necessary\r
-      //\r
-      if ( 0 == protocol ) {\r
-        protocol = IPPROTO_TCP;\r
-      }\r
-    }\r
-    else if ( SOCK_DGRAM == type ) {\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
       //\r
-      //  Set the default protocol if necessary\r
+      //  The socket type is not supported\r
       //\r
-      if ( 0 == protocol ) {\r
-        protocol = IPPROTO_UDP;\r
-      }\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r
-                "ERROR - Invalid type value" ));\r
       Status = EFI_INVALID_PARAMETER;\r
-      errno = EINVAL;\r
+      errno = EPROTOTYPE;\r
       break;\r
     }\r
 \r
+    //\r
+    //  Set the default protocol if necessary\r
+    //\r
+    pApi = ppApiArray[ type ];\r
+    if ( 0 == protocol ) {\r
+      protocol = pApi->DefaultProtocol;\r
+    }\r
+\r
     //\r
     //  Validate the protocol value\r
     //\r
-    if (( IPPROTO_TCP != protocol )\r
-      && ( IPPROTO_UDP != protocol )) {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r
-                "ERROR - Invalid protocol value" ));\r
+    if (( pApi->DefaultProtocol != protocol )\r
+      && ( SOCK_RAW != type )) {\r
       Status = EFI_INVALID_PARAMETER;\r
-      errno = EINVAL;\r
+\r
+      //\r
+      //  Assume that the driver supports this protocol\r
+      //\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
+        //\r
+        //  Verify against the IPv6 table\r
+        //\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
+      //\r
+      //  The driver does not support this protocol\r
+      //\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
 \r
     //\r
     //  Save the socket attributes\r
     //\r
+    pSocket->pApi = pApi;\r
     pSocket->Domain = domain;\r
     pSocket->Type = type;\r
     pSocket->Protocol = protocol;\r
@@ -212,11 +752,16 @@ EslSocket (
 /**\r
   Accept a network connection.\r
 \r
-  The SocketAccept routine waits for a network connection to the socket.\r
-  It is able to return the remote network address to the caller if\r
-  requested.\r
+  This routine calls the network specific layer to remove the next\r
+  connection from the FIFO.\r
 \r
-  @param [in] pSocketProtocol Address of the socket protocol structure.\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
 \r
   @param [in] pSockAddr       Address of a buffer to receive the remote\r
                               network address.\r
@@ -225,8 +770,9 @@ EslSocket (
                                     On output specifies the length of the\r
                                     remote network address.\r
 \r
-  @param [out] ppSocketProtocol Address of a buffer to receive the socket protocol\r
-                                instance associated with the new socket.\r
+  @param [out] ppSocketProtocol Address of a buffer to receive the\r
+                                ::EFI_SOCKET_PROTOCOL instance\r
+                                associated with the new socket.\r
 \r
   @param [out] pErrno   Address to receive the errno value upon completion.\r
 \r
@@ -243,8 +789,8 @@ EslSocketAccept (
   IN int * pErrno\r
   )\r
 {\r
-  DT_SOCKET * pNewSocket;\r
-  DT_SOCKET * pSocket;\r
+  ESL_SOCKET * pNewSocket;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
 \r
@@ -264,134 +810,122 @@ EslSocketAccept (
     pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
 \r
     //\r
-    //  Validate the sockaddr\r
+    //  Verify the API\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
+    if ( NULL == pSocket->pApi->pfnAccept ) {\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 the socket is in the listen state\r
+      //  Validate the sockaddr\r
       //\r
-      if ( SOCKET_STATE_LISTENING != pSocket->State ) {\r
+      if (( NULL != pSockAddr )\r
+        && ( NULL == pSockAddrLength )) {\r
         DEBUG (( DEBUG_ACCEPT,\r
-                  "ERROR - Socket is not listening!\r\n" ));\r
-        Status = EFI_NOT_STARTED;\r
-        pSocket->errno = EOPNOTSUPP;\r
+                  "ERROR - pSockAddr is NULL!\r\n" ));\r
+        Status = EFI_INVALID_PARAMETER;\r
+        pSocket->errno = EFAULT;\r
       }\r
       else {\r
         //\r
-        //  Determine if a socket is available\r
+        //  Synchronize with the socket layer\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
+        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
-            //  Update the socket state\r
+            //  Socket does not support listen\r
             //\r
-            pSocket->State = SOCKET_STATE_NO_PORTS;\r
+            pSocket->errno = EOPNOTSUPP;\r
+            Status = EFI_UNSUPPORTED;\r
           }\r
           else {\r
             //\r
-            //  Ports are available\r
-            //  No connection requests at this time\r
+            //  Socket supports listen, but not in listen state\r
             //\r
-            Status = EFI_NOT_READY;\r
-            pSocket->errno = EAGAIN;\r
+            pSocket->errno = EINVAL;\r
+            Status = EFI_NOT_STARTED;\r
           }\r
         }\r
         else {\r
-  \r
           //\r
-          //  Get the remote network address\r
+          //  Determine if a socket is available\r
           //\r
-          pNewSocket = pSocket->pFifoHead;\r
-          ASSERT ( NULL != pNewSocket );\r
-          switch ( pSocket->Domain ) {\r
-          default:\r
-            DEBUG (( DEBUG_ACCEPT,\r
-                      "ERROR - Invalid socket address family: %d\r\n",\r
-                      pSocket->Domain ));\r
-            Status = EFI_INVALID_PARAMETER;\r
-            pSocket->errno = EADDRNOTAVAIL;\r
-            break;\r
-\r
-          case AF_INET:\r
+          if ( 0 == pSocket->FifoDepth ) {\r
             //\r
-            //  Determine the connection point within the network stack\r
+            //  No connections available\r
+            //  Determine if any ports are available\r
             //\r
-            switch ( pSocket->Type ) {\r
-            default:\r
-              DEBUG (( DEBUG_ACCEPT,\r
-                        "ERROR - Invalid socket type: %d\r\n",\r
-                        pSocket->Type));\r
-              Status = EFI_INVALID_PARAMETER;\r
-              pSocket->errno = EADDRNOTAVAIL;\r
-              break;\r
-\r
-            case SOCK_STREAM:\r
-            case SOCK_SEQPACKET:\r
-              Status = EslTcpAccept4 ( pNewSocket,\r
-                                       pSockAddr,\r
-                                       pSockAddrLength );\r
-              break;\r
-\r
-  /*\r
-            case SOCK_DGRAM:\r
-              Status = UdpAccept4 ( pSocket );\r
-              break;\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
-            break;\r
-          }\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
+            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
-            //  Account for this socket\r
+            //  Attempt to accept the connection and\r
+            //  get the remote network address\r
             //\r
-            pSocket->FifoDepth -= 1;\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
-            //  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
+              //  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
-      //\r
-      //  Release the socket layer synchronization\r
-      //\r
-      RESTORE_TPL ( TplPrevious );\r
+        //\r
+        //  Release the socket layer synchronization\r
+        //\r
+        RESTORE_TPL ( TplPrevious );\r
+      }\r
     }\r
   }\r
 \r
@@ -410,10 +944,9 @@ EslSocketAccept (
     if ( NULL != pSocket ) {\r
       *pErrno = pSocket->errno;\r
     }\r
-    else\r
-    {\r
+    else {\r
       Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = EBADF;\r
+      *pErrno = ENOTSOCK;\r
     }\r
   }\r
   DBG_EXIT_STATUS ( Status );\r
@@ -422,9 +955,9 @@ EslSocketAccept (
 \r
 \r
 /**\r
-  Allocate and initialize a DT_SOCKET structure.\r
+  Allocate and initialize a ESL_SOCKET structure.\r
   \r
-  The ::SocketAllocate() function allocates a DT_SOCKET structure\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
@@ -436,11 +969,11 @@ EslSocketAccept (
                                 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 the DT_SOCKET structure address.\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 availabe to create\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
@@ -450,12 +983,12 @@ EFIAPI
 EslSocketAllocate (\r
   IN OUT EFI_HANDLE * pChildHandle,\r
   IN     UINTN DebugFlags,\r
-  IN OUT DT_SOCKET ** ppSocket\r
+  IN OUT ESL_SOCKET ** ppSocket\r
   )\r
 {\r
   UINTN LengthInBytes;\r
-  DT_LAYER * pLayer;\r
-  DT_SOCKET * pSocket;\r
+  ESL_LAYER * pLayer;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
 \r
@@ -465,12 +998,8 @@ EslSocketAllocate (
   //  Create a socket structure\r
   //\r
   LengthInBytes = sizeof ( *pSocket );\r
-  Status = gBS->AllocatePool (\r
-                  EfiRuntimeServicesData,\r
-                  LengthInBytes,\r
-                  (VOID **) &pSocket\r
-                  );\r
-  if ( !EFI_ERROR ( Status )) {\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
@@ -479,8 +1008,6 @@ EslSocketAllocate (
     //\r
     //  Initialize the socket protocol\r
     //\r
-    ZeroMem ( pSocket, LengthInBytes );\r
-\r
     pSocket->Signature = SOCKET_SIGNATURE;\r
     pSocket->SocketProtocol.pfnAccept = EslSocketAccept;\r
     pSocket->SocketProtocol.pfnBind = EslSocketBind;\r
@@ -494,9 +1021,9 @@ EslSocketAllocate (
     pSocket->SocketProtocol.pfnOptionSet = EslSocketOptionSet;\r
     pSocket->SocketProtocol.pfnPoll = EslSocketPoll;\r
     pSocket->SocketProtocol.pfnReceive = EslSocketReceive;\r
-    pSocket->SocketProtocol.pfnSend = EslSocketTransmit;\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
@@ -558,9 +1085,7 @@ EslSocketAllocate (
     }\r
   }\r
   else {\r
-    DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
-              "ERROR - Failed socket allocation, Status: %r\r\n",\r
-              Status ));\r
+    Status = EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
   //\r
@@ -574,11 +1099,13 @@ EslSocketAllocate (
 /**\r
   Bind a name to a socket.\r
 \r
-  The ::SocketBind routine connects a name to a socket on the local machine.  The\r
-  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html">POSIX</a>\r
-  documentation for the bind routine is available online for reference.\r
+  This routine calls the network specific layer to save the network\r
+  address of the local connection point.\r
 \r
-  @param [in] pSocketProtocol Address of the socket protocol structure.\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
 \r
   @param [in] pSockAddr Address of a sockaddr structure that contains the\r
                         connection point on the local machine.  An IPv4 address\r
@@ -590,7 +1117,7 @@ EslSocketAllocate (
                         number from the dynamic range.  Specifying a specific\r
                         port number causes the network layer to use that port.\r
 \r
-  @param [in] SockAddrLen   Specifies the length in bytes of the sockaddr structure.\r
+  @param [in] SockAddrLength  Specifies the length in bytes of the sockaddr structure.\r
 \r
   @param [out] pErrno   Address to receive the errno value upon completion.\r
 \r
@@ -600,12 +1127,18 @@ EslSocketAllocate (
 EFI_STATUS\r
 EslSocketBind (\r
   IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN const struct sockaddr * pSockAddr,\r
+  IN CONST struct sockaddr * pSockAddr,\r
   IN socklen_t SockAddrLength,\r
   OUT int * pErrno\r
   )\r
 {\r
-  DT_SOCKET * pSocket;\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
@@ -626,91 +1159,133 @@ EslSocketBind (
     //\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
-    else{\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
-      //  Validate the name length\r
+      //  Synchronize with the socket layer\r
       //\r
-      if (( SockAddrLength < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))\r
-        || ( pSockAddr->sa_len < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))) {\r
-        DEBUG (( DEBUG_BIND,\r
-                  "ERROR - Invalid bind name length: %d, sa_len: %d\r\n",\r
-                  SockAddrLength,\r
-                  pSockAddr->sa_len ));\r
-        Status = EFI_INVALID_PARAMETER;\r
-        pSocket->errno = EINVAL;\r
-      }\r
-      else {\r
-        //\r
-        //  Set the socket address length\r
-        //\r
-        if ( SockAddrLength > pSockAddr->sa_len ) {\r
-          SockAddrLength = pSockAddr->sa_len;\r
-        }\r
+      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
 \r
-        //\r
-        //  Synchronize with the socket layer\r
-        //\r
-        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\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
-        //  Validate the local address\r
+        //  Create the port\r
         //\r
-        switch ( pSockAddr->sa_family ) {\r
-        default:\r
-          DEBUG (( DEBUG_BIND,\r
-                    "ERROR - Invalid bind address family: %d\r\n",\r
-                    pSockAddr->sa_family ));\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EADDRNOTAVAIL;\r
-          break;\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
-        case AF_INET:\r
           //\r
-          //  Determine the connection point within the network stack\r
+          //  Open the port\r
           //\r
-          switch ( pSocket->Type ) {\r
-          default:\r
-            DEBUG (( DEBUG_BIND,\r
-                      "ERROR - Invalid socket type: %d\r\n",\r
-                      pSocket->Type));\r
-            Status = EFI_INVALID_PARAMETER;\r
-            pSocket->errno = EADDRNOTAVAIL;\r
-            break;\r
-\r
-          case SOCK_STREAM:\r
-          case SOCK_SEQPACKET:\r
-            Status = EslTcpBind4 ( pSocket,\r
-                                   pSockAddr,\r
-                                   SockAddrLength );\r
-            break;\r
-\r
-          case SOCK_DGRAM:\r
-            Status = EslUdpBind4 ( pSocket,\r
-                                   pSockAddr,\r
-                                   SockAddrLength );\r
-            break;\r
-          }\r
-          break;\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
-        //  Mark this socket as bound if successful\r
+        //  Set the next service\r
         //\r
-        if ( !EFI_ERROR ( Status )) {\r
-          pSocket->State = SOCKET_STATE_BOUND;\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
-        //  Release the socket layer synchronization\r
-        //\r
-        RESTORE_TPL ( TplPrevious );\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
@@ -721,10 +1296,9 @@ EslSocketBind (
     if ( NULL != pSocket ) {\r
       *pErrno = pSocket->errno;\r
     }\r
-    else\r
-    {\r
+    else {\r
       Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = EBADF;\r
+      *pErrno = ENOTSOCK;\r
     }\r
   }\r
   DBG_EXIT_STATUS ( Status );\r
@@ -733,47 +1307,114 @@ EslSocketBind (
 \r
 \r
 /**\r
-  Determine if the socket is closed\r
-\r
-  Reverses the operations of the ::SocketAllocate() routine.\r
+  Test the bind configuration.\r
 \r
-  @param [in] pSocketProtocol Address of the socket protocol structure.\r
-  @param [out] pErrno         Address to receive the errno value upon completion.\r
+  @param [in] pPort       Address of the ::ESL_PORT structure.\r
+  @param [in] ErrnoValue  errno value if test fails\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
+  @retval EFI_SUCCESS   The connection was successfully established.\r
+  @retval Others        The connection attempt failed.\r
 \r
-**/\r
+ **/\r
 EFI_STATUS\r
-EslSocketClosePoll (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN int * pErrno\r
+EslSocketBindTest (\r
+  IN ESL_PORT * pPort,\r
+  IN int ErrnoValue\r
   )\r
 {\r
-  int errno;\r
-  DT_LAYER * pLayer;\r
-  DT_SOCKET * pNextSocket;\r
-  DT_SOCKET * pSocket;\r
+  UINT8 * pBuffer;\r
+  VOID * pConfigData;\r
   EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Assume success\r
+  //  Locate the configuration data\r
   //\r
-  errno = 0;\r
-  Status = EFI_SUCCESS;\r
+  pBuffer = (UINT8 *)pPort;\r
+  pBuffer = &pBuffer [ pPort->pSocket->pApi->ConfigDataOffset ];\r
+  pConfigData = (VOID *)pBuffer;\r
 \r
   //\r
-  //  Synchronize with the socket layer\r
+  //  Attempt to use this configuration\r
   //\r
-  RAISE_TPL ( TplPrevious, TPL_SOCKETS );\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
-  //  Locate the socket\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\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
+**/\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
@@ -868,11 +1509,19 @@ EslSocketClosePoll (
 /**\r
   Start the close operation on the socket\r
 \r
-  Start closing the socket by closing all of the ports.  Upon\r
-  completion, the ::SocketPoll() routine finishes closing the\r
-  socket.\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
-  @param [in] pSocketProtocol Address of the socket protocol structure.\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
@@ -890,9 +1539,9 @@ EslSocketCloseStart (
   )\r
 {\r
   int errno;\r
-  DT_PORT * pNextPort;\r
-  DT_PORT * pPort;\r
-  DT_SOCKET * pSocket;\r
+  ESL_PORT * pNextPort;\r
+  ESL_PORT * pPort;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
 \r
@@ -928,9 +1577,9 @@ EslSocketCloseStart (
       //  Start closing the ports\r
       //\r
       pNextPort = pPort->pLinkSocket;\r
-      Status = pPort->pfnCloseStart ( pPort,\r
-                                      bCloseNow,\r
-                                      DEBUG_CLOSE | DEBUG_LISTEN | DEBUG_CONNECTION );\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
@@ -951,8 +1600,8 @@ EslSocketCloseStart (
     }\r
   }\r
   else {\r
-    Status = EFI_ALREADY_STARTED;\r
-    errno = EALREADY;\r
+    Status = EFI_NOT_READY;\r
+    errno = EAGAIN;\r
   }\r
 \r
   //\r
@@ -974,28 +1623,16 @@ EslSocketCloseStart (
 /**\r
   Connect to a remote system via the network.\r
 \r
-  The ::SocketConnect routine attempts to establish a connection to a\r
-  socket on the local or remote system using the specified address.\r
-  The POSIX\r
-  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html">connect</a>\r
-  documentation is available online.\r
-\r
-  There are three states associated with a connection:\r
-  <ul>\r
-    <li>Not connected</li>\r
-    <li>Connection in progress</li>\r
-    <li>Connected</li>\r
-  </ul>\r
-  In the "Not connected" state, calls to ::connect start the connection\r
-  processing and update the state to "Connection in progress".  During\r
-  the "Connection in progress" state, connect polls for connection completion\r
-  and moves the state to "Connected" after the connection is established.\r
-  Note that these states are only visible when the file descriptor is marked\r
-  with O_NONBLOCK.  Also, the POLL_WRITE bit is set when the connection\r
-  completes and may be used by poll or select as an indicator to call\r
-  connect again.\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
-  @param [in] pSocketProtocol Address of the socket protocol structure.\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
 \r
   @param [in] pSockAddr       Network address of the remote system.\r
     \r
@@ -1016,7 +1653,9 @@ EslSocketConnect (
   IN int * pErrno\r
   )\r
 {\r
-  DT_SOCKET * pSocket;\r
+  struct sockaddr_in6 LocalAddress;\r
+  ESL_PORT * pPort;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
   \r
@@ -1037,12 +1676,10 @@ EslSocketConnect (
     //\r
     //  Validate the name length\r
     //\r
-    if (( SockAddrLength < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))\r
-      || ( pSockAddr->sa_len < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))) {\r
+    if ( SockAddrLength < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data ))) {\r
       DEBUG (( DEBUG_CONNECT,\r
-                "ERROR - Invalid bind name length: %d, sa_len: %d\r\n",\r
-                SockAddrLength,\r
-                pSockAddr->sa_len ));\r
+                "ERROR - Invalid bind name length: %d\r\n",\r
+                SockAddrLength ));\r
       Status = EFI_INVALID_PARAMETER;\r
       pSocket->errno = EINVAL;\r
     }\r
@@ -1052,13 +1689,6 @@ EslSocketConnect (
       //\r
       pSocket->errno = 0;\r
 \r
-      //\r
-      //  Set the socket address length\r
-      //\r
-      if ( SockAddrLength > pSockAddr->sa_len ) {\r
-        SockAddrLength = pSockAddr->sa_len;\r
-      }\r
-\r
       //\r
       //  Synchronize with the socket layer\r
       //\r
@@ -1079,112 +1709,121 @@ EslSocketConnect (
       case SOCKET_STATE_NOT_CONFIGURED:\r
       case SOCKET_STATE_BOUND:\r
         //\r
-        //  Validate the local address\r
+        //  Validate the address length\r
         //\r
-        switch ( pSockAddr->sa_family ) {\r
-        default:\r
-          DEBUG (( DEBUG_CONNECT,\r
-                    "ERROR - Invalid bind address family: %d\r\n",\r
-                    pSockAddr->sa_family ));\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EADDRNOTAVAIL;\r
-          break;\r
-\r
-        case AF_INET:\r
+        if ( SockAddrLength >= pSocket->pApi->MinimumAddressLength ) {\r
           //\r
-          //  Determine the connection point within the network stack\r
+          //  Verify the API\r
           //\r
-          switch ( pSocket->Type ) {\r
-          default:\r
-            DEBUG (( DEBUG_CONNECT,\r
-                      "ERROR - Invalid socket type: %d\r\n",\r
-                      pSocket->Type));\r
-            Status = EFI_INVALID_PARAMETER;\r
-            pSocket->errno = EADDRNOTAVAIL;\r
-            break;\r
-\r
-          case SOCK_STREAM:\r
-          case SOCK_SEQPACKET:\r
+          if ( NULL == pSocket->pApi->pfnRemoteAddrSet ) {\r
             //\r
-            //  Start the connection processing\r
+            //  Already connected\r
             //\r
-            Status = EslTcpConnectStart4 ( pSocket,\r
-                                           pSockAddr,\r
-                                           SockAddrLength );\r
-\r
+            pSocket->errno = ENOTSUP;\r
+            Status = EFI_UNSUPPORTED;\r
+          }\r
+          else {\r
             //\r
-            //  Set the next state if connecting\r
+            //  Determine if BIND was already called\r
             //\r
-            if ( EFI_NOT_READY == Status ) {\r
-              pSocket->State = SOCKET_STATE_CONNECTING;\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
-            break;\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
-          case SOCK_DGRAM:\r
-            Status = EslUdpConnect4 ( pSocket,\r
-                                      pSockAddr,\r
-                                      SockAddrLength );\r
-            break;\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
-          break;\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
-        //  Validate the local address\r
+        //  Poll the network adapter\r
         //\r
-        switch ( pSockAddr->sa_family ) {\r
-        default:\r
-          DEBUG (( DEBUG_CONNECT,\r
-                    "ERROR - Invalid bind address family: %d\r\n",\r
-                    pSockAddr->sa_family ));\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EADDRNOTAVAIL;\r
-          break;\r
+        EslSocketRxPoll ( pSocket );\r
 \r
-        case AF_INET:\r
+        //\r
+        //  Poll for connection completion\r
+        //\r
+        if ( NULL == pSocket->pApi->pfnConnectPoll ) {\r
           //\r
-          //  Determine the connection point within the network stack\r
+          //  Already connected\r
           //\r
-          switch ( pSocket->Type ) {\r
-          default:\r
-            DEBUG (( DEBUG_CONNECT,\r
-                      "ERROR - Invalid socket type: %d\r\n",\r
-                      pSocket->Type));\r
-            Status = EFI_INVALID_PARAMETER;\r
-            pSocket->errno = EADDRNOTAVAIL;\r
-            break;\r
+          pSocket->errno = EISCONN;\r
+          Status = EFI_ALREADY_STARTED;\r
+        }\r
+        else {\r
+          Status = pSocket->pApi->pfnConnectPoll ( pSocket );\r
 \r
-          case SOCK_STREAM:\r
-          case SOCK_SEQPACKET:\r
-            //\r
-            //  Determine if the connection processing is completed\r
-            //\r
-            Status = EslTcpConnectPoll4 ( pSocket );\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_CONNECTED;\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_CONNECTED;\r
-              }\r
-              else {\r
-                pSocket->State = SOCKET_STATE_BOUND;\r
-              }\r
+              //\r
+              //  Start the receive operations\r
+              //\r
+              EslSocketRxStart ( pSocket->pPortList );\r
+            }\r
+            else {\r
+              pSocket->State = SOCKET_STATE_BOUND;\r
             }\r
-            break;\r
-\r
-          case SOCK_DGRAM:\r
-            //\r
-            //  Already connected\r
-            //\r
-            pSocket->errno = EISCONN;\r
-            Status = EFI_ALREADY_STARTED;\r
-            break;\r
           }\r
-          break;\r
         }\r
         break;\r
 \r
@@ -1211,15 +1850,14 @@ EslSocketConnect (
     if ( NULL != pSocket ) {\r
       *pErrno = pSocket->errno;\r
     }\r
-    else\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 = EBADF;\r
+      *pErrno = ENOTSOCK;\r
     }\r
   }\r
 \r
@@ -1232,98 +1870,130 @@ EslSocketConnect (
 \r
 \r
 /**\r
-  Creates a child handle and installs a protocol.\r
-  \r
-  The CreateChild() function installs a protocol on ChildHandle. \r
-  If pChildHandle is a pointer to NULL, then a new handle is created and returned in pChildHandle. \r
-  If pChildHandle is not a pointer to NULL, then the protocol installs on the existing pChildHandle.\r
+  Copy a fragmented buffer into a destination buffer.\r
 \r
-  @param [in] pThis        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
-  @param [in] pChildHandle Pointer to the handle of the child to create. If it is NULL,\r
-                           then a new handle is created. If it is a pointer to an existing UEFI handle, \r
-                           then the protocol is added to the existing UEFI handle.\r
+  This support routine copies a fragmented buffer to the caller specified buffer.\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 availabe to create\r
-                                the child\r
-  @retval other                 The child handle was not created\r
+  This routine is called by ::EslIp4Receive and ::EslUdp4Receive.\r
+\r
+  @param [in] FragmentCount   Number of fragments in the table\r
+\r
+  @param [in] pFragmentTable  Address of an EFI_IP4_FRAGMENT_DATA structure\r
+\r
+  @param [in] BufferLength    Length of the the buffer\r
+\r
+  @param [in] pBuffer         Address of a buffer to receive the data.\r
+\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
 **/\r
-EFI_STATUS\r
-EFIAPI\r
-EslSocketCreateChild (\r
-  IN     EFI_SERVICE_BINDING_PROTOCOL * pThis,\r
-  IN OUT EFI_HANDLE * pChildHandle\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
-  DT_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
+  size_t BytesToCopy;\r
+  UINT32 Fragment;\r
+  UINT8 * pBufferEnd;\r
+  UINT8 * pData;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Create a socket structure\r
+  //  Validate the IP and UDP structures are identical\r
   //\r
-  Status = EslSocketAllocate ( pChildHandle,\r
-                               DEBUG_SOCKET,\r
-                               &pSocket );\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
-  //  Return the operation status\r
+  //  Copy the received data\r
   //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\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
 /**\r
-  Destroys a child handle with a protocol installed on it.\r
-  \r
-  The DestroyChild() function does the opposite of CreateChild(). It removes a protocol \r
-  that was installed by CreateChild() from ChildHandle. If the removed protocol is the \r
-  last protocol on ChildHandle, then ChildHandle is destroyed.\r
+  Free the socket.\r
 \r
-  @param [in] pThis       Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
-  @param [in] ChildHandle Handle of the child to destroy\r
+  This routine frees the socket structure and handle resources.\r
 \r
-  @retval EFI_SUCCESS           The protocol was removed from ChildHandle.\r
-  @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.\r
-  @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.\r
-  @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle\r
-                                because its services are being used.\r
-  @retval other                 The child handle was not destroyed\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
-**/\r
+  @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
+  \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
+ **/\r
 EFI_STATUS\r
-EFIAPI\r
-EslSocketDestroyChild (\r
-  IN EFI_SERVICE_BINDING_PROTOCOL * pThis,\r
-  IN EFI_HANDLE ChildHandle\r
+EslSocketFree (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN int * pErrno\r
   )\r
 {\r
-  DT_LAYER * pLayer;\r
-  DT_SOCKET * pSocket;\r
-  DT_SOCKET * pSocketPrevious;\r
-  EFI_SOCKET_PROTOCOL * pSocketProtocol;\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
-  //  Locate the socket control structure\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
-  Status = gBS->OpenProtocol (\r
-                  ChildHandle,\r
-                  &gEfiSocketProtocolGuid,\r
-                  (VOID **)&pSocketProtocol,\r
-                  pLayer->ImageHandle,\r
-                  NULL,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-  if ( !EFI_ERROR ( Status )) {\r
+  if ( NULL != pSocketProtocol ) {\r
     pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
 \r
     //\r
@@ -1380,6 +2050,7 @@ EslSocketDestroyChild (
       //\r
       //  Remove the socket protocol\r
       //\r
+      ChildHandle = pSocket->SocketProtocol.SocketHandle;\r
       Status = gBS->UninstallMultipleProtocolInterfaces (\r
                 ChildHandle,\r
                 &gEfiSocketProtocolGuid,\r
@@ -1399,6 +2070,7 @@ EslSocketDestroyChild (
                     "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
@@ -1422,9 +2094,14 @@ EslSocketDestroyChild (
   }\r
   else {\r
     DEBUG (( DEBUG_ERROR,\r
-              "ERROR - Failed to open socket protocol on 0x%08x, Status; %r\r\n",\r
-              ChildHandle,\r
-              Status ));\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
@@ -1438,7 +2115,13 @@ EslSocketDestroyChild (
 /**\r
   Get the local address.\r
 \r
-  @param [in] pSocketProtocol Address of the socket protocol structure.\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
   \r
   @param [out] pAddress       Network address to receive the local system address\r
 \r
@@ -1457,7 +2140,9 @@ EslSocketGetLocalAddress (
   IN int * pErrno\r
   )\r
 {\r
-  DT_SOCKET * pSocket;\r
+  socklen_t LengthInBytes;\r
+  ESL_PORT * pPort;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
   \r
@@ -1476,77 +2161,75 @@ EslSocketGetLocalAddress (
     pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
 \r
     //\r
-    //  Verify the address buffer and length address\r
+    //  Verify the socket state\r
     //\r
-    if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r
+    EslSocketIsConfigured ( pSocket );\r
+    if ( pSocket->bAddressSet ) {\r
       //\r
-      //  Verify the socket state\r
+      //  Verify the address buffer and length address\r
       //\r
-      if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
-        //\r
-        //  Synchronize with the socket layer\r
-        //\r
-        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
+      if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r
         //\r
-        //  Validate the local address\r
+        //  Verify the API\r
         //\r
-        switch ( pSocket->Domain ) {\r
-        default:\r
-          DEBUG (( DEBUG_RX,\r
-                    "ERROR - Invalid socket address family: %d\r\n",\r
-                    pSocket->Domain ));\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EADDRNOTAVAIL;\r
-          break;\r
-\r
-        case AF_INET:\r
+        if ( NULL == pSocket->pApi->pfnLocalAddrGet ) {\r
+          Status = EFI_UNSUPPORTED;\r
+          pSocket->errno = ENOTSUP;\r
+        }\r
+        else {\r
           //\r
-          //  Determine the connection point within the network stack\r
+          //  Synchronize with the socket layer\r
           //\r
-          switch ( pSocket->Type ) {\r
-          default:\r
-            DEBUG (( DEBUG_RX,\r
-                      "ERROR - Invalid socket type: %d\r\n",\r
-                      pSocket->Type));\r
-            Status = EFI_INVALID_PARAMETER;\r
-            break;\r
-\r
-          case SOCK_STREAM:\r
-          case SOCK_SEQPACKET:\r
-            //\r
-            //  Get the local address\r
-            //\r
-            Status = EslTcpGetLocalAddress4 ( pSocket,\r
-                                              pAddress,\r
-                                              pAddressLength );\r
-            break;\r
+          RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
 \r
-          case SOCK_DGRAM:\r
+          //\r
+          //  Verify that there is just a single connection\r
+          //\r
+          pPort = pSocket->pPortList;\r
+          if ( NULL != pPort ) {\r
             //\r
-            //  Get the local address\r
+            //  Verify the address length\r
             //\r
-            Status = EslUdpGetLocalAddress4 ( pSocket,\r
-                                              pAddress,\r
-                                              pAddressLength );\r
-            break;\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
-          break;\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
-        //\r
-        //  Release the socket layer synchronization\r
-        //\r
-        RESTORE_TPL ( TplPrevious );\r
       }\r
       else {\r
-        pSocket->errno = ENOTCONN;\r
-        Status = EFI_NOT_STARTED;\r
+        pSocket->errno = EINVAL;\r
+        Status = EFI_INVALID_PARAMETER;\r
       }\r
     }\r
     else {\r
-      pSocket->errno = EINVAL;\r
-      Status = EFI_INVALID_PARAMETER;\r
+      //\r
+      //  Address not set\r
+      //\r
+      Status = EFI_NOT_STARTED;\r
+      pSocket->errno = EADDRNOTAVAIL;\r
     }\r
   }\r
   \r
@@ -1557,10 +2240,9 @@ EslSocketGetLocalAddress (
     if ( NULL != pSocket ) {\r
       *pErrno = pSocket->errno;\r
     }\r
-    else\r
-    {\r
+    else {\r
       Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = EBADF;\r
+      *pErrno = ENOTSOCK;\r
     }\r
   }\r
   DBG_EXIT_STATUS ( Status );\r
@@ -1571,7 +2253,13 @@ EslSocketGetLocalAddress (
 /**\r
   Get the peer address.\r
 \r
-  @param [in] pSocketProtocol Address of the socket protocol structure.\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
   \r
   @param [out] pAddress       Network address to receive the remote system address\r
 \r
@@ -1590,7 +2278,9 @@ EslSocketGetPeerAddress (
   IN int * pErrno\r
   )\r
 {\r
-  DT_SOCKET * pSocket;\r
+  socklen_t LengthInBytes;\r
+  ESL_PORT * pPort;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
   \r
@@ -1609,80 +2299,79 @@ EslSocketGetPeerAddress (
     pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
 \r
     //\r
-    //  Verify the address buffer and length address\r
+    //  Verify the socket state\r
     //\r
-    if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r
+    Status = EslSocketIsConfigured ( pSocket );\r
+    if ( !EFI_ERROR ( Status )) {\r
       //\r
-      //  Verify the socket state\r
+      //  Verify the API\r
       //\r
-      if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
+      if ( NULL == pSocket->pApi->pfnRemoteAddrGet ) {\r
+        Status = EFI_UNSUPPORTED;\r
+        pSocket->errno = ENOTSUP;\r
+      }\r
+      else {\r
         //\r
-        //  Synchronize with the socket layer\r
+        //  Verify the address buffer and length address\r
         //\r
-        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-        //\r
-        //  Validate the local address\r
-        //\r
-        switch ( pSocket->Domain ) {\r
-        default:\r
-          DEBUG (( DEBUG_RX,\r
-                    "ERROR - Invalid socket address family: %d\r\n",\r
-                    pSocket->Domain ));\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EADDRNOTAVAIL;\r
-          break;\r
-\r
-        case AF_INET:\r
+        if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r
           //\r
-          //  Determine the connection point within the network stack\r
+          //  Verify the socket state\r
           //\r
-          switch ( pSocket->Type ) {\r
-          default:\r
-            DEBUG (( DEBUG_RX,\r
-                      "ERROR - Invalid socket type: %d\r\n",\r
-                      pSocket->Type));\r
-            Status = EFI_INVALID_PARAMETER;\r
-            break;\r
+          if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
+            //\r
+            //  Synchronize with the socket layer\r
+            //\r
+            RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
 \r
-          case SOCK_STREAM:\r
-          case SOCK_SEQPACKET:\r
             //\r
-            //  Verify the port state\r
+            //  Verify that there is just a single connection\r
             //\r
-            Status = EslTcpGetRemoteAddress4 ( pSocket,\r
-                                               pAddress,\r
-                                               pAddressLength );\r
-            break;\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
-          case SOCK_DGRAM:\r
             //\r
-            //  Verify the port state\r
+            //  Release the socket layer synchronization\r
             //\r
-            Status = EslUdpGetRemoteAddress4 ( pSocket,\r
-                                               pAddress,\r
-                                               pAddressLength );\r
-            break;\r
+            RESTORE_TPL ( TplPrevious );\r
+          }\r
+          else {\r
+            pSocket->errno = ENOTCONN;\r
+            Status = EFI_NOT_STARTED;\r
           }\r
-          break;\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
+        else {\r
+          pSocket->errno = EINVAL;\r
+          Status = EFI_INVALID_PARAMETER;\r
+        }\r
       }\r
     }\r
-    else {\r
-      pSocket->errno = EINVAL;\r
-      Status = EFI_INVALID_PARAMETER;\r
-    }\r
   }\r
-  \r
+\r
   //\r
   //  Return the operation status\r
   //\r
@@ -1690,10 +2379,9 @@ EslSocketGetPeerAddress (
     if ( NULL != pSocket ) {\r
       *pErrno = pSocket->errno;\r
     }\r
-    else\r
-    {\r
+    else {\r
       Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = EBADF;\r
+      *pErrno = ENOTSOCK;\r
     }\r
   }\r
   DBG_EXIT_STATUS ( Status );\r
@@ -1702,39 +2390,35 @@ EslSocketGetPeerAddress (
 \r
 \r
 /**\r
-  Establish the known port to listen for network connections.\r
+  Free the ESL_IO_MGMT event and structure\r
 \r
-  The ::SocketListen routine places the port into a state that enables connection\r
-  attempts.  Connections are placed into FIFO order in a queue to be serviced\r
-  by the application.  The application calls the ::SocketAccept routine to remove\r
-  the next connection from the queue and get the associated socket.  The\r
-  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html">POSIX</a>\r
-  documentation for the listen routine is available online for reference.\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
-  @param [in] pSocketProtocol Address of the socket protocol structure.\r
-\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
+  See the \ref TransmitEngine section.\r
 \r
-  @param [out] pErrno         Address to receive the errno value upon completion.\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 - Socket successfully created\r
-  @retval Other - Failed to enable the socket for listen\r
+  @retval EFI_SUCCESS - The structures were properly initialized\r
 \r
 **/\r
 EFI_STATUS\r
-EslSocketListen (\r
-  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
-  IN INT32 Backlog,\r
-  OUT int * pErrno\r
+EslSocketIoFree (\r
+  IN ESL_PORT * pPort,\r
+  IN ESL_IO_MGMT ** ppFreeQueue,\r
+  IN UINTN DebugFlags,\r
+  IN CHAR8 * pEventName\r
   )\r
 {\r
-  DT_SOCKET * pSocket;\r
+  UINT8 * pBuffer;\r
+  EFI_EVENT * pEvent;\r
+  ESL_IO_MGMT * pIo;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
-  EFI_STATUS TempStatus;\r
-  EFI_TPL TplPrevious;\r
 \r
   DBG_ENTER ( );\r
 \r
@@ -1744,969 +2428,2889 @@ EslSocketListen (
   Status = EFI_SUCCESS;\r
 \r
   //\r
-  //  Validate the socket\r
+  //  Walk the list of IO structures\r
   //\r
-  pSocket = NULL;\r
-  if ( NULL != pSocketProtocol ) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
+  pSocket = pPort->pSocket;\r
+  while ( *ppFreeQueue ) {\r
     //\r
-    //  Assume success\r
+    //  Free the event for this structure\r
     //\r
-    pSocket->Status = EFI_SUCCESS;\r
-    pSocket->errno = 0;\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
-    //  Verify that the bind operation was successful\r
+    //  Remove this structure from the queue\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
-                                  TplPrevious,\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
-        //  Validate the local address\r
-        //\r
-        switch ( pSocket->Domain ) {\r
-        default:\r
-          DEBUG (( DEBUG_BIND,\r
-                    "ERROR - Invalid socket address family: %d\r\n",\r
-                    pSocket->Domain ));\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EADDRNOTAVAIL;\r
-          break;\r
-\r
-        case AF_INET:\r
-          //\r
-          //  Determine the connection point within the network stack\r
-          //\r
-          switch ( pSocket->Type ) {\r
-          default:\r
-            DEBUG (( DEBUG_BIND,\r
-                      "ERROR - Invalid socket type: %d\r\n",\r
-                      pSocket->Type));\r
-            Status = EFI_INVALID_PARAMETER;\r
-            pSocket->errno = EADDRNOTAVAIL;\r
-            break;\r
-\r
-          case SOCK_STREAM:\r
-          case SOCK_SEQPACKET:\r
-            Status = EslTcpListen4 ( pSocket );\r
-            break;\r
-\r
-/*\r
-          case SOCK_DGRAM:\r
-            Status = UdpListen4 ( pSocket );\r
-            break;\r
-*/\r
-          }\r
-          break;\r
-        }\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
-        }\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 = EDESTADDRREQ;\r
-    }\r
+    *ppFreeQueue = pIo->pNext;\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
-      Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = EBADF;\r
-    }\r
-  }\r
   DBG_EXIT_STATUS ( Status );\r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Get the socket options\r
+  Initialize the ESL_IO_MGMT structures\r
 \r
-  Retrieve the socket options one at a time by name.  The\r
-  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html">POSIX</a>\r
-  documentation is available online.\r
+  This support routine initializes the ESL_IO_MGMT structure and\r
+  places them on to a free list.\r
 \r
-  @param [in] pSocketProtocol   Address of the 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
+  This routine is called by ::EslSocketPortAllocate routines to prepare\r
+  the transmit engines.  See the \ref TransmitEngine section.\r
 \r
-  @retval EFI_SUCCESS - Socket data successfully received\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
- **/\r
+  @retval EFI_SUCCESS - The structures were properly initialized\r
+\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
+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
-  int errno;\r
-  socklen_t LengthInBytes;\r
-  socklen_t MaxBytes;\r
-  UINT8 * pOptionData;\r
-  DT_SOCKET * pSocket;\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 failure\r
+  //  Assume success\r
   //\r
-  errno = EINVAL;\r
-  Status = EFI_INVALID_PARAMETER;\r
+  Status = EFI_SUCCESS;\r
 \r
   //\r
-  //  Validate the socket\r
+  //  Walk the list of IO structures\r
   //\r
-  pSocket = NULL;\r
-  if (( NULL != pSocketProtocol )\r
-    && ( NULL != pOptionValue )\r
-    && ( NULL != pOptionLength )) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-    LengthInBytes = 0;\r
-    MaxBytes = *pOptionLength;\r
-    pOptionData = NULL;\r
-    switch ( level ) {\r
-    default:\r
-      //\r
-      //  Protocol level not supported\r
-      //\r
-      errno = ENOTSUP;\r
-      Status = EFI_UNSUPPORTED;\r
-      break;\r
-\r
-    case SOL_SOCKET:\r
-      switch ( OptionName ) {\r
-      default:\r
-        //\r
-        //  Option not supported\r
-        //\r
-        errno = ENOTSUP;\r
-        Status = EFI_UNSUPPORTED;\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 transmit buffer size\r
-        //\r
-        pOptionData = (UINT8 *)&pSocket->MaxRxBuf;\r
-        LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r
-        break;\r
-\r
-      case SO_SNDBUF:\r
-        //\r
-        //  Return the maximum transmit buffer size\r
-        //\r
-        pOptionData = (UINT8 *)&pSocket->MaxTxBuf;\r
-        LengthInBytes = sizeof ( pSocket->MaxTxBuf );\r
-        break;\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
-      case SO_TYPE:\r
-        //\r
-        //  Return the socket type\r
-        //\r
-        pOptionData = (UINT8 *)&pSocket->Type;\r
-        LengthInBytes = sizeof ( pSocket->Type );\r
-        break;\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
-    //  Return the option length\r
+    //  Add this structure to the queue\r
     //\r
-    *pOptionLength = LengthInBytes;\r
+    pIo->pNext = *ppFreeQueue;\r
+    *ppFreeQueue = pIo;\r
 \r
     //\r
-    //  Return the option value\r
+    //  Set the next structure\r
     //\r
-    if ( NULL != pOptionData ) {\r
-      //\r
-      //  Silently truncate the value length\r
-      //\r
-      if ( LengthInBytes > MaxBytes ) {\r
-        LengthInBytes = MaxBytes;\r
-      }\r
-      CopyMem ( pOptionValue, pOptionData, LengthInBytes );\r
-      errno = 0;\r
-      Status = EFI_SUCCESS;\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
-  if ( NULL != pErrno ) {\r
-    *pErrno = errno;\r
-  }\r
   DBG_EXIT_STATUS ( Status );\r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Set the socket options\r
+  Determine if the socket is configured\r
 \r
-  Adjust the socket options one at a time by name.  The\r
-  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html">POSIX</a>\r
-  documentation is available online.\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] pSocketProtocol Address of the 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
+  @param [in] pSocket       Address of an ::ESL_SOCKET structure\r
 \r
-  @retval EFI_SUCCESS - Socket data successfully received\r
+  @retval EFI_SUCCESS - The socket is configured\r
 \r
- **/\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
+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
+/**\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
+\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
+\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
+**/\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
+/**\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
+ **/\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
-  UINT8 * pOptionData;\r
-  DT_SOCKET * pSocket;\r
+  socklen_t MaxBytes;\r
+  CONST UINT8 * pOptionData;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
-  \r
+\r
   DBG_ENTER ( );\r
-  \r
+\r
   //\r
   //  Assume failure\r
   //\r
   errno = EINVAL;\r
   Status = EFI_INVALID_PARAMETER;\r
-  \r
+\r
   //\r
   //  Validate the socket\r
   //\r
   pSocket = NULL;\r
-  if (( NULL != pSocketProtocol )\r
-    && ( NULL != pOptionValue )) {\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
-      //  Protocol level not supported\r
+      //  See if the protocol will handle the option\r
       //\r
-      errno = ENOTSUP;\r
-      Status = EFI_UNSUPPORTED;\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
+\r
     case SOL_SOCKET:\r
       switch ( OptionName ) {\r
       default:\r
         //\r
-        //  Option not supported\r
+        //  Socket option not supported\r
         //\r
-        errno = ENOTSUP;\r
-        Status = EFI_UNSUPPORTED;\r
+        DEBUG (( DEBUG_INFO | DEBUG_OPTION, "ERROR - Invalid socket option!\r\n" ));\r
+        errno = EINVAL;\r
+        Status = EFI_INVALID_PARAMETER;\r
         break;\r
-  \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 = (UINT8 *)&pSocket->RxTimeout;\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
+/**\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
+ **/\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
+/**\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
+ **/\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
+/**\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
+ **/\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
+/**\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
+\r
+  @param [in] Events    Events of interest for this socket\r
+\r
+  @param [in] pEvents   Address to receive the detected events\r
+\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
+ **/\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
+\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
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the detected events\r
+  //\r
+  *pEvents = DetectedEvents & ( Events\r
+                              | POLLERR\r
+                              | POLLHUP\r
+                              | POLLNVAL );\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
+/**\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
+ **/\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
+/**\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
+**/\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
+/**\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
+\r
+  @param [in] pPort     Address of an ::ESL_PORT structure.\r
+\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
+  //\r
+  //  Update the port state\r
+  //\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
+  //\r
+  //  Shutdown the receive operation on the port\r
+  //\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
+  //\r
+  //  Determine if the receive operation is pending\r
+  //\r
+  Status = EslSocketPortCloseRxDone ( pPort );\r
+  DBG_EXIT_STATUS ( Status );\r
+}\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
+**/\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
+/**\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
+**/\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
+/**\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
-      case SO_RCVBUF:\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
-        //  Return the maximum transmit buffer size\r
+        //  The receive operation is complete\r
+        //  Update the port state\r
         //\r
-        pOptionData = (UINT8 *)&pSocket->MaxRxBuf;\r
-        LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r
-        break;\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
-      case SO_SNDBUF:\r
         //\r
-        //  Send buffer size\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
-        //  Return the maximum transmit buffer size\r
+        //  Display the pending normal transmit packets\r
         //\r
-        pOptionData = (UINT8 *)&pSocket->MaxTxBuf;\r
-        LengthInBytes = sizeof ( pSocket->MaxTxBuf );\r
-        break;\r
-      }\r
-      break;\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
-    //\r
-    //  Validate the option length\r
-    //\r
-    if ( LengthInBytes <= OptionLength ) {\r
-      //\r
-      //  Set the option value\r
-      //\r
-      if ( NULL != pOptionData ) {\r
-        CopyMem ( pOptionData, pOptionValue, LengthInBytes );\r
-        errno = 0;\r
-        Status = EFI_SUCCESS;\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
   //\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
 /**\r
-  Allocate a packet for a receive or transmit operation\r
+  Receive data from a network connection.\r
 \r
-  @param [in] ppPacket      Address to receive the DT_PACKET structure\r
-  @param [in] LengthInBytes Length of the packet structure\r
-  @param [in] DebugFlags    Flags for debug messages\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
-  @retval EFI_SUCCESS - The packet was allocated successfully\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
+  \r
+  @param [in] Flags           Message control flags\r
+  \r
+  @param [in] BufferLength    Length of the the buffer\r
+  \r
+  @param [in] pBuffer         Address of a buffer to receive the data.\r
+  \r
+  @param [in] pDataLength     Number of received data bytes in the buffer.\r
+\r
+  @param [out] pAddress       Network address to receive the remote system address\r
+\r
+  @param [in,out] pAddressLength  Length of the remote network address structure\r
+\r
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS - Socket data successfully received\r
 \r
  **/\r
 EFI_STATUS\r
-EslSocketPacketAllocate (\r
-  IN DT_PACKET ** ppPacket,\r
-  IN size_t LengthInBytes,\r
-  IN UINTN DebugFlags\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
-  DT_PACKET * pPacket;\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
-  //  Allocate a packet structure\r
+  //  Assume success\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 | DEBUG_INIT,\r
-              "0x%08x: Allocate pPacket, %d bytes\r\n",\r
-              pPacket,\r
-              LengthInBytes ));\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
+  Status = EFI_SUCCESS;\r
 \r
   //\r
-  //  Return the packet\r
+  //  Validate the socket\r
   //\r
-  *ppPacket = pPacket;\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
 /**\r
-  Free a packet used for receive or transmit operation\r
+  Cancel the receive operations\r
 \r
-  @param [in] pPacket     Address of the DT_PACKET structure\r
-  @param [in] DebugFlags  Flags for debug messages\r
+  This routine cancels a pending receive operation.\r
+  See the \ref ReceiveEngine section.\r
 \r
-  @retval EFI_SUCCESS - The packet was allocated successfully\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
  **/\r
-EFI_STATUS\r
-EslSocketPacketFree (\r
-  IN DT_PACKET * pPacket,\r
-  IN UINTN DebugFlags\r
+VOID\r
+EslSocketRxCancel (\r
+  IN ESL_PORT * pPort,\r
+  IN ESL_IO_MGMT * pIo\r
   )\r
 {\r
-  UINTN LengthInBytes;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Allocate a packet structure\r
+  //  Cancel the outstanding receive\r
   //\r
-  LengthInBytes = pPacket->PacketSize;\r
-  Status = gBS->FreePool ( pPacket );\r
+  Status = pPort->pfnRxCancel ( pPort->pProtocol.v,\r
+                                &pIo->Token );\r
   if ( !EFI_ERROR ( Status )) {\r
-    DEBUG (( DebugFlags | DEBUG_POOL,\r
-              "0x%08x: Free pPacket, %d bytes\r\n",\r
-              pPacket,\r
-              LengthInBytes ));\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 (( DebugFlags | DEBUG_POOL | DEBUG_INFO,\r
-              "ERROR - Failed to free packet 0x%08x, Status: %r\r\n",\r
-              pPacket,\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
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
+  DBG_EXIT ( );\r
 }\r
 \r
 \r
 /**\r
-  Poll a socket for pending activity.\r
+  Process the receive completion\r
 \r
-  The SocketPoll routine checks a socket for pending activity associated\r
-  with the event mask.  Activity is returned in the detected event buffer.\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
-  @param [in] pSocketProtocol Address of the socket protocol structure.\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] Events    Events of interest for this socket\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
-  @param [in] pEvents   Address to receive the detected events\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
-  @param [out] pErrno   Address to receive the errno value upon completion.\r
+  DBG_ENTER ( );\r
+  VERIFY_AT_TPL ( TPL_SOCKETS );\r
 \r
-  @retval EFI_SUCCESS - Socket successfully polled\r
-  @retval EFI_INVALID_PARAMETER - When pEvents is NULL\r
+  //\r
+  //  Locate the active receive packet\r
+  //\r
+  pPacket = pIo->pPacket;\r
+  pPort = pIo->pPort;\r
+  pSocket = pPort->pSocket;\r
 \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
-  DT_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
-  short ValidEvents;\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
-  DEBUG (( DEBUG_POLL, "Entering SocketPoll\r\n" ));\r
+  //\r
+  //  Free the IO structure\r
+  //\r
+  pIo->pNext = pPort->pRxFree;\r
+  pPort->pRxFree = pIo;\r
 \r
   //\r
-  //  Assume success\r
+  //            pRxOobPacketListHead              pRxOobPacketListTail\r
+  //                      |                                 |\r
+  //                      V                                 V\r
+  //               +------------+   +------------+   +------------+   \r
+  //  Urgent Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL\r
+  //               +------------+   +------------+   +------------+   \r
   //\r
-  Status = EFI_SUCCESS;\r
-  DetectedEvents = 0;\r
-  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-  pSocket->errno = 0;\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
-  //  Verify the socket state\r
+  //  Determine if this receive was successful\r
   //\r
-  if ( !pSocket->bConfigured ) {\r
+  if (( !EFI_ERROR ( Status ))\r
+    && ( PORT_STATE_CLOSE_STARTED > pPort->State )\r
+    && ( !pSocket->bRxDisable )) {\r
     //\r
-    //  Synchronize with the socket layer\r
+    //  Account for the received data\r
     //\r
-    RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+    *pRxBytes += LengthInBytes;\r
 \r
     //\r
-    //  Validate the local address\r
+    //  Log the received data\r
     //\r
-    switch ( pSocket->Domain ) {\r
-    default:\r
-      DEBUG (( DEBUG_RX,\r
-                "ERROR - Invalid socket address family: %d\r\n",\r
-                pSocket->Domain ));\r
-      Status = EFI_INVALID_PARAMETER;\r
-      pSocket->errno = EADDRNOTAVAIL;\r
-      break;\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
-    case AF_INET:\r
-      //\r
-      //  Determine the connection point within the network stack\r
-      //\r
-      switch ( pSocket->Type ) {\r
-      default:\r
-        DEBUG (( DEBUG_RX,\r
-                  "ERROR - Invalid socket type: %d\r\n",\r
-                  pSocket->Type));\r
-        Status = EFI_INVALID_PARAMETER;\r
-        pSocket->errno = EADDRNOTAVAIL;\r
-        break;\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
-      case SOCK_STREAM:\r
-      case SOCK_SEQPACKET:\r
-        //\r
-        //  Verify the port state\r
-        //\r
-        Status = EslTcpSocketIsConfigured4 ( pSocket );\r
-        break;\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
-      case SOCK_DGRAM:\r
-        //\r
-        //  Verify the port state\r
-        //\r
-        Status = EslUdpSocketIsConfigured4 ( pSocket );\r
-        break;\r
-      }\r
-      break;\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
-    //  Release the socket layer synchronization\r
+    //  Receive error, free the packet save the error\r
     //\r
-    RESTORE_TPL ( TplPrevious );\r
-  }\r
-  if ( !EFI_ERROR ( Status )) {\r
+    EslSocketPacketFree ( pPacket, DEBUG_RX );\r
+    if ( !EFI_ERROR ( pSocket->RxError )) {\r
+      pSocket->RxError = Status;\r
+    }\r
+\r
     //\r
-    //  Check for invalid events\r
+    //  Update the port state\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
+    if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {\r
+      if ( PORT_STATE_CLOSE_DONE == pPort->State ) {\r
+        EslSocketPortCloseRxDone ( pPort );\r
+      }\r
     }\r
     else {\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
+      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
-      //\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
+  DBG_EXIT ( );\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
+  Poll a socket for pending receive activity.\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
+  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
-      //\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
+  The ::EslSocketPoll, ::EslSocketReceive and ::EslSocketTransmit\r
+  routines call this routine when there is nothing to do.\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
+  @param [in] pSocket   Address of an ::EFI_SOCKET structure.\r
 \r
-      //\r
-      //  Handle the transmit error\r
-      //\r
-      if ( EFI_ERROR ( pSocket->TxError )) {\r
-        DetectedEvents |= POLLERR;\r
-      }\r
-    }\r
-  }\r
+ **/\r
+VOID\r
+EslSocketRxPoll (\r
+  IN ESL_SOCKET * pSocket\r
+  )\r
+{\r
+  ESL_PORT * pPort;\r
 \r
-  //\r
-  //  Return the detected events\r
-  //\r
-  *pEvents = DetectedEvents & ( Events\r
-                              | POLLERR\r
-                              | POLLHUP\r
-                              | POLLNVAL );\r
+  DEBUG (( DEBUG_POLL, "Entering EslSocketRxPoll\r\n" ));\r
 \r
   //\r
-  //  Return the operation status\r
+  //  Increase the network performance by extending the\r
+  //  polling (idle) loop down into the LAN driver\r
   //\r
-  DEBUG (( DEBUG_POLL, "Exiting SocketPoll, Status: %r\r\n", Status ));\r
-  return Status;\r
-}\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
-  Receive data from a network connection.\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
-  @param [in] pSocketProtocol Address of the socket protocol structure.\r
-  \r
-  @param [in] Flags           Message control flags\r
-  \r
-  @param [in] BufferLength    Length of the the buffer\r
-  \r
-  @param [in] pBuffer         Address of a buffer to receive the data.\r
-  \r
-  @param [in] pDataLength     Number of received data bytes in the buffer.\r
 \r
-  @param [out] pAddress       Network address to receive the remote system address\r
+/**\r
+  Start a receive operation\r
 \r
-  @param [in,out] pAddressLength  Length of the remote network address structure\r
+  This routine posts a receive buffer to the network adapter.\r
+  See the \ref ReceiveEngine section.\r
 \r
-  @param [out] pErrno         Address to receive the errno value upon completion.\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 recevie 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
-  @retval EFI_SUCCESS - Socket data successfully received\r
+  @param [in] pPort       Address of an ::ESL_PORT structure.\r
 \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
+VOID\r
+EslSocketRxStart (\r
+  IN ESL_PORT * pPort\r
   )\r
 {\r
-  DT_SOCKET * pSocket;\r
+  UINT8 * pBuffer;\r
+  ESL_IO_MGMT * pIo;\r
+  ESL_PACKET * pPacket;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Assume success\r
+  //  Determine if a receive is already pending\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
+  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
-      //  Verify the socket state\r
+      //  Start all of the pending receive operations\r
       //\r
-      if ( !pSocket->bConfigured ) {\r
-        //\r
-        //  Synchronize with the socket layer\r
-        //\r
-        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
+      while ( NULL != pPort->pRxFree ) {\r
         //\r
-        //  Validate the local address\r
+        //  Determine if there are any free packets\r
         //\r
-        switch ( pSocket->Domain ) {\r
-        default:\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
-                    "ERROR - Invalid socket address family: %d\r\n",\r
-                    pSocket->Domain ));\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EADDRNOTAVAIL;\r
-          break;\r
-\r
-        case AF_INET:\r
+                    "0x%08x: Port removed packet 0x%08x from free list\r\n",\r
+                    pPort,\r
+                    pPacket ));\r
+        }\r
+        else {\r
           //\r
-          //  Determine the connection point within the network stack\r
+          //  Allocate a packet structure\r
           //\r
-          switch ( pSocket->Type ) {\r
-          default:\r
-            DEBUG (( DEBUG_RX,\r
-                      "ERROR - Invalid socket type: %d\r\n",\r
-                      pSocket->Type));\r
-            Status = EFI_INVALID_PARAMETER;\r
-            break;\r
-\r
-          case SOCK_STREAM:\r
-          case SOCK_SEQPACKET:\r
-            //\r
-            //  Verify the port state\r
-            //\r
-            Status = EslTcpSocketIsConfigured4 ( pSocket );\r
-            break;\r
-\r
-          case SOCK_DGRAM:\r
-            //\r
-            //  Verify the port state\r
-            //\r
-            Status = EslUdpSocketIsConfigured4 ( pSocket );\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
-          break;\r
         }\r
 \r
         //\r
-        //  Release the socket layer synchronization\r
+        //  Connect the IO and packet structures\r
         //\r
-        RESTORE_TPL ( TplPrevious );\r
+        pIo = pPort->pRxFree;\r
+        pIo->pPacket = pPacket;\r
 \r
         //\r
-        //  Set errno if a failure occurs\r
+        //  Eliminate the need for IP4 and UDP4 specific routines by\r
+        //  clearing the RX data pointer here.\r
         //\r
-        if ( EFI_ERROR ( Status )) {\r
-          pSocket->errno = EADDRNOTAVAIL;\r
-        }\r
-      }\r
-      if ( !EFI_ERROR ( Status )) {\r
+        //  No driver buffer for this packet\r
         //\r
-        //  Validate the buffer length\r
+        //    +--------------------+\r
+        //    | ESL_IO_MGMT        |\r
+        //    |                    |\r
+        //    |    +---------------+\r
+        //    |    | Token         |\r
+        //    |    |        RxData --> NULL\r
+        //    +----+---------------+\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
+        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
-        else{\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
-          //  Synchronize with the socket layer\r
+          //  Allocate the receive control structure\r
           //\r
-          RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
+          pPort->pRxFree = pIo->pNext;\r
+          \r
           //\r
-          //  Validate the local address\r
+          //  Mark this receive as pending\r
           //\r
-          switch ( pSocket->Domain ) {\r
-          default:\r
-            DEBUG (( DEBUG_RX,\r
-                      "ERROR - Invalid socket address family: %d\r\n",\r
-                      pSocket->Domain ));\r
-            Status = EFI_INVALID_PARAMETER;\r
-            pSocket->errno = EADDRNOTAVAIL;\r
-            break;\r
-\r
-          case AF_INET:\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
-            //  Determine the connection point within the network stack\r
+            //  Save the error status\r
             //\r
-            switch ( pSocket->Type ) {\r
-            default:\r
-              DEBUG (( DEBUG_RX,\r
-                        "ERROR - Invalid socket type: %d\r\n",\r
-                        pSocket->Type));\r
-              Status = EFI_INVALID_PARAMETER;\r
-              pSocket->errno = EADDRNOTAVAIL;\r
-              break;\r
-\r
-            case SOCK_STREAM:\r
-            case SOCK_SEQPACKET:\r
-              Status = EslTcpReceive4 ( pSocket,\r
-                                        Flags,\r
-                                        BufferLength,\r
-                                        pBuffer,\r
-                                        pDataLength,\r
-                                        pAddress,\r
-                                        pAddressLength );\r
-              break;\r
-\r
-            case SOCK_DGRAM:\r
-              Status = EslUdpReceive4 ( pSocket,\r
-                                        Flags,\r
-                                        BufferLength,\r
-                                        pBuffer,\r
-                                        pDataLength,\r
-                                        pAddress,\r
-                                        pAddressLength);\r
-              break;\r
-            }\r
-            break;\r
+            pSocket->RxError = Status;\r
           }\r
 \r
           //\r
-          //  Release the socket layer synchronization\r
+          //  Free the packet\r
           //\r
-          RESTORE_TPL ( TplPrevious );\r
+          pIo->pPacket = NULL;\r
+          pPacket->pNext = pSocket->pRxFree;\r
+          pSocket->pRxFree = pPacket;\r
+          break;\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
-    {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = EBADF;\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
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\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
 /**\r
   Shutdown the socket receive and transmit operations\r
 \r
-  The SocketShutdown routine stops the socket receive and transmit\r
-  operations.\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
-  @param [in] pSocketProtocol Address of the socket protocol structure.\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
   \r
   @param [in] How             Which operations to stop\r
   \r
@@ -2722,7 +5326,9 @@ EslSocketShutdown (
   IN int * pErrno\r
   )\r
 {\r
-  DT_SOCKET * pSocket;\r
+  ESL_IO_MGMT * pIo;\r
+  ESL_PORT * pPort;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
   \r
@@ -2768,47 +5374,29 @@ EslSocketShutdown (
         }\r
 \r
         //\r
-        //  Validate the local address\r
+        //  Cancel the pending receive operations\r
         //\r
-        switch ( pSocket->Domain ) {\r
-        default:\r
-          DEBUG (( DEBUG_RX,\r
-                    "ERROR - Invalid socket address family: %d\r\n",\r
-                    pSocket->Domain ));\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EADDRNOTAVAIL;\r
-          break;\r
-        \r
-        case AF_INET:\r
+        if ( pSocket->bRxDisable ) {\r
           //\r
-          //  Determine the connection point within the network stack\r
+          //  Walk the list of ports\r
           //\r
-          switch ( pSocket->Type ) {\r
-          default:\r
-            DEBUG (( DEBUG_RX,\r
-                      "ERROR - Invalid socket type: %d\r\n",\r
-                      pSocket->Type));\r
-            Status = EFI_INVALID_PARAMETER;\r
-            break;\r
-        \r
-          case SOCK_STREAM:\r
-          case SOCK_SEQPACKET:\r
+          pPort = pSocket->pPortList;\r
+          while ( NULL != pPort ) {\r
             //\r
-            //  Cancel the pending receive operation\r
+            //  Walk the list of active receive operations\r
             //\r
-            Status = EslTcpRxCancel4 ( pSocket );\r
-            break;\r
-        \r
-          case SOCK_DGRAM:\r
+            pIo = pPort->pRxActive;\r
+            while ( NULL != pIo ) {\r
+              EslSocketRxCancel ( pPort, pIo );\r
+            }\r
+\r
             //\r
-            //  Cancel the pending receive operation\r
+            //  Set the next port\r
             //\r
-            Status = EslUdpRxCancel4 ( pSocket );\r
-            break;\r
+            pPort = pPort->pLinkSocket;\r
           }\r
-          break;\r
         }\r
-        \r
+\r
         //\r
         //  Release the socket layer synchronization\r
         //\r
@@ -2816,18 +5404,18 @@ EslSocketShutdown (
       }\r
       else {\r
         //\r
-        //  The socket is not connected\r
+        //  Invalid How value\r
         //\r
-        pSocket->errno = ENOTCONN;\r
-        Status = EFI_NOT_STARTED;\r
+        pSocket->errno = EINVAL;\r
+        Status = EFI_INVALID_PARAMETER;\r
       }\r
     }\r
     else {\r
       //\r
-      //  Invalid How value\r
+      //  The socket is not connected\r
       //\r
-      pSocket->errno = EINVAL;\r
-      Status = EFI_INVALID_PARAMETER;\r
+      pSocket->errno = ENOTCONN;\r
+      Status = EFI_NOT_STARTED;\r
     }\r
   }\r
 \r
@@ -2838,10 +5426,9 @@ EslSocketShutdown (
     if ( NULL != pSocket ) {\r
       *pErrno = pSocket->errno;\r
     }\r
-    else\r
-    {\r
+    else {\r
       Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = EBADF;\r
+      *pErrno = ENOTSOCK;\r
     }\r
   }\r
   DBG_EXIT_STATUS ( Status );\r
@@ -2852,10 +5439,17 @@ EslSocketShutdown (
 /**\r
   Send data using a network connection.\r
 \r
-  The SocketTransmit routine queues the data for transmission to the\r
-  remote network connection.\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
-  @param [in] pSocketProtocol Address of the socket protocol structure.\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
   \r
   @param [in] Flags           Message control flags\r
   \r
@@ -2886,7 +5480,7 @@ EslSocketTransmit (
   IN int * pErrno\r
   )\r
 {\r
-  DT_SOCKET * pSocket;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
 \r
@@ -2916,66 +5510,7 @@ EslSocketTransmit (
       //\r
       //  Verify the socket state\r
       //\r
-      if ( !pSocket->bConfigured ) {\r
-        //\r
-        //  Synchronize with the socket layer\r
-        //\r
-        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-        //\r
-        //  Validate the local address\r
-        //\r
-        switch ( pSocket->Domain ) {\r
-        default:\r
-          DEBUG (( DEBUG_RX,\r
-                    "ERROR - Invalid socket address family: %d\r\n",\r
-                    pSocket->Domain ));\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EADDRNOTAVAIL;\r
-          break;\r
-\r
-        case AF_INET:\r
-          //\r
-          //  Determine the connection point within the network stack\r
-          //\r
-          switch ( pSocket->Type ) {\r
-          default:\r
-            DEBUG (( DEBUG_RX,\r
-                      "ERROR - Invalid socket type: %d\r\n",\r
-                      pSocket->Type));\r
-            Status = EFI_INVALID_PARAMETER;\r
-            break;\r
-\r
-          case SOCK_STREAM:\r
-          case SOCK_SEQPACKET:\r
-            //\r
-            //  Verify the port state\r
-            //\r
-            Status = EslTcpSocketIsConfigured4 ( pSocket );\r
-            break;\r
-\r
-          case SOCK_DGRAM:\r
-            //\r
-            //  Verify the port state\r
-            //\r
-            Status = EslUdpSocketIsConfigured4 ( pSocket );\r
-            break;\r
-          }\r
-          break;\r
-        }\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
+      Status = EslSocketIsConfigured ( pSocket );\r
       if ( !EFI_ERROR ( Status )) {\r
         //\r
         //  Verify that transmit is still allowed\r
@@ -3015,61 +5550,39 @@ EslSocketTransmit (
             }\r
             else {\r
               //\r
-              //  Synchronize with the socket layer\r
-              //\r
-              RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-              //\r
-              //  Validate the local address\r
+              //  Verify the API\r
               //\r
-              switch ( pSocket->Domain ) {\r
-              default:\r
-                DEBUG (( DEBUG_RX,\r
-                          "ERROR - Invalid socket address family: %d\r\n",\r
-                          pSocket->Domain ));\r
-                Status = EFI_INVALID_PARAMETER;\r
-                pSocket->errno = EADDRNOTAVAIL;\r
-                break;\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
-              case AF_INET:\r
                 //\r
-                //  Determine the connection point within the network stack\r
+                //  Poll the network to increase performance\r
                 //\r
-                switch ( pSocket->Type ) {\r
-                default:\r
-                  DEBUG (( DEBUG_RX,\r
-                            "ERROR - Invalid socket type: %d\r\n",\r
-                            pSocket->Type));\r
-                  Status = EFI_INVALID_PARAMETER;\r
-                  pSocket->errno = EADDRNOTAVAIL;\r
-                  break;\r
+                EslSocketRxPoll ( pSocket );\r
 \r
-                case SOCK_STREAM:\r
-                case SOCK_SEQPACKET:\r
-                  Status = EslTcpTxBuffer4 ( pSocket,\r
-                                             Flags,\r
-                                             BufferLength,\r
-                                             pBuffer,\r
-                                             pDataLength );\r
-                  break;\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
-                case SOCK_DGRAM:\r
-                  Status = EslUdpTxBuffer4 ( pSocket,\r
-                                             Flags,\r
-                                             BufferLength,\r
-                                             pBuffer,\r
-                                             pDataLength,\r
-                                             pAddress,\r
-                                             AddressLength );\r
-                  break;\r
-                }\r
-                break;\r
+                //\r
+                //  Release the socket layer synchronization\r
+                //\r
+                RESTORE_TPL ( TplPrevious );\r
               }\r
-\r
-              //\r
-              //  Release the socket layer synchronization\r
-              //\r
-              RESTORE_TPL ( TplPrevious );\r
             }\r
           }\r
         }\r
@@ -3091,10 +5604,9 @@ EslSocketTransmit (
     if ( NULL != pSocket ) {\r
       *pErrno = pSocket->errno;\r
     }\r
-    else\r
-    {\r
+    else {\r
       Status = EFI_INVALID_PARAMETER;\r
-      *pErrno = EBADF;\r
+      *pErrno = ENOTSOCK;\r
     }\r
   }\r
   DBG_EXIT_STATUS ( Status );\r
@@ -3103,9 +5615,325 @@ EslSocketTransmit (
 \r
 \r
 /**\r
-  Socket layer's service binding protocol delcaration.\r
-**/\r
-EFI_SERVICE_BINDING_PROTOCOL mEfiServiceBinding = {\r
-  EslSocketCreateChild,\r
-  EslSocketDestroyChild\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
+ **/\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
+/**\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
+ **/\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
+      if ( EFI_SUCCESS == pSocket->TxError ) {\r
+        pSocket->TxError = Status;\r
+      }\r
+\r
+      //\r
+      //  Discard the transmit buffer\r
+      //\r
+      EslSocketPacketFree ( pPacket, DEBUG_TX );\r
+    }\r
+  }\r
+\r
+  DBG_EXIT ( );\r
+}\r