]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/EfiSocketLib/Tcp4.c
StdLib: Remove EfiSocketLib and Ip4Config Protocol dependency.
[mirror_edk2.git] / StdLib / EfiSocketLib / Tcp4.c
index 2840dd7e0e9bde9119aec8889de3957737eb1b33..68477fba6e70122d173a2ffc918564a4a6432446 100644 (file)
@@ -1,28 +1,97 @@
 /** @file\r
   Implement the TCP4 driver support for the socket layer.\r
 \r
-  Copyright (c) 2011, Intel Corporation\r
-  All rights reserved. This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
+  Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
 \r
   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 ConnectionManagement Connection Management\r
+\r
+  The ::EslTcp4Listen routine initially places the SOCK_STREAM or\r
+  SOCK_SEQPACKET socket into a listen state.   When a remote machine\r
+  makes a connection to the socket, the TCPv4 network layer calls\r
+  ::EslTcp4ListenComplete to complete the connection processing.\r
+  EslTcp4ListenComplete manages the connections by placing them in\r
+  FIFO order in a queue to be serviced by the application.  When the\r
+  number of connections exceeds the backlog (ESL_SOCKET::MaxFifoDepth),\r
+  the new connection is closed.  Eventually, the application indirectly\r
+  calls ::EslTcp4Accept to remove the next connection from the queue\r
+  and get the associated socket.\r
+\r
 **/\r
 \r
 #include "Socket.h"\r
 \r
 \r
+/**\r
+  Attempt to connect to a remote TCP port\r
+\r
+  This routine starts the connection processing for a SOCK_STREAM\r
+  or SOCK_SEQPAKCET socket using the TCPv4 network layer.  It\r
+  configures the local TCPv4 connection point and then attempts to\r
+  connect to a remote system.  Upon completion, the\r
+  ::EslTcp4ConnectComplete routine gets called with the connection\r
+  status.\r
+\r
+  This routine is called by ::EslSocketConnect to initiate the TCPv4\r
+  network specific connect operations.  The connection processing is\r
+  initiated by this routine and finished by ::EslTcp4ConnectComplete.\r
+  This pair of routines walks through the list of local TCPv4\r
+  connection points until a connection to the remote system is\r
+  made.\r
+\r
+  @param [in] pSocket   Address of an ::ESL_SOCKET structure.\r
+\r
+  @retval EFI_SUCCESS   The connection was successfully established.\r
+  @retval EFI_NOT_READY The connection is in progress, call this routine again.\r
+  @retval Others        The connection attempt failed.\r
+\r
+ **/\r
+EFI_STATUS\r
+EslTcp4ConnectStart (\r
+  IN ESL_SOCKET * pSocket\r
+  );\r
+\r
+\r
+/**\r
+  Process the connection attempt\r
+\r
+  A system has initiated a connection attempt with a socket in the\r
+  listen state.  Attempt to complete the connection.\r
+\r
+  The TCPv4 layer calls this routine when a connection is made to\r
+  the socket in the listen state.  See the\r
+  \ref ConnectionManagement section.\r
+\r
+  @param [in] Event     The listen completion event\r
+\r
+  @param [in] pPort     Address of an ::ESL_PORT structure.\r
+\r
+**/\r
+VOID\r
+EslTcp4ListenComplete (\r
+  IN EFI_EVENT Event,\r
+  IN ESL_PORT * pPort\r
+  );\r
+\r
+\r
 /**\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 waits for a network connection to the socket and\r
+  returns the remote network address to the caller if requested.\r
+\r
+  This routine is called by ::EslSocketAccept to handle the TCPv4 protocol\r
+  specific accept operations for SOCK_STREAM and SOCK_SEQPACKET sockets.\r
+  See the \ref ConnectionManagement section.\r
 \r
-  @param [in] pSocket   Address of the socket structure.\r
+  @param [in] pSocket   Address of an ::ESL_SOCKET structure.\r
 \r
   @param [in] pSockAddr       Address of a buffer to receive the remote\r
                               network address.\r
 \r
  **/\r
 EFI_STATUS\r
-EslTcpAccept4 (\r
-  IN DT_SOCKET * pSocket,\r
+EslTcp4Accept (\r
+  IN ESL_SOCKET * pSocket,\r
   IN struct sockaddr * pSockAddr,\r
   IN OUT socklen_t * pSockAddrLength\r
   )\r
 {\r
-  DT_PORT * pPort;\r
+  ESL_PORT * pPort;\r
   struct sockaddr_in * pRemoteAddress;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
   UINT32 RemoteAddress;\r
   EFI_STATUS Status;\r
 \r
@@ -102,302 +171,37 @@ EslTcpAccept4 (
 \r
 \r
 /**\r
-  Bind a name to a socket.\r
-\r
-  The ::TcpBind4 routine connects a name to a TCP4 stack on the local machine.\r
-\r
-  @param [in] pSocket   Address of the socket 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
-                        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
-\r
-  @param [in] SockAddrLen   Specifies the length in bytes of the sockaddr structure.\r
-\r
-  @retval EFI_SUCCESS - Socket successfully created\r
-\r
- **/\r
-EFI_STATUS\r
-EslTcpBind4 (\r
-  IN DT_SOCKET * pSocket,\r
-  IN const struct sockaddr * pSockAddr,\r
-  IN socklen_t SockAddrLength\r
-  )\r
-{\r
-  EFI_HANDLE ChildHandle;\r
-  DT_LAYER * pLayer;\r
-  DT_PORT * pPort;\r
-  DT_SERVICE * pService;\r
-  CONST struct sockaddr_in * pIp4Address;\r
-  EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service;\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
-  //  Assume success\r
-  //\r
-  pSocket->errno = 0;\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Validate the address length\r
-  //\r
-  pIp4Address = (CONST struct sockaddr_in *) pSockAddr;\r
-  if ( SockAddrLength >= ( sizeof ( *pIp4Address )\r
-                           - sizeof ( pIp4Address->sin_zero ))) {\r
-\r
-    //\r
-    //  Walk the list of services\r
-    //\r
-    pLayer = &mEslLayer;\r
-    pService = pLayer->pTcp4List;\r
-    while ( NULL != pService ) {\r
-      //\r
-      //  Create the TCP port\r
-      //\r
-      pTcp4Service = pService->pInterface;\r
-      ChildHandle = NULL;\r
-      Status = pTcp4Service->CreateChild ( pTcp4Service,\r
-                                           &ChildHandle );\r
-      if ( !EFI_ERROR ( Status )) {\r
-        DEBUG (( DEBUG_BIND | DEBUG_POOL,\r
-                  "0x%08x: Tcp4 port handle created\r\n",\r
-                  ChildHandle ));\r
-\r
-        //\r
-        //  Open the port\r
-        //\r
-        Status = EslTcpPortAllocate4 ( pSocket,\r
-                                       pService,\r
-                                       ChildHandle,\r
-                                       (UINT8 *) &pIp4Address->sin_addr.s_addr,\r
-                                       SwapBytes16 ( pIp4Address->sin_port ),\r
-                                       DEBUG_BIND,\r
-                                       &pPort );\r
-      }\r
-      else {\r
-        DEBUG (( DEBUG_BIND | DEBUG_POOL,\r
-                  "ERROR - Failed to open Tcp4 port handle, Status: %r\r\n",\r
-                  Status ));\r
-        ChildHandle = NULL;\r
-      }\r
-\r
-      //\r
-      //  Close the port if necessary\r
-      //\r
-      if (( EFI_ERROR ( Status )) && ( NULL != ChildHandle )) {\r
-        TempStatus = pTcp4Service->DestroyChild ( pTcp4Service,\r
-                                                  ChildHandle );\r
-        if ( !EFI_ERROR ( TempStatus )) {\r
-          DEBUG (( DEBUG_BIND | DEBUG_POOL,\r
-                    "0x%08x: Tcp4 port handle destroyed\r\n",\r
-                    ChildHandle ));\r
-        }\r
-        else {\r
-          DEBUG (( DEBUG_ERROR | DEBUG_BIND | DEBUG_POOL,\r
-                    "ERROR - Failed to destroy the Tcp4 port handle 0x%08x, Status: %r\r\n",\r
-                    ChildHandle,\r
-                    TempStatus ));\r
-          ASSERT ( EFI_SUCCESS == TempStatus );\r
-        }\r
-      }\r
-\r
-      //\r
-      //  Set the next service\r
-      //\r
-      pService = pService->pNext;\r
-    }\r
-\r
-    //\r
-    //  Verify that at least one network connection was found\r
-    //\r
-    if ( NULL == pSocket->pPortList ) {\r
-      DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,\r
-                "Socket address %d.%d.%d.%d (0x%08x) is not available!\r\n",\r
-                ( pIp4Address->sin_addr.s_addr >> 24 ) & 0xff,\r
-                ( pIp4Address->sin_addr.s_addr >> 16 ) & 0xff,\r
-                ( pIp4Address->sin_addr.s_addr >> 8 ) & 0xff,\r
-                pIp4Address->sin_addr.s_addr & 0xff,\r
-                pIp4Address->sin_addr.s_addr ));\r
-      pSocket->errno = EADDRNOTAVAIL;\r
-      Status = EFI_INVALID_PARAMETER;\r
-    }\r
-  }\r
-  else {\r
-    DEBUG (( DEBUG_BIND,\r
-              "ERROR - Invalid TCP4 address length: %d\r\n",\r
-              SockAddrLength ));\r
-    Status = EFI_INVALID_PARAMETER;\r
-    pSocket->errno = EINVAL;\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Attempt to connect to a remote TCP port\r
-\r
-  @param [in] pSocket         Address of the socket structure.\r
-\r
-  @retval EFI_SUCCESS   The connection was successfully established.\r
-  @retval EFI_NOT_READY The connection is in progress, call this routine again.\r
-  @retval Others        The connection attempt failed.\r
-\r
- **/\r
-EFI_STATUS\r
-EslTcpConnectAttempt4 (\r
-  IN DT_SOCKET * pSocket\r
-  )\r
-{\r
-  DT_PORT * pPort;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
-  EFI_TCP4_PROTOCOL * pTcp4Protocol;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-  \r
-  //\r
-  //  Determine if any more local adapters are available\r
-  //\r
-  pPort = pSocket->pPortList;\r
-  if ( NULL != pPort ) {\r
-    //\r
-    //  Configure the port\r
-    //\r
-    pTcp4 = &pPort->Context.Tcp4;\r
-    pTcp4->ConfigData.AccessPoint.ActiveFlag = TRUE;\r
-    pTcp4->ConfigData.TimeToLive = 255;\r
-    pTcp4Protocol = pTcp4->pProtocol;\r
-    Status = pTcp4Protocol->Configure ( pTcp4Protocol,\r
-                                        &pTcp4->ConfigData );\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_CONNECT,\r
-                "ERROR - Failed to configure the Tcp4 port, Status: %r\r\n",\r
-                Status ));\r
-      switch ( Status ) {\r
-      case EFI_ACCESS_DENIED:\r
-        pSocket->errno = EACCES;\r
-        break;\r
-    \r
-      default:\r
-      case EFI_DEVICE_ERROR:\r
-        pSocket->errno = EIO;\r
-        break;\r
-    \r
-      case EFI_INVALID_PARAMETER:\r
-        pSocket->errno = EADDRNOTAVAIL;\r
-        break;\r
-    \r
-      case EFI_NO_MAPPING:\r
-        pSocket->errno = EAFNOSUPPORT;\r
-        break;\r
-    \r
-      case EFI_OUT_OF_RESOURCES:\r
-        pSocket->errno = ENOBUFS;\r
-        break;\r
-    \r
-      case EFI_UNSUPPORTED:\r
-        pSocket->errno = EOPNOTSUPP;\r
-        break;\r
-      }\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_CONNECT,\r
-                "0x%08x: Port configured\r\n",\r
-                pPort ));\r
-      pTcp4->bConfigured = TRUE;\r
-\r
-      //\r
-      //  Attempt the connection to the remote system\r
-      //\r
-      Status = pTcp4Protocol->Connect ( pTcp4Protocol,\r
-                                        &pTcp4->ConnectToken );\r
-      if ( !EFI_ERROR ( Status )) {\r
-        //\r
-        //  Connection in progress\r
-        //\r
-        pSocket->errno = EINPROGRESS;\r
-        Status = EFI_NOT_READY;\r
-        DEBUG (( DEBUG_CONNECT,\r
-                  "0x%08x: Port attempting connection to %d.%d.%d.%d:%d\r\n",\r
-                  pPort,\r
-                  pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],\r
-                  pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],\r
-                  pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],\r
-                  pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],\r
-                  pTcp4->ConfigData.AccessPoint.RemotePort ));\r
-      }\r
-      else {\r
-        //\r
-        //  Connection error\r
-        //\r
-        pSocket->errno = EINVAL;\r
-        DEBUG (( DEBUG_CONNECT,\r
-                  "ERROR - Port 0x%08x not connected, Status: %r\r\n",\r
-                  pPort,\r
-                  Status ));\r
-      }\r
-    }\r
-  }\r
-  else {\r
-    //\r
-    //  No more local adapters available\r
-    //\r
-    pSocket->errno = ENETUNREACH;\r
-    Status = EFI_NO_RESPONSE;\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Process the remote connection attempt\r
+  Process the remote connection completion event.\r
 \r
-  A connection attempt to a remote system has just completed when\r
-  this routine is invoked.  Release the port in the case of an\r
+  This routine handles the completion of a connection attempt.  It\r
+  releases the port (TCPv4 adapter connection) in the case of an\r
   error and start a connection attempt on the next port.  If the\r
-  connection attempt was successful, then release all of the other\r
-  ports.\r
+  connection attempt was successful then this routine releases all\r
+  of the other ports.\r
 \r
-  @param  Event         The connect completion event\r
+  This routine is called by the TCPv4 layer when a connect request\r
+  completes.  It sets the ESL_SOCKET::bConnected flag to notify the\r
+  ::EslTcp4ConnectComplete routine that the connection is available.\r
+  The flag is set when the connection is established or no more ports\r
+  exist in the list.  The connection status is passed via\r
+  ESL_SOCKET::ConnectStatus.\r
 \r
-  @param  pPort         The DT_PORT structure address\r
+  @param [in] Event     The connect completion event\r
+\r
+  @param [in] pPort     Address of an ::ESL_PORT structure.\r
 \r
 **/\r
 VOID\r
-EslTcpConnectComplete4 (\r
+EslTcp4ConnectComplete (\r
   IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
+  IN ESL_PORT * pPort\r
   )\r
 {\r
   BOOLEAN bRemoveFirstPort;\r
   BOOLEAN bRemovePorts;\r
-  DT_PORT * pNextPort;\r
-  DT_SOCKET * pSocket;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
+  ESL_PORT * pNextPort;\r
+  ESL_SOCKET * pSocket;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
@@ -422,12 +226,19 @@ EslTcpConnectComplete4 (
     DEBUG (( DEBUG_CONNECT,\r
               "0x%08x: Port connected to %d.%d.%d.%d:%d\r\n",\r
               pPort,\r
-              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [0],\r
-              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [1],\r
-              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [2],\r
-              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [3],\r
+              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],\r
+              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],\r
+              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],\r
+              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],\r
               pTcp4->ConfigData.AccessPoint.RemotePort ));\r
 \r
+    //\r
+    //  Start the receive operations\r
+    //\r
+    pSocket->bConfigured = TRUE;\r
+    pSocket->State = SOCKET_STATE_CONNECTED;\r
+    EslSocketRxStart ( pPort );\r
+\r
     //\r
     //  Remove the rest of the ports\r
     //\r
@@ -437,20 +248,22 @@ EslTcpConnectComplete4 (
     //\r
     //  The connection failed\r
     //\r
-    DEBUG (( DEBUG_CONNECT,\r
-              "0x%08x: Port connection to %d.%d.%d.%d:%d failed, Status: %r\r\n",\r
-              pPort,\r
-              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [0],\r
-              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [1],\r
-              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [2],\r
-              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [3],\r
-              pTcp4->ConfigData.AccessPoint.RemotePort,\r
-              Status ));\r
+    if ( pPort->bConfigured ) {\r
+      DEBUG (( DEBUG_CONNECT,\r
+                "0x%08x: Port connection to %d.%d.%d.%d:%d failed, Status: %r\r\n",\r
+                pPort,\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],\r
+                pTcp4->ConfigData.AccessPoint.RemotePort,\r
+                Status ));\r
+    }\r
 \r
     //\r
     //  Close the current port\r
     //\r
-    Status = EslTcpPortClose4 ( pPort );\r
+    Status = EslSocketPortClose ( pPort );\r
     if ( !EFI_ERROR ( Status )) {\r
       DEBUG (( DEBUG_CONNECT,\r
               "0x%08x: Port closed\r\n",\r
@@ -466,9 +279,8 @@ EslTcpConnectComplete4 (
     //\r
     //  Try to connect using the next port\r
     //\r
-    Status = EslTcpConnectAttempt4 ( pSocket );\r
+    Status = EslTcp4ConnectStart ( pSocket );\r
     if ( EFI_NOT_READY != Status ) {\r
-      pSocket->ConnectStatus = Status;\r
       bRemoveFirstPort = TRUE;\r
     }\r
   }\r
@@ -490,7 +302,7 @@ EslTcpConnectComplete4 (
     //\r
     while ( NULL != pPort ) {\r
       pNextPort = pPort->pLinkSocket;\r
-      EslTcpPortClose4 ( pPort );\r
+      EslSocketPortClose ( pPort );\r
       if ( !EFI_ERROR ( Status )) {\r
         DEBUG (( DEBUG_CONNECT,\r
                 "0x%08x: Port closed\r\n",\r
@@ -518,10 +330,16 @@ EslTcpConnectComplete4 (
 /**\r
   Poll for completion of the connection attempt.\r
 \r
-  The ::TcpConnectPoll4 routine determines when the connection\r
-  attempt transitions from being in process to being complete.\r
+  This routine polls the ESL_SOCKET::bConnected flag to determine\r
+  when the connection attempt is complete.\r
 \r
-  @param [in] pSocket         Address of the socket structure.\r
+  This routine is called from ::EslSocketConnect to determine when\r
+  the connection is complete.  The ESL_SOCKET::bConnected flag is\r
+  set by ::EslTcp4ConnectComplete when the TCPv4 layer establishes\r
+  a connection or runs out of local network adapters.  This routine\r
+  gets the connection status from ESL_SOCKET::ConnectStatus.\r
+\r
+  @param [in] pSocket   Address of an ::ESL_SOCKET structure.\r
 \r
   @retval EFI_SUCCESS   The connection was successfully established.\r
   @retval EFI_NOT_READY The connection is in progress, call this routine again.\r
@@ -529,8 +347,8 @@ EslTcpConnectComplete4 (
 \r
  **/\r
 EFI_STATUS\r
-EslTcpConnectPoll4 (\r
-  IN DT_SOCKET * pSocket\r
+EslTcp4ConnectPoll (\r
+  IN ESL_SOCKET * pSocket\r
   )\r
 {\r
   EFI_STATUS Status;\r
@@ -564,29 +382,47 @@ EslTcpConnectPoll4 (
       break;\r
 \r
     case EFI_ABORTED:\r
-      pSocket->errno = ECONNREFUSED;\r
+      pSocket->errno = ECONNABORTED;\r
+      break;\r
+\r
+    case EFI_ACCESS_DENIED:\r
+      pSocket->errno = EACCES;\r
+      break;\r
+\r
+    case EFI_CONNECTION_RESET:\r
+      pSocket->errno = ECONNRESET;\r
       break;\r
 \r
     case EFI_INVALID_PARAMETER:\r
-      pSocket->errno = EINVAL;\r
+      pSocket->errno = EADDRNOTAVAIL;\r
       break;\r
 \r
-    case EFI_NO_MAPPING:\r
+    case EFI_HOST_UNREACHABLE:\r
     case EFI_NO_RESPONSE:\r
       pSocket->errno = EHOSTUNREACH;\r
       break;\r
 \r
+    case EFI_NO_MAPPING:\r
+      pSocket->errno = EAFNOSUPPORT;\r
+      break;\r
+\r
     case EFI_NO_MEDIA:\r
+    case EFI_NETWORK_UNREACHABLE:\r
       pSocket->errno = ENETDOWN;\r
       break;\r
 \r
     case EFI_OUT_OF_RESOURCES:\r
-      pSocket->errno = ENOMEM;\r
+      pSocket->errno = ENOBUFS;\r
+      break;\r
+\r
+    case EFI_PORT_UNREACHABLE:\r
+    case EFI_PROTOCOL_UNREACHABLE:\r
+    case EFI_CONNECTION_REFUSED:\r
+      pSocket->errno = ECONNREFUSED;\r
       break;\r
 \r
     case EFI_SUCCESS:\r
       pSocket->errno = 0;\r
-      pSocket->bConfigured = TRUE;\r
       break;\r
 \r
     case EFI_TIMEOUT:\r
@@ -594,13 +430,17 @@ EslTcpConnectPoll4 (
       break;\r
 \r
     case EFI_UNSUPPORTED:\r
-      pSocket->errno = ENOTSUP;\r
-      break;\r
-\r
-    case 0x80000069:\r
-      pSocket->errno = ECONNRESET;\r
+      pSocket->errno = EOPNOTSUPP;\r
       break;\r
     }\r
+\r
+    //\r
+    //  Display the translation\r
+    //\r
+    DEBUG (( DEBUG_CONNECT,\r
+              "ERROR - errno: %d, Status: %r\r\n",\r
+              pSocket->errno,\r
+              Status ));\r
   }\r
 \r
   //\r
@@ -612,292 +452,141 @@ EslTcpConnectPoll4 (
 \r
 \r
 /**\r
-  Connect to a remote system via the network.\r
+  Attempt to connect to a remote TCP port\r
 \r
-  The ::TcpConnectStart4= routine starts the connection processing\r
-  for a TCP4 port.\r
+  This routine starts the connection processing for a SOCK_STREAM\r
+  or SOCK_SEQPAKCET socket using the TCPv4 network layer.  It\r
+  configures the local TCPv4 connection point and then attempts to\r
+  connect to a remote system.  Upon completion, the\r
+  ::EslTcp4ConnectComplete routine gets called with the connection\r
+  status.\r
 \r
-  @param [in] pSocket         Address of the socket structure.\r
+  This routine is called by ::EslSocketConnect to initiate the TCPv4\r
+  network specific connect operations.  The connection processing is\r
+  initiated by this routine and finished by ::EslTcp4ConnectComplete.\r
+  This pair of routines walks through the list of local TCPv4\r
+  connection points until a connection to the remote system is\r
+  made.\r
+\r
+  @param [in] pSocket   Address of an ::ESL_SOCKET structure.\r
 \r
-  @param [in] pSockAddr       Network address of the remote system.\r
-    \r
-  @param [in] SockAddrLength  Length in bytes of the network address.\r
-  \r
   @retval EFI_SUCCESS   The connection was successfully established.\r
   @retval EFI_NOT_READY The connection is in progress, call this routine again.\r
   @retval Others        The connection attempt failed.\r
 \r
  **/\r
 EFI_STATUS\r
-EslTcpConnectStart4 (\r
-  IN DT_SOCKET * pSocket,\r
-  IN const struct sockaddr * pSockAddr,\r
-  IN socklen_t SockAddrLength\r
+EslTcp4ConnectStart (\r
+  IN ESL_SOCKET * pSocket\r
   )\r
 {\r
-  struct sockaddr_in LocalAddress;\r
-  DT_PORT * pPort;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
-  CONST struct sockaddr_in * pIp4Address;\r
+  ESL_PORT * pPort;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
+  EFI_TCP4_PROTOCOL * pTcp4Protocol;\r
+  EFI_SIMPLE_NETWORK_MODE SnpModeData;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Validate the address length\r
+  //  Determine if any more local adapters are available\r
   //\r
-  Status = EFI_SUCCESS;\r
-  pIp4Address = (CONST struct sockaddr_in *) pSockAddr;\r
-  if ( SockAddrLength >= ( sizeof ( *pIp4Address )\r
-                           - sizeof ( pIp4Address->sin_zero ))) {\r
+  pPort = pSocket->pPortList;\r
+  if ( NULL != pPort ) {\r
     //\r
-    //  Determine if BIND was already called\r
+    //  Configure the port\r
     //\r
-    if ( NULL == pSocket->pPortList ) {\r
-      //\r
-      //  Allow any local port\r
-      //\r
-      ZeroMem ( &LocalAddress, sizeof ( LocalAddress ));\r
-      LocalAddress.sin_len = sizeof ( LocalAddress );\r
-      LocalAddress.sin_family = AF_INET;\r
-      Status = EslSocketBind ( &pSocket->SocketProtocol,\r
-                               (struct sockaddr *)&LocalAddress,\r
-                               LocalAddress.sin_len,\r
-                               &pSocket->errno );\r
+    pTcp4 = &pPort->Context.Tcp4;\r
+    pTcp4->ConfigData.AccessPoint.ActiveFlag = TRUE;\r
+    pTcp4->ConfigData.TimeToLive = 255;\r
+    pTcp4Protocol = pPort->pProtocol.TCPv4;\r
+    Status = pTcp4Protocol->Configure ( pTcp4Protocol,\r
+                                        &pTcp4->ConfigData );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_CONNECT,\r
+                "ERROR - Failed to configure the Tcp4 port, Status: %r\r\n",\r
+                Status ));\r
     }\r
-    if ( NULL != pSocket->pPortList ) {\r
+    else {\r
+      DEBUG (( DEBUG_CONNECT,\r
+                "0x%08x: Port configured\r\n",\r
+                pPort ));\r
+      pPort->bConfigured = TRUE;\r
+\r
       //\r
-      //  Walk the list of ports\r
+      //  Verify the port connection\r
       //\r
-      pPort = pSocket->pPortList;\r
-      while ( NULL != pPort ) {\r
-        //\r
-        //  Set the remote address\r
-        //\r
-        pTcp4 = &pPort->Context.Tcp4;\r
-        *(UINT32 *)&pTcp4->ConfigData.AccessPoint.RemoteAddress = pIp4Address->sin_addr.s_addr;\r
-        pTcp4->ConfigData.AccessPoint.RemotePort = SwapBytes16 ( pIp4Address->sin_port );\r
-\r
+      Status = pTcp4Protocol->GetModeData ( pTcp4Protocol,\r
+                                            NULL,\r
+                                            NULL,\r
+                                            NULL,\r
+                                            NULL,\r
+                                            &SnpModeData );\r
+      if ( !EFI_ERROR ( Status )) {\r
+        if ( SnpModeData.MediaPresentSupported\r
+          && ( !SnpModeData.MediaPresent )) {\r
+          //\r
+          //  Port is not connected to the network\r
+          //\r
+          Status = EFI_NO_MEDIA;\r
+        }\r
+        else {\r
+          //\r
+          //  Attempt the connection to the remote system\r
+          //\r
+          Status = pTcp4Protocol->Connect ( pTcp4Protocol,\r
+                                            &pTcp4->ConnectToken );\r
+        }\r
+      }\r
+      if ( EFI_ERROR ( Status )) {\r
         //\r
-        //  Set the next port\r
+        //  Connection error\r
         //\r
-        pPort = pPort->pLinkSocket;\r
+        DEBUG (( DEBUG_CONNECT,\r
+                  "ERROR - Port 0x%08x not connected, Status: %r\r\n",\r
+                  pPort,\r
+                  Status ));\r
       }\r
-      \r
-      //\r
-      //  Attempt a connection using the first adapter\r
-      //\r
-      Status = EslTcpConnectAttempt4 ( pSocket );\r
     }\r
-  }\r
-  else {\r
-    DEBUG (( DEBUG_CONNECT,\r
-              "ERROR - Invalid TCP4 address length: %d\r\n",\r
-              SockAddrLength ));\r
-    Status = EFI_INVALID_PARAMETER;\r
-    pSocket->errno = EINVAL;\r
-  }\r
-\r
-  //\r
-  //  Return the initialization status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Initialize the TCP4 service.\r
-\r
-  This routine initializes the TCP4 service after its service binding\r
-  protocol was located on a controller.\r
-\r
-  @param [in] pService        DT_SERVICE structure address\r
-\r
-  @retval EFI_SUCCESS         The service was properly initialized\r
-  @retval other               A failure occurred during the service initialization\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-EslTcpInitialize4 (\r
-  IN DT_SERVICE * pService\r
-  )\r
-{\r
-  DT_LAYER * pLayer;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Identify the service\r
-  //\r
-  pService->NetworkType = NETWORK_TYPE_TCP4;\r
-\r
-  //\r
-  //  Connect this service to the service list\r
-  //\r
-  pLayer = &mEslLayer;\r
-  pService->pNext = pLayer->pTcp4List;\r
-  pLayer->pTcp4List = pService;\r
-\r
-  //\r
-  //  Assume the list is empty\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  //  Return the initialization status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Get the local socket address\r
-\r
-  @param [in] pSocket             Address of the socket structure.\r
-\r
-  @param [out] pAddress           Network address to receive the local system address\r
-\r
-  @param [in,out] pAddressLength  Length of the local network address structure\r
-\r
-  @retval EFI_SUCCESS - Address available\r
-  @retval Other - Failed to get the address\r
-\r
-**/\r
-EFI_STATUS\r
-EslTcpGetLocalAddress4 (\r
-  IN DT_SOCKET * pSocket,\r
-  OUT struct sockaddr * pAddress,\r
-  IN OUT socklen_t * pAddressLength\r
-  )\r
-{\r
-  socklen_t LengthInBytes;\r
-  DT_PORT * pPort;\r
-  struct sockaddr_in * pLocalAddress;\r
-  DT_TCP4_CONTEXT * pTcp4;\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 there is just a single connection\r
-  //\r
-  pPort = pSocket->pPortList;\r
-  if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {\r
-    //\r
-    //  Verify the address length\r
-    //\r
-    LengthInBytes = sizeof ( struct sockaddr_in );\r
-    if ( LengthInBytes <= * pAddressLength ) {\r
+    if ( !EFI_ERROR ( Status )) {\r
       //\r
-      //  Return the local address\r
+      //  Connection in progress\r
       //\r
-      pTcp4 = &pPort->Context.Tcp4;\r
-      pLocalAddress = (struct sockaddr_in *)pAddress;\r
-      ZeroMem ( pLocalAddress, LengthInBytes );\r
-      pLocalAddress->sin_family = AF_INET;\r
-      pLocalAddress->sin_len = (uint8_t)LengthInBytes;\r
-      pLocalAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.StationPort );\r
-      CopyMem ( &pLocalAddress->sin_addr,\r
-                &pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0],\r
-                sizeof ( pLocalAddress->sin_addr ));\r
-      pSocket->errno = 0;\r
-      Status = EFI_SUCCESS;\r
+      pSocket->errno = EINPROGRESS;\r
+      DEBUG (( DEBUG_CONNECT,\r
+                "0x%08x: Port attempting connection to %d.%d.%d.%d:%d\r\n",\r
+                pPort,\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],\r
+                pTcp4->ConfigData.AccessPoint.RemotePort ));\r
     }\r
     else {\r
-      pSocket->errno = EINVAL;\r
-      Status = EFI_INVALID_PARAMETER;\r
-    }\r
-  }\r
-  else {\r
-    pSocket->errno = ENOTCONN;\r
-    Status = EFI_NOT_STARTED;\r
-  }\r
-  \r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Get the remote socket address\r
-\r
-  @param [in] pSocket             Address of the socket structure.\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
-  @retval EFI_SUCCESS - Address available\r
-  @retval Other - Failed to get the address\r
-\r
-**/\r
-EFI_STATUS\r
-EslTcpGetRemoteAddress4 (\r
-  IN DT_SOCKET * pSocket,\r
-  OUT struct sockaddr * pAddress,\r
-  IN OUT socklen_t * pAddressLength\r
-  )\r
-{\r
-  socklen_t LengthInBytes;\r
-  DT_PORT * pPort;\r
-  struct sockaddr_in * pRemoteAddress;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
+      //\r
+      //  Error return path is through EslTcp4ConnectComplete to\r
+      //  enable retry on other ports\r
+      //\r
+      //  Status to errno translation gets done in EslTcp4ConnectPoll\r
+      //\r
+      pTcp4->ConnectToken.CompletionToken.Status = Status;\r
 \r
-  //\r
-  //  Verify that there is just a single connection\r
-  //\r
-  pPort = pSocket->pPortList;\r
-  if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {\r
-    //\r
-    //  Verify the address length\r
-    //\r
-    LengthInBytes = sizeof ( struct sockaddr_in );\r
-    if ( LengthInBytes <= * pAddressLength ) {\r
       //\r
-      //  Return the local address\r
+      //  Continue with the next port\r
       //\r
-      pTcp4 = &pPort->Context.Tcp4;\r
-      pRemoteAddress = (struct sockaddr_in *)pAddress;\r
-      ZeroMem ( pRemoteAddress, LengthInBytes );\r
-      pRemoteAddress->sin_family = AF_INET;\r
-      pRemoteAddress->sin_len = (uint8_t)LengthInBytes;\r
-      pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );\r
-      CopyMem ( &pRemoteAddress->sin_addr,\r
-                &pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],\r
-                sizeof ( pRemoteAddress->sin_addr ));\r
-      pSocket->errno = 0;\r
-      Status = EFI_SUCCESS;\r
-    }\r
-    else {\r
-      pSocket->errno = EINVAL;\r
-      Status = EFI_INVALID_PARAMETER;\r
+      gBS->CheckEvent ( pTcp4->ConnectToken.CompletionToken.Event );\r
+      gBS->SignalEvent ( pTcp4->ConnectToken.CompletionToken.Event );\r
     }\r
+    Status = EFI_NOT_READY;\r
   }\r
   else {\r
-    pSocket->errno = ENOTCONN;\r
-    Status = EFI_NOT_STARTED;\r
+    //\r
+    //  No more local adapters available\r
+    //\r
+    pSocket->errno = ENETUNREACH;\r
+    Status = EFI_NO_RESPONSE;\r
   }\r
-  \r
+\r
   //\r
   //  Return the operation status\r
   //\r
@@ -909,27 +598,27 @@ EslTcpGetRemoteAddress4 (
 /**\r
   Establish the known port to listen for network connections.\r
 \r
-  The ::Tcp4Listen 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 ::Tcp4Accept 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 routine places the port into a state that enables connection\r
+  attempts.\r
+\r
+  This routine is called by ::EslSocketListen to handle the network\r
+  specifics of the listen operation for SOCK_STREAM and SOCK_SEQPACKET\r
+  sockets.  See the \ref ConnectionManagement section.\r
 \r
-  @param [in] pSocket     Address of the socket structure.\r
+  @param [in] pSocket   Address of an ::ESL_SOCKET structure.\r
 \r
   @retval EFI_SUCCESS - Socket successfully created\r
   @retval Other - Failed to enable the socket for listen\r
 \r
 **/\r
 EFI_STATUS\r
-EslTcpListen4 (\r
-  IN DT_SOCKET * pSocket\r
+EslTcp4Listen (\r
+  IN ESL_SOCKET * pSocket\r
   )\r
 {\r
-  DT_PORT * pNextPort;\r
-  DT_PORT * pPort;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
+  ESL_PORT * pNextPort;\r
+  ESL_PORT * pPort;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
   EFI_TCP4_PROTOCOL * pTcp4Protocol;\r
   EFI_STATUS Status;\r
 \r
@@ -970,7 +659,7 @@ EslTcpListen4 (
         pTcp4 = &pPort->Context.Tcp4;\r
         Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,\r
                                     TPL_SOCKETS,\r
-                                    (EFI_EVENT_NOTIFY)EslTcpListenComplete4,\r
+                                    (EFI_EVENT_NOTIFY)EslTcp4ListenComplete,\r
                                     pPort,\r
                                     &pTcp4->ListenToken.CompletionToken.Event );\r
         if ( EFI_ERROR ( Status )) {\r
@@ -987,7 +676,7 @@ EslTcpListen4 (
         //\r
         //  Configure the port\r
         //\r
-        pTcp4Protocol = pTcp4->pProtocol;\r
+        pTcp4Protocol = pPort->pProtocol.TCPv4;\r
         Status = pTcp4Protocol->Configure ( pTcp4Protocol,\r
                                             &pTcp4->ConfigData );\r
         if ( EFI_ERROR ( Status )) {\r
@@ -1025,7 +714,7 @@ EslTcpListen4 (
         DEBUG (( DEBUG_LISTEN,\r
                   "0x%08x: Port configured\r\n",\r
                   pPort ));\r
-        pTcp4->bConfigured = TRUE;\r
+        pPort->bConfigured = TRUE;\r
 \r
         //\r
         //  Start the listen operation on the port\r
@@ -1078,9 +767,8 @@ EslTcpListen4 (
       //\r
       //  Close the port upon error\r
       //\r
-      if ( EFI_ERROR ( Status ))\r
-      {\r
-        EslTcpPortCloseStart4 ( pPort, TRUE, DEBUG_LISTEN );\r
+      if ( EFI_ERROR ( Status )) {\r
+        EslSocketPortCloseStart ( pPort, TRUE, DEBUG_LISTEN );\r
       }\r
 \r
       //\r
@@ -1088,7 +776,7 @@ EslTcpListen4 (
       //\r
       pPort = pNextPort;\r
     }\r
-    \r
+\r
     //\r
     //  Determine if any ports are in the listen state\r
     //\r
@@ -1108,6 +796,8 @@ EslTcpListen4 (
     //  Mark the socket as configured\r
     //\r
     pSocket->bConfigured = TRUE;\r
+    Status = EFI_SUCCESS;\r
+    pSocket->errno = 0;\r
 \r
     //\r
     //  All done\r
@@ -1132,30 +822,35 @@ EslTcpListen4 (
   A system has initiated a connection attempt with a socket in the\r
   listen state.  Attempt to complete the connection.\r
 \r
-  @param  Event         The listen completion event\r
+  The TCPv4 layer calls this routine when a connection is made to\r
+  the socket in the listen state.  See the\r
+  \ref ConnectionManagement section.\r
+\r
+  @param [in] Event     The listen completion event\r
 \r
-  @param  pPort         The DT_PORT structure address\r
+  @param [in] pPort     Address of an ::ESL_PORT structure.\r
 \r
 **/\r
 VOID\r
-EslTcpListenComplete4 (\r
+EslTcp4ListenComplete (\r
   IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
+  IN ESL_PORT * pPort\r
   )\r
 {\r
   EFI_HANDLE ChildHandle;\r
+  struct sockaddr_in LocalAddress;\r
   EFI_TCP4_CONFIG_DATA * pConfigData;\r
-  DT_LAYER * pLayer;\r
-  DT_PORT * pNewPort;\r
-  DT_SOCKET * pNewSocket;\r
-  DT_SOCKET * pSocket;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
+  ESL_PORT * pNewPort;\r
+  ESL_SOCKET * pNewSocket;\r
+  ESL_SOCKET * pSocket;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
   EFI_TCP4_PROTOCOL * pTcp4Protocol;\r
   EFI_STATUS Status;\r
   EFI_HANDLE TcpPortHandle;\r
   EFI_STATUS TempStatus;\r
 \r
   DBG_ENTER ( );\r
+  VERIFY_AT_TPL ( TPL_SOCKETS );\r
 \r
   //\r
   //  Assume success\r
@@ -1173,7 +868,6 @@ EslTcpListenComplete4 (
     //  Allocate a socket for this connection\r
     //\r
     ChildHandle = NULL;\r
-    pLayer = &mEslLayer;\r
     Status = EslSocketAllocate ( &ChildHandle,\r
                                  DEBUG_CONNECTION,\r
                                  &pNewSocket );\r
@@ -1181,26 +875,36 @@ EslTcpListenComplete4 (
       //\r
       //  Clone the socket parameters\r
       //\r
+      pNewSocket->pApi = pSocket->pApi;\r
       pNewSocket->Domain = pSocket->Domain;\r
       pNewSocket->Protocol = pSocket->Protocol;\r
       pNewSocket->Type = pSocket->Type;\r
 \r
       //\r
-      //  Allocate a port for this connection\r
+      //  Build the local address\r
       //\r
       pTcp4 = &pPort->Context.Tcp4;\r
-      Status = EslTcpPortAllocate4 ( pNewSocket,\r
-                                     pPort->pService,\r
-                                     TcpPortHandle,\r
-                                     &pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0],\r
-                                     0,\r
-                                     DEBUG_CONNECTION,\r
-                                     &pNewPort );\r
+      LocalAddress.sin_len = (uint8_t)pNewSocket->pApi->MinimumAddressLength;\r
+      LocalAddress.sin_family = AF_INET;\r
+      LocalAddress.sin_port = 0;\r
+      LocalAddress.sin_addr.s_addr = *(UINT32 *)&pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0];\r
+\r
+      //\r
+      //  Allocate a port for this connection\r
+      //  Note in this instance Configure may not be called with NULL!\r
+      //\r
+      Status = EslSocketPortAllocate ( pNewSocket,\r
+                                       pPort->pService,\r
+                                       TcpPortHandle,\r
+                                       (struct sockaddr *)&LocalAddress,\r
+                                       FALSE,\r
+                                       DEBUG_CONNECTION,\r
+                                       &pNewPort );\r
       if ( !EFI_ERROR ( Status )) {\r
         //\r
         //  Restart the listen operation on the port\r
         //\r
-        pTcp4Protocol = pTcp4->pProtocol;\r
+        pTcp4Protocol = pPort->pProtocol.TCPv4;\r
         Status = pTcp4Protocol->Accept ( pTcp4Protocol,\r
                                          &pTcp4->ListenToken );\r
 \r
@@ -1209,7 +913,6 @@ EslTcpListenComplete4 (
         //\r
         TcpPortHandle = NULL;\r
         pTcp4 = &pNewPort->Context.Tcp4;\r
-        pTcp4->bConfigured = TRUE;\r
 \r
         //\r
         //  Check for an accept call error\r
@@ -1218,9 +921,10 @@ EslTcpListenComplete4 (
           //\r
           //  Get the port configuration\r
           //\r
+          pNewPort->bConfigured = TRUE;\r
           pConfigData = &pTcp4->ConfigData;\r
           pConfigData->ControlOption = &pTcp4->Option;\r
-          pTcp4Protocol = pTcp4->pProtocol;\r
+          pTcp4Protocol = pNewPort->pProtocol.TCPv4;\r
           Status = pTcp4Protocol->GetModeData ( pTcp4Protocol,\r
                                                 NULL,\r
                                                 pConfigData,\r
@@ -1276,7 +980,7 @@ EslTcpListenComplete4 (
             //\r
             //  Start the receive operation\r
             //\r
-            EslTcpRxStart4 ( pNewPort );\r
+            EslSocketRxStart ( pNewPort );\r
           }\r
           else {\r
             DEBUG (( DEBUG_ERROR | DEBUG_CONNECTION | DEBUG_INFO,\r
@@ -1297,7 +1001,7 @@ EslTcpListenComplete4 (
           //\r
           //  Close the listening port\r
           //\r
-          EslTcpPortCloseStart4 ( pPort, TRUE, DEBUG_LISTEN );\r
+          EslSocketPortCloseStart ( pPort, TRUE, DEBUG_LISTEN );\r
         }\r
       }\r
 \r
@@ -1335,7 +1039,7 @@ EslTcpListenComplete4 (
     //  Process:\r
     //    Call close\r
     //    Release the resources\r
-    \r
+\r
   }\r
 \r
   DBG_EXIT ( );\r
@@ -1343,142 +1047,234 @@ EslTcpListenComplete4 (
 \r
 \r
 /**\r
-  Allocate and initialize a DT_PORT structure.\r
+  Get the local socket address.\r
 \r
-  @param [in] pSocket     Address of the socket structure.\r
-  @param [in] pService    Address of the DT_SERVICE structure.\r
-  @param [in] ChildHandle TCP4 child handle\r
-  @param [in] pIpAddress  Buffer containing IP4 network address of the local host\r
-  @param [in] PortNumber  Tcp4 port number\r
-  @param [in] DebugFlags  Flags for debug messages\r
-  @param [out] ppPort     Buffer to receive new DT_PORT structure address\r
+  This routine returns the IPv4 address and TCP port number associated\r
+  with the local socket.\r
 \r
-  @retval EFI_SUCCESS - Socket successfully created\r
+  This routine is called by ::EslSocketGetLocalAddress to determine the\r
+  network address for the SOCK_STREAM or SOCK_SEQPACKET socket.\r
+\r
+  @param [in] pPort       Address of an ::ESL_PORT structure.\r
+\r
+  @param [out] pSockAddr  Network address to receive the local system address\r
+\r
+**/\r
+VOID\r
+EslTcp4LocalAddressGet (\r
+  IN ESL_PORT * pPort,\r
+  OUT struct sockaddr * pSockAddr\r
+  )\r
+{\r
+  struct sockaddr_in * pLocalAddress;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Return the local address\r
+  //\r
+  pTcp4 = &pPort->Context.Tcp4;\r
+  pLocalAddress = (struct sockaddr_in *)pSockAddr;\r
+  pLocalAddress->sin_family = AF_INET;\r
+  pLocalAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.StationPort );\r
+  CopyMem ( &pLocalAddress->sin_addr,\r
+            &pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0],\r
+            sizeof ( pLocalAddress->sin_addr ));\r
+\r
+  DBG_EXIT ( );\r
+}\r
+\r
+\r
+/**\r
+  Set the local port address.\r
+\r
+  This routine sets the local port address.\r
+\r
+  This support routine is called by ::EslSocketPortAllocate.\r
+\r
+  @param [in] pPort       Address of an ESL_PORT structure\r
+  @param [in] pSockAddr   Address of a sockaddr structure that contains the\r
+                          connection point on the local machine.  An IPv4 address\r
+                          of INADDR_ANY specifies that the connection is made to\r
+                          all of the network stacks on the platform.  Specifying a\r
+                          specific IPv4 address restricts the connection to the\r
+                          network stack supporting that address.  Specifying zero\r
+                          for the port causes the network layer to assign a port\r
+                          number from the dynamic range.  Specifying a specific\r
+                          port number causes the network layer to use that port.\r
+\r
+  @param [in] bBindTest   TRUE = run bind testing\r
+\r
+  @retval EFI_SUCCESS     The operation was successful\r
 \r
  **/\r
 EFI_STATUS\r
-EslTcpPortAllocate4 (\r
-  IN DT_SOCKET * pSocket,\r
-  IN DT_SERVICE * pService,\r
-  IN EFI_HANDLE ChildHandle,\r
-  IN CONST UINT8 * pIpAddress,\r
-  IN UINT16 PortNumber,\r
-  IN UINTN DebugFlags,\r
-  OUT DT_PORT ** ppPort\r
+EslTcp4LocalAddressSet (\r
+  IN ESL_PORT * pPort,\r
+  IN CONST struct sockaddr * pSockAddr,\r
+  IN BOOLEAN bBindTest\r
   )\r
 {\r
-  UINTN LengthInBytes;\r
   EFI_TCP4_ACCESS_POINT * pAccessPoint;\r
-  DT_LAYER * pLayer;\r
-  DT_PORT * pPort;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
+  CONST struct sockaddr_in * pIpAddress;\r
+  CONST UINT8 * pIpv4Address;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Use for/break instead of goto\r
-  for ( ; ; ) {\r
+  //  Validate the address\r
+  //\r
+  pIpAddress = (struct sockaddr_in *)pSockAddr;\r
+  if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) {\r
     //\r
-    //  Allocate a port structure\r
+    //  The local address must not be the broadcast address\r
     //\r
-    pLayer = &mEslLayer;\r
-    LengthInBytes = sizeof ( *pPort );\r
-    Status = gBS->AllocatePool ( EfiRuntimeServicesData,\r
-                                 LengthInBytes,\r
-                                 (VOID **)&pPort );\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
-                "ERROR - Failed to allocate the port structure, Status: %r\r\n",\r
-                Status ));\r
-      pSocket->errno = ENOMEM;\r
-      pPort = NULL;\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
+    Status = EFI_INVALID_PARAMETER;\r
+    pPort->pSocket->errno = EADDRNOTAVAIL;\r
+  }\r
+  else {\r
     //\r
-    //  Initialize the port\r
+    //  Set the local address\r
     //\r
-    ZeroMem ( pPort, LengthInBytes );\r
-    pPort->Signature = PORT_SIGNATURE;\r
-    pPort->pService = pService;\r
-    pPort->pSocket = pSocket;\r
-    pPort->pfnCloseStart = EslTcpPortCloseStart4;\r
-    pPort->DebugFlags = DebugFlags;\r
+    pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr;\r
+    pAccessPoint = &pPort->Context.Tcp4.ConfigData.AccessPoint;\r
+    pAccessPoint->StationAddress.Addr[0] = pIpv4Address[0];\r
+    pAccessPoint->StationAddress.Addr[1] = pIpv4Address[1];\r
+    pAccessPoint->StationAddress.Addr[2] = pIpv4Address[2];\r
+    pAccessPoint->StationAddress.Addr[3] = pIpv4Address[3];\r
 \r
     //\r
-    //  Allocate the receive event\r
+    //  Determine if the default address is used\r
     //\r
-    pTcp4 = &pPort->Context.Tcp4;\r
-    Status = gBS->CreateEvent (  EVT_NOTIFY_SIGNAL,\r
-                                 TPL_SOCKETS,\r
-                                 (EFI_EVENT_NOTIFY)EslTcpRxComplete4,\r
-                                 pPort,\r
-                                 &pTcp4->RxToken.CompletionToken.Event);\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to create the receive event, Status: %r\r\n",\r
-                Status ));\r
-      pSocket->errno = ENOMEM;\r
-      break;\r
-    }\r
-    DEBUG (( DEBUG_RX | DEBUG_POOL,\r
-              "0x%08x: Created receive event\r\n",\r
-              pTcp4->RxToken.CompletionToken.Event ));\r
+    pAccessPoint->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr );\r
 \r
     //\r
-    //  Allocate the urgent transmit event\r
+    //  Set the subnet mask\r
     //\r
-    Status = gBS->CreateEvent (  EVT_NOTIFY_SIGNAL,\r
-                                 TPL_SOCKETS,\r
-                                 (EFI_EVENT_NOTIFY)EslTcpTxOobComplete4,\r
-                                 pPort,\r
-                                 &pTcp4->TxOobToken.CompletionToken.Event);\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to create the urgent transmit event, Status: %r\r\n",\r
-                Status ));\r
-      pSocket->errno = ENOMEM;\r
-      break;\r
+    if ( pAccessPoint->UseDefaultAddress ) {\r
+      pAccessPoint->SubnetMask.Addr[0] = 0;\r
+      pAccessPoint->SubnetMask.Addr[1] = 0;\r
+      pAccessPoint->SubnetMask.Addr[2] = 0;\r
+      pAccessPoint->SubnetMask.Addr[3] = 0;\r
+    }\r
+    else {\r
+      pAccessPoint->SubnetMask.Addr[0] = 0xff;\r
+      pAccessPoint->SubnetMask.Addr[1] = ( 128 <= pAccessPoint->StationAddress.Addr[0]) ? 0xff : 0;\r
+      pAccessPoint->SubnetMask.Addr[2] = ( 192 <= pAccessPoint->StationAddress.Addr[0]) ? 0xff : 0;\r
+      pAccessPoint->SubnetMask.Addr[3] = ( 224 <= pAccessPoint->StationAddress.Addr[0]) ? 0xff : 0;\r
     }\r
-    DEBUG (( DEBUG_CLOSE | DEBUG_POOL,\r
-              "0x%08x: Created urgent transmit event\r\n",\r
-              pTcp4->TxOobToken.CompletionToken.Event ));\r
 \r
     //\r
-    //  Allocate the normal transmit event\r
+    //  Validate the IP address\r
     //\r
-    Status = gBS->CreateEvent (  EVT_NOTIFY_SIGNAL,\r
-                                 TPL_SOCKETS,\r
-                                 (EFI_EVENT_NOTIFY)EslTcpTxComplete4,\r
-                                 pPort,\r
-                                 &pTcp4->TxToken.CompletionToken.Event);\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to create the normal transmit event, Status: %r\r\n",\r
-                Status ));\r
-      pSocket->errno = ENOMEM;\r
-      break;\r
+    pAccessPoint->StationPort = 0;\r
+    Status = bBindTest ? EslSocketBindTest ( pPort, EADDRNOTAVAIL )\r
+                       : EFI_SUCCESS;\r
+    if ( !EFI_ERROR ( Status )) {\r
+      //\r
+      //  Set the port number\r
+      //\r
+      pAccessPoint->StationPort = SwapBytes16 ( pIpAddress->sin_port );\r
+      pPort->pSocket->bAddressSet = TRUE;\r
+\r
+      //\r
+      //  Display the local address\r
+      //\r
+      DEBUG (( DEBUG_BIND,\r
+                "0x%08x: Port, Local TCP4 Address: %d.%d.%d.%d:%d\r\n",\r
+                pPort,\r
+                pAccessPoint->StationAddress.Addr[0],\r
+                pAccessPoint->StationAddress.Addr[1],\r
+                pAccessPoint->StationAddress.Addr[2],\r
+                pAccessPoint->StationAddress.Addr[3],\r
+                pAccessPoint->StationPort ));\r
     }\r
-    DEBUG (( DEBUG_CLOSE | DEBUG_POOL,\r
-              "0x%08x: Created normal transmit event\r\n",\r
-              pTcp4->TxToken.CompletionToken.Event ));\r
+  }\r
 \r
-    //\r
-    //  Allocate the close event\r
-    //\r
-    Status = gBS->CreateEvent (  EVT_NOTIFY_SIGNAL,\r
-                                 TPL_SOCKETS,\r
-                                 (EFI_EVENT_NOTIFY)EslTcpPortCloseComplete4,\r
-                                 pPort,\r
-                                 &pTcp4->CloseToken.CompletionToken.Event);\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to create the close event, Status: %r\r\n",\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Free a receive packet\r
+\r
+  This routine performs the network specific operations necessary\r
+  to free a receive packet.\r
+\r
+  This routine is called by ::EslSocketPortCloseTxDone to free a\r
+  receive packet.\r
+\r
+  @param [in] pPacket         Address of an ::ESL_PACKET structure.\r
+  @param [in, out] pRxBytes   Address of the count of RX bytes\r
+\r
+**/\r
+VOID\r
+EslTcp4PacketFree (\r
+  IN ESL_PACKET * pPacket,\r
+  IN OUT size_t * pRxBytes\r
+  )\r
+{\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Account for the receive bytes\r
+  //\r
+  *pRxBytes -= pPacket->Op.Tcp4Rx.RxData.DataLength;\r
+  DBG_EXIT ( );\r
+}\r
+\r
+\r
+/**\r
+  Initialize the network specific portions of an ::ESL_PORT structure.\r
+\r
+  This routine initializes the network specific portions of an\r
+  ::ESL_PORT structure for use by the socket.\r
+\r
+  This support routine is called by ::EslSocketPortAllocate\r
+  to connect the socket with the underlying network adapter\r
+  running the TCPv4 protocol.\r
+\r
+  @param [in] pPort       Address of an ESL_PORT structure\r
+  @param [in] DebugFlags  Flags for debug messages\r
+\r
+  @retval EFI_SUCCESS - Socket successfully created\r
+\r
+ **/\r
+EFI_STATUS\r
+EslTcp4PortAllocate (\r
+  IN ESL_PORT * pPort,\r
+  IN UINTN DebugFlags\r
+  )\r
+{\r
+  EFI_TCP4_ACCESS_POINT * pAccessPoint;\r
+  ESL_SOCKET * pSocket;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Use for/break instead of goto\r
+  for ( ; ; ) {\r
+    //\r
+    //  Allocate the close event\r
+    //\r
+    pSocket = pPort->pSocket;\r
+    pTcp4 = &pPort->Context.Tcp4;\r
+    Status = gBS->CreateEvent (  EVT_NOTIFY_SIGNAL,\r
+                                 TPL_SOCKETS,\r
+                                 (EFI_EVENT_NOTIFY)EslSocketPortCloseComplete,\r
+                                 pPort,\r
+                                 &pTcp4->CloseToken.CompletionToken.Event);\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR | DebugFlags,\r
+                "ERROR - Failed to create the close event, Status: %r\r\n",\r
                 Status ));\r
       pSocket->errno = ENOMEM;\r
       break;\r
@@ -1492,7 +1288,7 @@ EslTcpPortAllocate4 (
     //\r
     Status = gBS->CreateEvent (  EVT_NOTIFY_SIGNAL,\r
                                  TPL_SOCKETS,\r
-                                 (EFI_EVENT_NOTIFY)EslTcpConnectComplete4,\r
+                                 (EFI_EVENT_NOTIFY)EslTcp4ConnectComplete,\r
                                  pPort,\r
                                  &pTcp4->ConnectToken.CompletionToken.Event);\r
     if ( EFI_ERROR ( Status )) {\r
@@ -1507,89 +1303,30 @@ EslTcpPortAllocate4 (
               pTcp4->ConnectToken.CompletionToken.Event ));\r
 \r
     //\r
-    //  Open the port protocol\r
-    //\r
-    Status = gBS->OpenProtocol (\r
-                    ChildHandle,\r
-                    &gEfiTcp4ProtocolGuid,\r
-                    (VOID **) &pTcp4->pProtocol,\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 gEfiTcp4ProtocolGuid on controller 0x%08x\r\n",\r
-                pTcp4->Handle ));\r
-      pSocket->errno = EEXIST;\r
-      break;\r
-    }\r
-    DEBUG (( DebugFlags,\r
-              "0x%08x: gEfiTcp4ProtocolGuid opened on controller 0x%08x\r\n",\r
-              pTcp4->pProtocol,\r
-              ChildHandle ));\r
-\r
-    //\r
-    //  Set the port address\r
-    //\r
-    pTcp4->Handle = ChildHandle;\r
-    pAccessPoint = &pPort->Context.Tcp4.ConfigData.AccessPoint;\r
-    pAccessPoint->StationPort = PortNumber;\r
-    if (( 0 == pIpAddress[0])\r
-      && ( 0 == pIpAddress[1])\r
-      && ( 0 == pIpAddress[2])\r
-      && ( 0 == pIpAddress[3])) {\r
-      pAccessPoint->UseDefaultAddress = TRUE;\r
-    }\r
-    else {\r
-      pAccessPoint->StationAddress.Addr[0] = pIpAddress[0];\r
-      pAccessPoint->StationAddress.Addr[1] = pIpAddress[1];\r
-      pAccessPoint->StationAddress.Addr[2] = pIpAddress[2];\r
-      pAccessPoint->StationAddress.Addr[3] = pIpAddress[3];\r
-      pAccessPoint->SubnetMask.Addr[0] = 0xff;\r
-      pAccessPoint->SubnetMask.Addr[1] = 0xff;\r
-      pAccessPoint->SubnetMask.Addr[2] = 0xff;\r
-      pAccessPoint->SubnetMask.Addr[3] = 0xff;\r
-    }\r
-    pAccessPoint->ActiveFlag = FALSE;\r
-    pTcp4->ConfigData.TimeToLive = 255;\r
-\r
-    //\r
-    //  Verify the socket layer synchronization\r
-    //\r
-    VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-    //\r
-    //  Add this port to the socket\r
+    //  Initialize the port\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
+    pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Tcp4Tx.TxData );\r
+    pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Tcp4Tx.CompletionToken.Event );\r
+    pSocket->TxTokenOffset = OFFSET_OF ( EFI_TCP4_IO_TOKEN, Packet.TxData );\r
 \r
     //\r
-    //  Add this port to the service\r
+    //  Save the cancel, receive and transmit addresses\r
+    //  pPort->pfnRxCancel = NULL; since the UEFI implementation returns EFI_UNSUPPORTED\r
     //\r
-    pPort->pLinkService = pService->pPortList;\r
-    pService->pPortList = pPort;\r
+    pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.TCPv4->Configure;\r
+    pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.TCPv4->Poll;\r
+    pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Receive;\r
+    pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Transmit;\r
 \r
     //\r
-    //  Return the port\r
+    //  Set the configuration flags\r
     //\r
-    *ppPort = pPort;\r
+    pAccessPoint = &pPort->Context.Tcp4.ConfigData.AccessPoint;\r
+    pAccessPoint->ActiveFlag = FALSE;\r
+    pTcp4->ConfigData.TimeToLive = 255;\r
     break;\r
   }\r
 \r
-  //\r
-  //  Clean up after the error if necessary\r
-  //\r
-  if (( EFI_ERROR ( Status )) && ( NULL != pPort )) {\r
-    //\r
-    //  Close the port\r
-    //\r
-    EslTcpPortClose4 ( pPort );\r
-  }\r
   //\r
   //  Return the operation status\r
   //\r
@@ -1601,127 +1338,35 @@ EslTcpPortAllocate4 (
 /**\r
   Close a TCP4 port.\r
 \r
-  This routine releases the resources allocated by\r
-  ::TcpPortAllocate4().\r
-  \r
-  @param [in] pPort       Address of the port structure.\r
+  This routine releases the network specific resources allocated by\r
+  ::EslTcp4PortAllocate.\r
+\r
+  This routine is called by ::EslSocketPortClose.\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
-EslTcpPortClose4 (\r
-  IN DT_PORT * pPort\r
+EslTcp4PortClose (\r
+  IN ESL_PORT * pPort\r
   )\r
 {\r
   UINTN DebugFlags;\r
-  DT_LAYER * pLayer;\r
-  DT_PACKET * pPacket;\r
-  DT_PORT * pPreviousPort;\r
-  DT_SERVICE * pService;\r
-  DT_SOCKET * pSocket;\r
-  EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
   EFI_STATUS Status;\r
-  \r
-  DBG_ENTER ( );\r
 \r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
+  DBG_ENTER ( );\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
-  //\r
-  pService = pPort->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
-  //  Empty the urgent receive queue\r
-  //\r
   pTcp4 = &pPort->Context.Tcp4;\r
-  while ( NULL != pSocket->pRxOobPacketListHead ) {\r
-    pPacket = pSocket->pRxOobPacketListHead;\r
-    pSocket->pRxOobPacketListHead = pPacket->pNext;\r
-    pSocket->RxOobBytes -= pPacket->Op.Tcp4Rx.ValidBytes;\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->RxBytes -= pPacket->Op.Tcp4Rx.ValidBytes;\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
   //  Done with the connect event\r
@@ -1777,121 +1422,6 @@ EslTcpPortClose4 (
     }\r
   }\r
 \r
-  //\r
-  //  Done with the receive event\r
-  //\r
-  if ( NULL != pTcp4->RxToken.CompletionToken.Event ) {\r
-    Status = gBS->CloseEvent ( pTcp4->RxToken.CompletionToken.Event );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DebugFlags | DEBUG_POOL,\r
-                "0x%08x: Closed receive event\r\n",\r
-                pTcp4->RxToken.CompletionToken.Event ));\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to close the receive event, Status: %r\r\n",\r
-                Status ));\r
-      ASSERT ( EFI_SUCCESS == Status );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Done with the normal transmit event\r
-  //\r
-  if ( NULL != pTcp4->TxToken.CompletionToken.Event ) {\r
-    Status = gBS->CloseEvent ( pTcp4->TxToken.CompletionToken.Event );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DebugFlags | DEBUG_POOL,\r
-                "0x%08x: Closed normal transmit event\r\n",\r
-                pTcp4->TxToken.CompletionToken.Event ));\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to close the normal transmit event, Status: %r\r\n",\r
-                Status ));\r
-      ASSERT ( EFI_SUCCESS == Status );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Done with the urgent transmit event\r
-  //\r
-  if ( NULL != pTcp4->TxOobToken.CompletionToken.Event ) {\r
-    Status = gBS->CloseEvent ( pTcp4->TxOobToken.CompletionToken.Event );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DebugFlags | DEBUG_POOL,\r
-                "0x%08x: Closed urgent transmit event\r\n",\r
-                pTcp4->TxOobToken.CompletionToken.Event ));\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to close the urgent transmit event, Status: %r\r\n",\r
-                Status ));\r
-      ASSERT ( EFI_SUCCESS == Status );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Done with the TCP protocol\r
-  //\r
-  pTcp4Service = pService->pInterface;\r
-  if ( NULL != pTcp4->pProtocol ) {\r
-    Status = gBS->CloseProtocol ( pTcp4->Handle,\r
-                                  &gEfiTcp4ProtocolGuid,\r
-                                  pLayer->ImageHandle,\r
-                                  NULL );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DebugFlags,\r
-                "0x%08x: gEfiTcp4ProtocolGuid closed on controller 0x%08x\r\n",\r
-                pTcp4->pProtocol,\r
-                pTcp4->Handle ));\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to close gEfiTcp4ProtocolGuid opened on controller 0x%08x, Status: %r\r\n",\r
-                pTcp4->Handle,\r
-                Status ));\r
-      ASSERT ( EFI_SUCCESS == Status );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Done with the TCP port\r
-  //\r
-  if ( NULL != pTcp4->Handle ) {\r
-    Status = pTcp4Service->DestroyChild ( pTcp4Service,\r
-                                          pTcp4->Handle );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DebugFlags | DEBUG_POOL,\r
-                "0x%08x: Tcp4 port handle destroyed\r\n",\r
-                pTcp4->Handle ));\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,\r
-                "ERROR - Failed to destroy the Tcp4 port handle, Status: %r\r\n",\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
   //  Return the operation status\r
   //\r
@@ -1901,94 +1431,52 @@ EslTcpPortClose4 (
 \r
 \r
 /**\r
-  Process the port close completion\r
-\r
-  @param  Event         The close completion event\r
-\r
-  @param  pPort         The DT_PORT structure address\r
-\r
-**/\r
-VOID\r
-EslTcpPortCloseComplete4 (\r
-  IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
-  )\r
-{\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Update the port state\r
-  //\r
-  pPort->State = PORT_STATE_CLOSE_DONE;\r
+  Perform the network specific close operation on the port.\r
 \r
-  //\r
-  //  Release the resources once the receive operation completes\r
-  //\r
-  Status = EslTcpPortCloseRxDone4 ( pPort );\r
-  DBG_EXIT_STATUS ( Status );\r
-}\r
+  This routine performs a cancel operations on the TCPv4 port to\r
+  shutdown the receive operations on the port.\r
 \r
+  This routine is called by the ::EslSocketPortCloseTxDone\r
+  routine after the port completes all of the transmission.\r
 \r
-/**\r
-  Start the close operation on a TCP4 port, state 1.\r
-\r
-  Closing a port goes through the following states:\r
-  1. Port close starting - Mark the port as closing and wait for transmission to complete\r
-  2. Port TX close done - Transmissions complete, close the port and abort the receives\r
-  3. Port RX close done - Receive operations complete, close the port\r
-  4. Port closed - Release the port resources\r
-  \r
-  @param [in] pPort       Address of the port structure.\r
-  @param [in] bCloseNow   Set TRUE to abort active transfers\r
-  @param [in] DebugFlags  Flags for debug messages\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 has started the closing process\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
-EslTcpPortCloseStart4 (\r
-  IN DT_PORT * pPort,\r
-  IN BOOLEAN bCloseNow,\r
-  IN UINTN DebugFlags\r
+EslTcp4PortCloseOp (\r
+  IN ESL_PORT * pPort\r
   )\r
 {\r
-  DT_SOCKET * pSocket;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
+  EFI_TCP4_PROTOCOL * pTcp4Protocol;\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
+  //  Close the configured port\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
+  Status = EFI_SUCCESS;\r
+  pTcp4 = &pPort->Context.Tcp4;\r
+  pTcp4Protocol = pPort->pProtocol.TCPv4;\r
+  pTcp4->CloseToken.AbortOnClose = pPort->bCloseNow;\r
+  Status = pTcp4Protocol->Close ( pTcp4Protocol,\r
+                                  &pTcp4->CloseToken );\r
+  if ( !EFI_ERROR ( Status )) {\r
+    DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,\r
+              "0x%08x: Port 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 = EslTcpPortCloseTxDone4 ( pPort );\r
+  }\r
+  else {\r
+    DEBUG (( DEBUG_ERROR | pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,\r
+             "ERROR - Close failed on port 0x%08x, Status: %r\r\n",\r
+             pPort,\r
+             Status ));\r
   }\r
 \r
   //\r
@@ -2000,883 +1488,343 @@ EslTcpPortCloseStart4 (
 \r
 \r
 /**\r
-  Port close state 3\r
+  Receive data from a network connection.\r
 \r
-  Continue the close operation after the receive is complete.\r
+  This routine attempts to return buffered data to the caller.  The\r
+  data is removed from the urgent queue if the message flag MSG_OOB\r
+  is specified, otherwise data is removed from the normal queue.\r
+  See the \ref ReceiveEngine section.\r
 \r
-  @param [in] pPort       Address of the port structure.\r
+  This routine is called by ::EslSocketReceive to handle the network\r
+  specific receive operation to support SOCK_STREAM and SOCK_SEQPACKET\r
+  sockets.\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
+  @param [in] pPort           Address of an ::ESL_PORT structure.\r
 \r
-**/\r
-EFI_STATUS\r
-EslTcpPortCloseRxDone4 (\r
-  IN DT_PORT * pPort\r
-  )\r
-{\r
-  PORT_STATE PortState;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
-  EFI_STATUS Status;\r
+  @param [in] pPacket         Address of an ::ESL_PACKET structure.\r
 \r
-  DBG_ENTER ( );\r
+  @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed\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
-  PortState = pPort->State;\r
-  if (( PORT_STATE_CLOSE_TX_DONE == PortState )\r
-    || ( PORT_STATE_CLOSE_DONE == PortState )) {\r
-    //\r
-    //  Determine if the receive operation is pending\r
-    //\r
-    Status = EFI_NOT_READY;\r
-    pTcp4 = &pPort->Context.Tcp4;\r
-    if ( NULL == pTcp4->pReceivePending ) {\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
-      //  Determine if the close operation has completed\r
-      //\r
-      if ( PORT_STATE_CLOSE_DONE == PortState ) {\r
-        //\r
-        //  The close operation has completed\r
-        //  Release the port resources\r
-        //\r
-        Status = EslTcpPortClose4 ( pPort );\r
-      }\r
-      else\r
-      {\r
-        DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                  "0x%08x: Port Close: Close operation still pending!\r\n",\r
-                  pPort ));\r
-      }\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                "0x%08x: Port Close: Receive still pending!\r\n",\r
-                pPort ));\r
-    }\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
-  Continue the close operation after the transmission is complete.\r
-\r
-  @param [in] pPort       Address of the 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
-EslTcpPortCloseTxDone4 (\r
-  IN DT_PORT * pPort\r
-  )\r
-{\r
-  DT_SOCKET * pSocket;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
-  EFI_TCP4_PROTOCOL * pTcp4Protocol;\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
-         || (( 0 == pSocket->TxOobBytes )\r
-                && ( 0 == pSocket->TxBytes ))) {\r
-      //\r
-      //  Start the close operation on the port\r
-      //\r
-      pTcp4 = &pPort->Context.Tcp4;\r
-      pTcp4->CloseToken.AbortOnClose = FALSE;\r
-      pTcp4Protocol = pTcp4->pProtocol;\r
-      if ( !pTcp4->bConfigured ) {\r
-        //\r
-        //  Skip the close operation since the port is not\r
-        //  configured\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
-        Status = EFI_SUCCESS;\r
-      }\r
-      else {\r
-        //\r
-        //  Close the configured port\r
-        //\r
-        Status = pTcp4Protocol->Close ( pTcp4Protocol,\r
-                                        &pTcp4->CloseToken );\r
-        if ( !EFI_ERROR ( Status )) {\r
-          DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,\r
-                    "0x%08x: Port close started\r\n",\r
-                    pPort ));\r
-\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
-        else {\r
-          DEBUG (( DEBUG_ERROR | pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,\r
-                   "ERROR - Close failed on port 0x%08x, Status: %r\r\n",\r
-                   pPort,\r
-                   Status ));\r
-          ASSERT ( EFI_SUCCESS == Status );\r
-        }\r
-      }\r
-\r
-      //\r
-      //  Determine if the receive operation is pending\r
-      //\r
-      if ( !EFI_ERROR ( Status )) {\r
-        Status = EslTcpPortCloseRxDone4 ( pPort );\r
-      }\r
-    }\r
-    else {\r
-      //\r
-      //  Transmissions are still active, exit\r
-      //\r
-      DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                "0x%08x: Port Close: Transmits are still pending!\r\n",\r
-                pPort ));\r
-      Status = EFI_NOT_READY;\r
-      pSocket->errno = EAGAIN;\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Receive data from a network connection.\r
-\r
-\r
-  @param [in] pSocket         Address of a DT_SOCKET structure\r
-  \r
-  @param [in] Flags           Message control flags\r
-  \r
   @param [in] BufferLength    Length of the the buffer\r
-  \r
+\r
   @param [in] pBuffer         Address of a buffer to receive the data.\r
-  \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
+  @param [out] pSkipBytes     Address to receive the number of bytes skipped\r
 \r
-  @retval EFI_SUCCESS - Socket data successfully received\r
+  @return   Returns the address of the next free byte in the buffer.\r
 \r
  **/\r
-EFI_STATUS\r
-EslTcpReceive4 (\r
-  IN DT_SOCKET * pSocket,\r
-  IN INT32 Flags,\r
+UINT8 *\r
+EslTcp4Receive (\r
+  IN ESL_PORT * pPort,\r
+  IN ESL_PACKET * pPacket,\r
+  IN BOOLEAN * pbConsumePacket,\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
+  OUT size_t * pSkipBytes\r
   )\r
 {\r
-  socklen_t AddressLength;\r
-  size_t BytesToCopy;\r
-  in_addr_t IpAddress;\r
-  size_t LengthInBytes;\r
-  DT_PACKET * pPacket;\r
-  DT_PORT * pPort;\r
-  DT_PACKET ** ppQueueHead;\r
-  DT_PACKET ** ppQueueTail;\r
+  size_t DataLength;\r
   struct sockaddr_in * pRemoteAddress;\r
-  size_t * pRxDataBytes;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
-  struct sockaddr_in RemoteAddress;\r
-  EFI_STATUS Status;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Assume failure\r
-  //\r
-  Status = EFI_UNSUPPORTED;\r
-  pSocket->errno = ENOTCONN;\r
-\r
-  //\r
-  //  Verify that the socket is connected\r
+  //  Return the remote system address if requested\r
   //\r
-  if (( SOCKET_STATE_CONNECTED == pSocket->State )\r
-    || ( PORT_STATE_RX_ERROR == pSocket->State )) {\r
+  if ( NULL != pAddress ) {\r
     //\r
-    //  Locate the port\r
+    //  Build the remote address\r
     //\r
-    pPort = pSocket->pPortList;\r
-    if ( NULL != pPort ) {\r
-      //\r
-      //  Determine the queue head\r
-      //\r
-      pTcp4 = &pPort->Context.Tcp4;\r
-      if ( 0 != ( Flags & MSG_OOB )) {\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
-      pPacket = *ppQueueHead;\r
-      if ( NULL != pPacket ) {\r
-        //\r
-        //  Validate the return address parameters\r
-        //\r
-        if (( NULL == pAddress ) || ( NULL != pAddressLength )) {\r
-          //\r
-          //  Return the remote system address if requested\r
-          //\r
-          if ( NULL != pAddress ) {\r
-            //\r
-            //  Build the remote address\r
-            //\r
-            ZeroMem ( &RemoteAddress, sizeof ( RemoteAddress ));\r
-            RemoteAddress.sin_len = sizeof ( RemoteAddress );\r
-            RemoteAddress.sin_family = AF_INET;\r
-            IpAddress = pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3];\r
-            IpAddress <<= 8;\r
-            IpAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2];\r
-            IpAddress <<= 8;\r
-            IpAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1];\r
-            IpAddress <<= 8;\r
-            IpAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0];\r
-            RemoteAddress.sin_addr.s_addr = IpAddress;\r
-            RemoteAddress.sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );\r
-\r
-            //\r
-            //  Copy the address\r
-            //\r
-            pRemoteAddress = (struct sockaddr_in *)pAddress;\r
-            AddressLength = sizeof ( *pRemoteAddress );\r
-            if ( AddressLength > *pAddressLength ) {\r
-              AddressLength = *pAddressLength;\r
-            }\r
-            CopyMem ( pRemoteAddress,\r
-                      &RemoteAddress,\r
-                      AddressLength );\r
-\r
-            //\r
-            //  Update the address length\r
-            //\r
-            *pAddressLength = AddressLength;\r
-          }\r
-\r
-          //\r
-          //  Copy the received data\r
-          //\r
-          LengthInBytes = 0;\r
-          do {\r
-            //\r
-            //  Determine the amount of received data\r
-            //\r
-            BytesToCopy = pPacket->Op.Tcp4Rx.ValidBytes;\r
-            if (( BufferLength - LengthInBytes ) < BytesToCopy ) {\r
-              BytesToCopy = BufferLength - LengthInBytes;\r
-            }\r
-            LengthInBytes += BytesToCopy;\r
-\r
-            //\r
-            //  Move the data into the buffer\r
-            //\r
-            DEBUG (( DEBUG_RX,\r
-                      "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",\r
-                      pPort,\r
-                      pPacket,\r
-                      pBuffer,\r
-                      BytesToCopy ));\r
-            CopyMem ( pBuffer, pPacket->Op.Tcp4Rx.pBuffer, BytesToCopy );\r
-\r
-            //\r
-            //  Determine if the data is being read\r
-            //\r
-            if ( 0 == ( Flags & MSG_PEEK )) {\r
-              //\r
-              //  Account for the bytes consumed\r
-              //\r
-              pPacket->Op.Tcp4Rx.pBuffer += BytesToCopy;\r
-              pPacket->Op.Tcp4Rx.ValidBytes -= BytesToCopy;\r
-              *pRxDataBytes -= BytesToCopy;\r
-              DEBUG (( DEBUG_RX,\r
-                        "0x%08x: Port account for 0x%08x bytes\r\n",\r
-                        pPort,\r
-                        BytesToCopy ));\r
-\r
-              //\r
-              //  Determine if the entire packet was consumed\r
-              //\r
-              if (( 0 == pPacket->Op.Tcp4Rx.ValidBytes )\r
-                || ( SOCK_STREAM != pSocket->Type )) {\r
-                //\r
-                //  All done with this packet\r
-                //  Account for any discarded data\r
-                //\r
-                *pRxDataBytes -= pPacket->Op.Tcp4Rx.ValidBytes;\r
-                if ( 0 != pPacket->Op.Tcp4Rx.ValidBytes ) {\r
-                  DEBUG (( DEBUG_RX,\r
-                            "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n",\r
-                            pPort,\r
-                            pPacket->Op.Tcp4Rx.ValidBytes ));\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 this receive operation if necessary\r
-                //\r
-                if (( NULL == pTcp4->pReceivePending )\r
-                  && ( MAX_RX_DATA > pSocket->RxBytes )) {\r
-                    EslTcpRxStart4 ( pPort );\r
-                }\r
-              }\r
-            }\r
-\r
-            //\r
-            //  Get the next packet\r
-            //\r
-            pPacket = *ppQueueHead;\r
-          } while (( SOCK_STREAM == pSocket->Type )\r
-                && ( NULL != pPacket )\r
-                && ( 0 == ( Flags & MSG_PEEK ))\r
-                && ( BufferLength > LengthInBytes ));\r
-\r
-          //\r
-          //  Return the data length\r
-          //\r
-          *pDataLength = LengthInBytes;\r
-\r
-          //\r
-          //  Successful operation\r
-          //\r
-          Status = EFI_SUCCESS;\r
-          pSocket->errno = 0;\r
-        }\r
-        else {\r
-          //\r
-          //  Bad return address pointer and length\r
-          //\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EINVAL;\r
-        }\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
-          switch ( Status ) {\r
-          default:\r
-            pSocket->errno = EIO;\r
-            break;\r
-          \r
-          case EFI_CONNECTION_FIN:\r
-            pSocket->errno = ESHUTDOWN;\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
-          pSocket->RxError = EFI_SUCCESS;\r
-        }\r
-        else {\r
-          Status = EFI_NOT_READY;\r
-          pSocket->errno = EAGAIN;\r
-        }\r
-      }\r
-    }\r
+    pTcp4 = &pPort->Context.Tcp4;\r
+    DEBUG (( DEBUG_RX,\r
+              "Getting packet remote address: %d.%d.%d.%d:%d\r\n",\r
+              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],\r
+              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],\r
+              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],\r
+              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],\r
+              pTcp4->ConfigData.AccessPoint.RemotePort ));\r
+    pRemoteAddress = (struct sockaddr_in *)pAddress;\r
+    CopyMem ( &pRemoteAddress->sin_addr,\r
+              &pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],\r
+              sizeof ( pRemoteAddress->sin_addr ));\r
+    pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );\r
   }\r
 \r
   //\r
-  //  Return the operation status\r
+  //  Determine the amount of received data\r
   //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Cancel the receive operations\r
-\r
-  @param [in] pSocket         Address of a DT_SOCKET structure\r
-  \r
-  @retval EFI_SUCCESS - The cancel was successful\r
-\r
- **/\r
-EFI_STATUS\r
-EslTcpRxCancel4 (\r
-  IN DT_SOCKET * pSocket\r
-  )\r
-{\r
-  DT_PACKET * pPacket;\r
-  DT_PORT * pPort;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
-  EFI_TCP4_PROTOCOL * pTcp4Protocol;\r
-  EFI_STATUS Status;\r
+  DataLength = pPacket->ValidBytes;\r
+  if ( BufferLength < DataLength ) {\r
+    DataLength = BufferLength;\r
+  }\r
 \r
-  DBG_ENTER ( );\r
+  //\r
+  //  Move the data into the buffer\r
+  //\r
+  DEBUG (( DEBUG_RX,\r
+            "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",\r
+            pPort,\r
+            pPacket,\r
+            pBuffer,\r
+            DataLength ));\r
+  CopyMem ( pBuffer, pPacket->pBuffer, DataLength );\r
 \r
   //\r
-  //  Assume failure\r
+  //  Set the next buffer address\r
   //\r
-  Status = EFI_NOT_FOUND;\r
+  pBuffer += DataLength;\r
 \r
   //\r
-  //  Locate the port\r
+  //  Determine if the data is being read\r
   //\r
-  pPort = pSocket->pPortList;\r
-  if ( NULL != pPort ) {\r
+  if ( *pbConsumePacket ) {\r
     //\r
-    //  Determine if a receive is pending\r
+    //  Account for the bytes consumed\r
     //\r
-    pTcp4 = &pPort->Context.Tcp4;\r
-    pPacket = pTcp4->pReceivePending;\r
-    if ( NULL != pPacket ) {\r
+    pPacket->pBuffer += DataLength;\r
+    pPacket->ValidBytes -= DataLength;\r
+    DEBUG (( DEBUG_RX,\r
+              "0x%08x: Port account for 0x%08x bytes\r\n",\r
+              pPort,\r
+              DataLength ));\r
+\r
+    //\r
+    //  Determine if the entire packet was consumed\r
+    //\r
+    if (( 0 == pPacket->ValidBytes )\r
+      || ( SOCK_STREAM != pPort->pSocket->Type )) {\r
       //\r
-      //  Attempt to cancel the receive operation\r
+      //  All done with this packet\r
+      //  Account for any discarded data\r
       //\r
-      pTcp4Protocol = pTcp4->pProtocol;\r
-      Status = pTcp4Protocol->Cancel ( pTcp4Protocol,\r
-                                       &pTcp4->RxToken.CompletionToken );\r
-      if ( EFI_NOT_FOUND == Status ) {\r
-        //\r
-        //  The receive is complete\r
-        //\r
-        Status = EFI_SUCCESS;\r
-      }\r
+      *pSkipBytes = pPacket->ValidBytes;\r
+    }\r
+    else\r
+    {\r
+      //\r
+      //  More data to consume later\r
+      //\r
+      *pbConsumePacket = FALSE;\r
     }\r
   }\r
 \r
   //\r
-  //  Return the operation status\r
+  //  Return the data length and the buffer address\r
   //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
+  *pDataLength = DataLength;\r
+  DBG_EXIT_HEX ( pBuffer );\r
+  return pBuffer;\r
 }\r
 \r
 \r
 /**\r
-  Process the receive completion\r
+  Get the remote socket address.\r
 \r
-  Buffer the data that was just received.\r
+  This routine returns the address of the remote connection point\r
+  associated with the SOCK_STREAM or SOCK_SEQPACKET socket.\r
+\r
+  This routine is called by ::EslSocketGetPeerAddress to detemine\r
+  the TCPv4 address and por number associated with the network adapter.\r
 \r
-  @param  Event         The receive completion event\r
+  @param [in] pPort       Address of an ::ESL_PORT structure.\r
 \r
-  @param  pPort         The DT_PORT structure address\r
+  @param [out] pAddress   Network address to receive the remote system address\r
 \r
 **/\r
 VOID\r
-EslTcpRxComplete4 (\r
-  IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
+EslTcp4RemoteAddressGet (\r
+  IN ESL_PORT * pPort,\r
+  OUT struct sockaddr * pAddress\r
   )\r
-{\r
-  BOOLEAN bUrgent;\r
-  size_t LengthInBytes;\r
-  DT_PACKET * pPacket;\r
-  DT_PACKET * pPrevious;\r
-  DT_SOCKET * pSocket;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Mark this receive complete\r
-  //\r
-  pTcp4 = &pPort->Context.Tcp4;\r
-  pPacket = pTcp4->pReceivePending;\r
-  pTcp4->pReceivePending = NULL;\r
-\r
-  //\r
-  //  Determine if this receive was successful\r
-  //\r
-  pSocket = pPort->pSocket;\r
-  Status = pTcp4->RxToken.CompletionToken.Status;\r
-  if (( !EFI_ERROR ( Status )) && ( !pSocket->bRxDisable )) {\r
-    //\r
-    //  Set the buffer size and address\r
-    //\r
-    pPacket->Op.Tcp4Rx.pBuffer = pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer;\r
-    LengthInBytes = pPacket->Op.Tcp4Rx.RxData.DataLength;\r
-    pPacket->Op.Tcp4Rx.ValidBytes = LengthInBytes;\r
-    pPacket->pNext = NULL;\r
-\r
-    //\r
-    //  Queue this packet\r
-    //\r
-    bUrgent = pPacket->Op.Tcp4Rx.RxData.UrgentFlag;\r
-    if ( bUrgent ) {\r
-      //\r
-      //  Add packet to the urgent list\r
-      //\r
-      pPrevious = pSocket->pRxOobPacketListTail;\r
-      if ( NULL == pPrevious ) {\r
-        pSocket->pRxOobPacketListHead = pPacket;\r
-      }\r
-      else {\r
-        pPrevious->pNext = pPacket;\r
-      }\r
-      pSocket->pRxOobPacketListTail = pPacket;\r
-\r
-      //\r
-      //  Account for the urgent data\r
-      //\r
-      pSocket->RxOobBytes += LengthInBytes;\r
-    }\r
-    else {\r
-      //\r
-      //  Add packet to the normal list\r
-      //\r
-      pPrevious = pSocket->pRxPacketListTail;\r
-      if ( NULL == pPrevious ) {\r
-        pSocket->pRxPacketListHead = pPacket;\r
-      }\r
-      else {\r
-        pPrevious->pNext = pPacket;\r
-      }\r
-      pSocket->pRxPacketListTail = pPacket;\r
-\r
-      //\r
-      //  Account for the normal data\r
-      //\r
-      pSocket->RxBytes += LengthInBytes;\r
-    }\r
-\r
-    //\r
-    //  Log the received data\r
-    //\r
-    DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-              "0x%08x: Packet queued on port 0x%08x with 0x%08x bytes of %s data\r\n",\r
-              pPacket,\r
-              pPort,\r
-              LengthInBytes,\r
-              bUrgent ? L"urgent" : L"normal" ));\r
-\r
-    //\r
-    //  Attempt to restart this receive operation\r
-    //\r
-    if ( pSocket->MaxRxBuf > pSocket->RxBytes ) {\r
-      EslTcpRxStart4 ( 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
-  {\r
-    DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-              "ERROR - Receiving packet 0x%08x, on port 0x%08x, Status:%r\r\n",\r
-              pPacket,\r
-              pPort,\r
-              Status ));\r
+{\r
+  struct sockaddr_in * pRemoteAddress;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
 \r
-    //\r
-    //  Receive error, free the packet save the error\r
-    //\r
-    EslSocketPacketFree ( pPacket, DEBUG_RX );\r
-    if ( !EFI_ERROR ( pSocket->RxError )) {\r
-      pSocket->RxError = Status;\r
-    }\r
+  DBG_ENTER ( );\r
 \r
-    //\r
-    //  Update the port state\r
-    //\r
-    if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {\r
-      EslTcpPortCloseRxDone4 ( pPort );\r
-    }\r
-    else {\r
-      if ( EFI_ERROR ( Status )) {\r
-        pPort->State = PORT_STATE_RX_ERROR;\r
-      }\r
-    }\r
-  }\r
+  //\r
+  //  Return the remote address\r
+  //\r
+  pTcp4 = &pPort->Context.Tcp4;\r
+  pRemoteAddress = (struct sockaddr_in *)pAddress;\r
+  pRemoteAddress->sin_family = AF_INET;\r
+  pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );\r
+  CopyMem ( &pRemoteAddress->sin_addr,\r
+            &pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],\r
+            sizeof ( pRemoteAddress->sin_addr ));\r
 \r
   DBG_EXIT ( );\r
 }\r
 \r
 \r
 /**\r
-  Start a receive operation\r
+  Set the remote address\r
+\r
+  This routine sets the remote address in the port.\r
+\r
+  This routine is called by ::EslSocketConnect to specify the\r
+  remote network address.\r
+\r
+  @param [in] pPort           Address of an ::ESL_PORT structure.\r
+\r
+  @param [in] pSockAddr       Network address of the remote system.\r
+\r
+  @param [in] SockAddrLength  Length in bytes of the network address.\r
 \r
-  @param [in] pPort       Address of the DT_PORT structure.\r
+  @retval EFI_SUCCESS     The operation was successful\r
 \r
  **/\r
-VOID\r
-EslTcpRxStart4 (\r
-  IN DT_PORT * pPort\r
+EFI_STATUS\r
+EslTcp4RemoteAddressSet (\r
+  IN ESL_PORT * pPort,\r
+  IN CONST struct sockaddr * pSockAddr,\r
+  IN socklen_t SockAddrLength\r
   )\r
 {\r
-  size_t LengthInBytes;\r
-  DT_PACKET * pPacket;\r
-  DT_SOCKET * pSocket;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
-  EFI_TCP4_PROTOCOL * pTcp4Protocol;\r
+  CONST struct sockaddr_in * pRemoteAddress;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Determine if a receive is already pending\r
+  //  Set the remote address\r
   //\r
-  Status = EFI_SUCCESS;\r
-  pPacket = NULL;\r
-  pSocket = pPort->pSocket;\r
   pTcp4 = &pPort->Context.Tcp4;\r
-  if ( !EFI_ERROR ( pPort->pSocket->RxError )) {\r
-    if (( NULL == pTcp4->pReceivePending )\r
-      && ( PORT_STATE_CLOSE_STARTED > pPort->State )) {\r
-      //\r
-      //  Determine if there are any free packets\r
-      //\r
-      pPacket = pSocket->pRxFree;\r
-      LengthInBytes = sizeof ( pPacket->Op.Tcp4Rx.Buffer );\r
-      if ( NULL != pPacket ) {\r
-        //\r
-        //  Remove this packet from the free list\r
-        //\r
-        pSocket->pRxFree = pPacket->pNext;\r
-        DEBUG (( DEBUG_RX,\r
-                  "0x%08x: Port removed packet 0x%08x from free list\r\n",\r
-                  pPort,\r
-                  pPacket ));\r
-      }\r
-      else {\r
-        //\r
-        //  Allocate a packet structure\r
-        //\r
-        Status = EslSocketPacketAllocate ( &pPacket,\r
-                                           sizeof ( pPacket->Op.Tcp4Rx ),\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
-        }\r
-      }\r
-\r
-      //\r
-      //  Determine if a packet is available\r
-      //\r
-      if ( NULL != pPacket ) {\r
-        //\r
-        //  Initialize the buffer for receive\r
-        //\r
-        pTcp4->RxToken.Packet.RxData = &pPacket->Op.Tcp4Rx.RxData;\r
-        pPacket->Op.Tcp4Rx.RxData.DataLength = (UINT32) LengthInBytes;\r
-        pPacket->Op.Tcp4Rx.RxData.FragmentCount = 1;\r
-        pPacket->Op.Tcp4Rx.RxData.FragmentTable [0].FragmentLength = (UINT32) LengthInBytes;\r
-        pPacket->Op.Tcp4Rx.RxData.FragmentTable [0].FragmentBuffer = &pPacket->Op.Tcp4Rx.Buffer [0];\r
-        pTcp4->pReceivePending = pPacket;\r
-\r
-        //\r
-        //  Start the receive on the packet\r
-        //\r
-        pTcp4Protocol = pTcp4->pProtocol;\r
-        Status = pTcp4Protocol->Receive ( pTcp4Protocol,\r
-                                          &pTcp4->RxToken );\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
-        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
-          pTcp4->pReceivePending = NULL;\r
-          if ( !EFI_ERROR ( pSocket->RxError )) {\r
-            //\r
-            //  Save the error status\r
-            //\r
-            pSocket->RxError = Status;\r
-          }\r
-        }\r
-      }\r
-    }\r
+  pRemoteAddress = (struct sockaddr_in *)pSockAddr;\r
+  pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );\r
+  pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );\r
+  pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );\r
+  pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );\r
+  pTcp4->ConfigData.AccessPoint.RemotePort = SwapBytes16 ( pRemoteAddress->sin_port );\r
+  Status = EFI_SUCCESS;\r
+  if ( INADDR_BROADCAST == pRemoteAddress->sin_addr.s_addr ) {\r
+    DEBUG (( DEBUG_CONNECT,\r
+              "ERROR - Invalid remote address\r\n" ));\r
+    Status = EFI_INVALID_PARAMETER;\r
+    pPort->pSocket->errno = EAFNOSUPPORT;\r
   }\r
 \r
-  DBG_EXIT ( );\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
 }\r
 \r
 \r
 /**\r
-  Shutdown the TCP4 service.\r
+  Process the receive completion\r
+\r
+  This routine queues the data in FIFO order in either the urgent\r
+  or normal data queues depending upon the type of data received.\r
+  See the \ref ReceiveEngine section.\r
+\r
+  This routine is called by the TCPv4 driver when some data is\r
+  received.\r
+\r
+  Buffer the data that was just received.\r
 \r
-  This routine undoes the work performed by ::TcpInitialize4.\r
+  @param [in] Event     The receive completion event\r
 \r
-  @param [in] pService        DT_SERVICE structure address\r
+  @param [in] pIo       Address of an ::ESL_IO_MGMT structure\r
 \r
 **/\r
 VOID\r
-EFIAPI\r
-EslTcpShutdown4 (\r
-  IN DT_SERVICE * pService\r
+EslTcp4RxComplete (\r
+  IN EFI_EVENT Event,\r
+  IN ESL_IO_MGMT * pIo\r
   )\r
 {\r
-  DT_LAYER * pLayer;\r
-  DT_PORT * pPort;\r
-  DT_SERVICE * pPreviousService;\r
+  BOOLEAN bUrgent;\r
+  size_t LengthInBytes;\r
+  ESL_PACKET * pPacket;\r
+  EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Verify the socket layer synchronization\r
+  //  Get the operation status.\r
   //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
+  Status = pIo->Token.Tcp4Rx.CompletionToken.Status;\r
 \r
   //\r
-  //  Walk the list of ports\r
+  //      +--------------------+   +---------------------------+\r
+  //      | ESL_IO_MGMT        |   | ESL_PACKET                |\r
+  //      |                    |   |                           |\r
+  //      |    +---------------+   +-----------------------+   |\r
+  //      |    | Token         |   | EFI_TCP4_RECEIVE_DATA |   |\r
+  //      |    |        RxData --> |                       |   |\r
+  //      |    |               |   +-----------------------+---+\r
+  //      |    |        Event  |   |       Data Buffer         |\r
+  //      +----+---------------+   |                           |\r
+  //                               |                           |\r
+  //                               +---------------------------+\r
   //\r
-  do {\r
-    pPort = pService->pPortList;\r
-    if ( NULL != pPort ) {\r
-      //\r
-      //  Remove the port from the port list\r
-      //\r
-      pService->pPortList = pPort->pLinkService;\r
+  //\r
+  //  Duplicate the buffer address and length for use by the\r
+  //  buffer handling code in EslTcp4Receive.  These fields are\r
+  //  used when a partial read is done of the data from the\r
+  //  packet.\r
+  //\r
+  pPacket = pIo->pPacket;\r
+  pPacket->pBuffer = pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer;\r
+  LengthInBytes = pPacket->Op.Tcp4Rx.RxData.DataLength;\r
+  pPacket->ValidBytes = LengthInBytes;\r
 \r
-      //\r
-      //  Close the port\r
-      // TODO: Fix this\r
-      //\r
-//      pPort->pfnClosePort ( pPort, DEBUG_LISTEN | DEBUG_CONNECTION );\r
-    }\r
-  } while ( NULL != pPort );\r
+  //\r
+  //  Get the data type so that it may be linked to the\r
+  //  correct receive buffer list on the ESL_SOCKET structure\r
+  //\r
+  bUrgent = pPacket->Op.Tcp4Rx.RxData.UrgentFlag;\r
 \r
   //\r
-  //  Remove the service from the service list\r
+  //  Complete this request\r
   //\r
-  pLayer = &mEslLayer;\r
-  pPreviousService = pLayer->pTcp4List;\r
-  if ( pService == pPreviousService ) {\r
-    //\r
-    //  Remove the service from the beginning of the list\r
-    //\r
-    pLayer->pTcp4List = pService->pNext;\r
-  }\r
-  else {\r
-    //\r
-    //  Remove the service from the middle of the list\r
-    //\r
-    while ( NULL != pPreviousService ) {\r
-      if ( pService == pPreviousService->pNext ) {\r
-        pPreviousService->pNext = pService->pNext;\r
-        break;\r
-      }\r
-    }\r
-  }\r
+  EslSocketRxComplete ( pIo, Status, LengthInBytes, bUrgent );\r
+  DBG_EXIT ( );\r
+}\r
+\r
+\r
+/**\r
+  Start a receive operation\r
+\r
+  This routine posts a receive buffer to the TCPv4 driver.\r
+  See the \ref ReceiveEngine section.\r
+\r
+  This support routine is called by EslSocketRxStart.\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
+VOID\r
+EslTcp4RxStart (\r
+  IN ESL_PORT * pPort,\r
+  IN ESL_IO_MGMT * pIo\r
+  )\r
+{\r
+  ESL_PACKET * pPacket;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Initialize the buffer for receive\r
+  //\r
+  pPacket = pIo->pPacket;\r
+  pIo->Token.Tcp4Rx.Packet.RxData = &pPacket->Op.Tcp4Rx.RxData;\r
+  pPacket->Op.Tcp4Rx.RxData.DataLength = sizeof ( pPacket->Op.Tcp4Rx.Buffer );\r
+  pPacket->Op.Tcp4Rx.RxData.FragmentCount = 1;\r
+  pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentLength = pPacket->Op.Tcp4Rx.RxData.DataLength;\r
+  pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Tcp4Rx.Buffer[0];\r
 \r
   DBG_EXIT ( );\r
 }\r
@@ -2885,16 +1833,21 @@ EslTcpShutdown4 (
 /**\r
   Determine if the socket is configured.\r
 \r
+  This routine uses the flag ESL_SOCKET::bConfigured to determine\r
+  if the network layer's configuration routine has been called.\r
+\r
+  This routine is called by EslSocketIsConfigured to verify\r
+  that the socket has been configured.\r
+\r
+  @param [in] pSocket   Address of an ::ESL_SOCKET structure.\r
 \r
-  @param [in] pSocket         Address of a DT_SOCKET structure\r
-  \r
   @retval EFI_SUCCESS - The port is connected\r
   @retval EFI_NOT_STARTED - The port is not connected\r
 \r
  **/\r
  EFI_STATUS\r
- EslTcpSocketIsConfigured4 (\r
-  IN DT_SOCKET * pSocket\r
+ EslTcp4SocketIsConfigured (\r
+  IN ESL_SOCKET * pSocket\r
   )\r
 {\r
   EFI_STATUS Status;\r
@@ -2917,52 +1870,58 @@ EslTcpShutdown4 (
 /**\r
   Buffer data for transmission over a network connection.\r
 \r
-  This routine is called by the socket layer API to buffer\r
-  data for transmission.  When necessary, this routine will\r
-  start the transmit engine that performs the data transmission\r
-  on the network connection.\r
+  This routine buffers data for the transmit engine in one of two\r
+  queues, one for urgent (out-of-band) data and the other for normal\r
+  data.  The urgent data is provided to TCP as soon as it is available,\r
+  allowing the TCP layer to schedule transmission of the urgent data\r
+  between packets of normal data.\r
 \r
-  The transmit engine uses two queues, one for urgent (out-of-band)\r
-  data and the other for normal data.  The urgent data is provided\r
-  to TCP as soon as it is available, allowing the TCP layer to\r
-  schedule transmission of the urgent data between packets of normal\r
-  data.\r
+  This routine is called by ::EslSocketTransmit to buffer\r
+  data for transmission.  When the \ref TransmitEngine has resources,\r
+  this routine will start the transmission of the next buffer on\r
+  the network connection.\r
 \r
   Transmission errors are returned during the next transmission or\r
   during the close operation.  Only buffering errors are returned\r
   during the current transmission attempt.\r
 \r
-  @param [in] pSocket         Address of a DT_SOCKET structure\r
-  \r
+  @param [in] pSocket         Address of an ::ESL_SOCKET structure\r
+\r
   @param [in] Flags           Message control flags\r
-  \r
+\r
   @param [in] BufferLength    Length of the the buffer\r
-  \r
+\r
   @param [in] pBuffer         Address of a buffer to receive the data.\r
-  \r
+\r
   @param [in] pDataLength     Number of received data bytes in the buffer.\r
 \r
+  @param [in] pAddress        Network address of the remote system address\r
+\r
+  @param [in] AddressLength   Length of the remote network address structure\r
+\r
   @retval EFI_SUCCESS - Socket data successfully buffered\r
 \r
  **/\r
 EFI_STATUS\r
-EslTcpTxBuffer4 (\r
-  IN DT_SOCKET * pSocket,\r
+EslTcp4TxBuffer (\r
+  IN ESL_SOCKET * pSocket,\r
   IN int Flags,\r
   IN size_t BufferLength,\r
   IN CONST UINT8 * pBuffer,\r
-  OUT size_t * pDataLength\r
+  OUT size_t * pDataLength,\r
+  IN const struct sockaddr * pAddress,\r
+  IN socklen_t AddressLength\r
   )\r
 {\r
   BOOLEAN bUrgent;\r
-  DT_PACKET * pPacket;\r
-  DT_PACKET * pPreviousPacket;\r
-  DT_PACKET ** ppPacket;\r
-  DT_PACKET ** ppQueueHead;\r
-  DT_PACKET ** ppQueueTail;\r
-  DT_PORT * pPort;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
-  EFI_TCP4_IO_TOKEN * pToken;\r
+  BOOLEAN bUrgentQueue;\r
+  ESL_PACKET * pPacket;\r
+  ESL_IO_MGMT ** ppActive;\r
+  ESL_IO_MGMT ** ppFree;\r
+  ESL_PORT * pPort;\r
+  ESL_PACKET ** ppQueueHead;\r
+  ESL_PACKET ** ppQueueTail;\r
+  ESL_PACKET * pPreviousPacket;\r
   size_t * pTxBytes;\r
   EFI_TCP4_TRANSMIT_DATA * pTxData;\r
   EFI_STATUS Status;\r
@@ -2975,7 +1934,7 @@ EslTcpTxBuffer4 (
   //\r
   Status = EFI_UNSUPPORTED;\r
   pSocket->errno = ENOTCONN;\r
-  * pDataLength = 0;\r
+  *pDataLength = 0;\r
 \r
   //\r
   //  Verify that the socket is connected\r
@@ -2989,20 +1948,22 @@ EslTcpTxBuffer4 (
       //\r
       //  Determine the queue head\r
       //\r
-      pTcp4 = &pPort->Context.Tcp4;\r
       bUrgent = (BOOLEAN)( 0 != ( Flags & MSG_OOB ));\r
-      if ( bUrgent ) {\r
+      bUrgentQueue = bUrgent\r
+                    && ( !pSocket->bOobInLine )\r
+                    && pSocket->pApi->bOobSupported;\r
+      if ( bUrgentQueue ) {\r
         ppQueueHead = &pSocket->pTxOobPacketListHead;\r
         ppQueueTail = &pSocket->pTxOobPacketListTail;\r
-        ppPacket = &pTcp4->pTxOobPacket;\r
-        pToken = &pTcp4->TxOobToken;\r
+        ppActive = &pPort->pTxOobActive;\r
+        ppFree = &pPort->pTxOobFree;\r
         pTxBytes = &pSocket->TxOobBytes;\r
       }\r
       else {\r
         ppQueueHead = &pSocket->pTxPacketListHead;\r
         ppQueueTail = &pSocket->pTxPacketListTail;\r
-        ppPacket = &pTcp4->pTxPacket;\r
-        pToken = &pTcp4->TxToken;\r
+        ppActive = &pPort->pTxActive;\r
+        ppFree = &pPort->pTxFree;\r
         pTxBytes = &pSocket->TxBytes;\r
       }\r
 \r
@@ -3011,6 +1972,15 @@ EslTcpTxBuffer4 (
       //  transmit operation\r
       //\r
       if ( pSocket->MaxTxBuf > *pTxBytes ) {\r
+        if ( pPort->bTxFlowControl ) {\r
+          DEBUG (( DEBUG_TX,\r
+                    "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\r\n0x%08x: pPort, TX flow control released, Max bytes: %d > %d bufferred bytes\r\n",\r
+                    pPort,\r
+                    pSocket->MaxTxBuf,\r
+                    *pTxBytes ));\r
+          pPort->bTxFlowControl = FALSE;\r
+        }\r
+\r
         //\r
         //  Attempt to allocate the packet\r
         //\r
@@ -3018,13 +1988,14 @@ EslTcpTxBuffer4 (
                                            sizeof ( pPacket->Op.Tcp4Tx )\r
                                            - sizeof ( pPacket->Op.Tcp4Tx.Buffer )\r
                                            + BufferLength,\r
+                                           0,\r
                                            DEBUG_TX );\r
         if ( !EFI_ERROR ( Status )) {\r
           //\r
           //  Initialize the transmit operation\r
           //\r
           pTxData = &pPacket->Op.Tcp4Tx.TxData;\r
-          pTxData->Push = TRUE;\r
+          pTxData->Push = TRUE || bUrgent;\r
           pTxData->Urgent = bUrgent;\r
           pTxData->DataLength = (UINT32) BufferLength;\r
           pTxData->FragmentCount = 1;\r
@@ -3071,7 +2042,7 @@ EslTcpTxBuffer4 (
             DEBUG (( DEBUG_TX,\r
                       "0x%08x: Packet on %s transmit list\r\n",\r
                       pPacket,\r
-                      bUrgent ? L"urgent" : L"normal" ));\r
+                      bUrgentQueue ? L"urgent" : L"normal" ));\r
 \r
             //\r
             //  Account for the buffered data\r
@@ -3082,12 +2053,12 @@ EslTcpTxBuffer4 (
             //\r
             //  Start the transmit engine if it is idle\r
             //\r
-            if ( NULL == *ppPacket ) {\r
-              EslTcpTxStart4 ( pSocket->pPortList,\r
-                               pToken,\r
-                               ppQueueHead,\r
-                               ppQueueTail,\r
-                               ppPacket );\r
+            if ( NULL != *ppFree ) {\r
+              EslSocketTxStart ( pPort,\r
+                                 ppQueueHead,\r
+                                 ppQueueTail,\r
+                                 ppActive,\r
+                                 ppFree );\r
             }\r
           }\r
           else {\r
@@ -3117,6 +2088,14 @@ EslTcpTxBuffer4 (
         }\r
       }\r
       else {\r
+        if ( !pPort->bTxFlowControl ) {\r
+          DEBUG (( DEBUG_TX,\r
+                    "0x%08x: pPort, TX flow control applied, Max bytes %d <= %d bufferred bytes\r\nTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\r\n",\r
+                    pPort,\r
+                    pSocket->MaxTxBuf,\r
+                    *pTxBytes ));\r
+          pPort->bTxFlowControl = TRUE;\r
+        }\r
         //\r
         //  Not enough buffer space available\r
         //\r
@@ -3137,104 +2116,56 @@ EslTcpTxBuffer4 (
 /**\r
   Process the normal data transmit completion\r
 \r
-  @param  Event         The normal transmit completion event\r
+  This routine use ::EslSocketTxComplete to perform the transmit\r
+  completion processing for normal data.\r
 \r
-  @param  pPort         The DT_PORT structure address\r
+  This routine is called by the TCPv4 network layer when a\r
+  normal data transmit request completes.\r
+\r
+  @param [in] Event     The normal transmit completion event\r
+\r
+  @param [in] pIo       The ESL_IO_MGMT structure address\r
 \r
 **/\r
 VOID\r
-EslTcpTxComplete4 (\r
+EslTcp4TxComplete (\r
   IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
+  IN ESL_IO_MGMT * pIo\r
   )\r
 {\r
   UINT32 LengthInBytes;\r
-  DT_PACKET * pCurrentPacket;\r
-  DT_PACKET * pNextPacket;\r
-  DT_PACKET * pPacket;\r
-  DT_SOCKET * pSocket;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
+  ESL_PACKET * pPacket;\r
+  ESL_PORT * pPort;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
-  \r
+\r
   DBG_ENTER ( );\r
-  \r
+\r
   //\r
   //  Locate the active transmit packet\r
   //\r
+  pPacket = pIo->pPacket;\r
+  pPort = pIo->pPort;\r
   pSocket = pPort->pSocket;\r
-  pTcp4 = &pPort->Context.Tcp4;\r
-  pPacket = pTcp4->pTxPacket;\r
-  \r
+\r
   //\r
-  //  Mark this packet as complete\r
+  //  Get the transmit length and status\r
   //\r
-  pTcp4->pTxPacket = NULL;\r
   LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength;\r
   pSocket->TxBytes -= LengthInBytes;\r
-  \r
-  //\r
-  //  Save any transmit error\r
-  //\r
-  Status = pTcp4->TxToken.CompletionToken.Status;\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 packet 0x%08x, Status: %r\r\n",\r
-              pPacket,\r
-              Status ));\r
-\r
-    //\r
-    //  Empty the normal transmit list\r
-    //\r
-    pCurrentPacket = pPacket;\r
-    pNextPacket = pSocket->pTxPacketListHead;\r
-    while ( NULL != pNextPacket ) {\r
-      pPacket = pNextPacket;\r
-      pNextPacket = pPacket->pNext;\r
-      EslSocketPacketFree ( pPacket, DEBUG_TX );\r
-    }\r
-    pSocket->pTxPacketListHead = NULL;\r
-    pSocket->pTxPacketListTail = NULL;\r
-    pPacket = pCurrentPacket;\r
-  }\r
-  else\r
-  {\r
-    DEBUG (( DEBUG_TX | DEBUG_INFO,\r
-              "0x%08x: Packet transmitted %d bytes successfully\r\n",\r
-              pPacket,\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
-      EslTcpTxStart4 ( pPort,\r
-                       &pTcp4->TxToken,\r
-                       &pSocket->pTxPacketListHead,\r
-                       &pSocket->pTxPacketListTail,\r
-                       &pTcp4->pTxPacket );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Release this packet\r
-  //\r
-  EslSocketPacketFree ( pPacket, DEBUG_TX );\r
+  Status = pIo->Token.Tcp4Tx.CompletionToken.Status;\r
 \r
   //\r
-  //  Finish the close operation if necessary\r
+  //  Complete the transmit operation\r
   //\r
-  if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {\r
-    //\r
-    //  Indicate that the transmit is complete\r
-    //\r
-    EslTcpPortCloseTxDone4 ( pPort );\r
-  }\r
+  EslSocketTxComplete ( pIo,\r
+                        LengthInBytes,\r
+                        Status,\r
+                        "Normal ",\r
+                        &pSocket->pTxPacketListHead,\r
+                        &pSocket->pTxPacketListTail,\r
+                        &pPort->pTxActive,\r
+                        &pPort->pTxFree );\r
   DBG_EXIT ( );\r
 }\r
 \r
@@ -3242,23 +2173,27 @@ EslTcpTxComplete4 (
 /**\r
   Process the urgent data transmit completion\r
 \r
-  @param  Event         The urgent transmit completion event\r
+  This routine use ::EslSocketTxComplete to perform the transmit\r
+  completion processing for urgent data.\r
 \r
-  @param  pPort         The DT_PORT structure address\r
+  This routine is called by the TCPv4 network layer when a\r
+  urgent data transmit request completes.\r
+\r
+  @param [in] Event     The urgent transmit completion event\r
+\r
+  @param [in] pIo       The ESL_IO_MGMT structure address\r
 \r
 **/\r
 VOID\r
-EslTcpTxOobComplete4 (\r
+EslTcp4TxOobComplete (\r
   IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
+  IN ESL_IO_MGMT * pIo\r
   )\r
 {\r
   UINT32 LengthInBytes;\r
-  DT_PACKET * pCurrentPacket;\r
-  DT_PACKET * pNextPacket;\r
-  DT_PACKET * pPacket;\r
-  DT_SOCKET * pSocket;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
+  ESL_PACKET * pPacket;\r
+  ESL_PORT * pPort;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
@@ -3266,150 +2201,232 @@ EslTcpTxOobComplete4 (
   //\r
   //  Locate the active transmit packet\r
   //\r
+  pPacket = pIo->pPacket;\r
+  pPort = pIo->pPort;\r
   pSocket = pPort->pSocket;\r
-  pTcp4 = &pPort->Context.Tcp4;\r
-  pPacket = pTcp4->pTxOobPacket;\r
 \r
   //\r
-  //  Mark this packet as complete\r
+  //  Get the transmit length and status\r
   //\r
-  pTcp4->pTxOobPacket = NULL;\r
   LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength;\r
   pSocket->TxOobBytes -= LengthInBytes;\r
+  Status = pIo->Token.Tcp4Tx.CompletionToken.Status;\r
 \r
   //\r
-  //  Save any transmit error\r
-  //\r
-  Status = pTcp4->TxOobToken.CompletionToken.Status;\r
-  if ( EFI_ERROR ( Status )) {\r
-    if ( !EFI_ERROR ( Status )) {\r
-      pSocket->TxError = Status;\r
-    }\r
-    DEBUG (( DEBUG_TX | DEBUG_INFO,\r
-              "ERROR - Transmit failure for urgent packet 0x%08x, Status: %r\r\n",\r
-              pPacket,\r
-              Status ));\r
-\r
-\r
-    //\r
-    //  Empty the OOB transmit list\r
-    //\r
-    pCurrentPacket = pPacket;\r
-    pNextPacket = pSocket->pTxOobPacketListHead;\r
-    while ( NULL != pNextPacket ) {\r
-      pPacket = pNextPacket;\r
-      pNextPacket = pPacket->pNext;\r
-      EslSocketPacketFree ( pPacket, DEBUG_TX );\r
-    }\r
-    pSocket->pTxOobPacketListHead = NULL;\r
-    pSocket->pTxOobPacketListTail = NULL;\r
-    pPacket = pCurrentPacket;\r
-  }\r
-  else\r
-  {\r
-    DEBUG (( DEBUG_TX | DEBUG_INFO,\r
-              "0x%08x: Urgent packet transmitted %d bytes successfully\r\n",\r
-              pPacket,\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
-      EslTcpTxStart4 ( pPort,\r
-                       &pTcp4->TxOobToken,\r
-                       &pSocket->pTxOobPacketListHead,\r
-                       &pSocket->pTxOobPacketListTail,\r
-                       &pTcp4->pTxOobPacket );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Release this packet\r
-  //\r
-  EslSocketPacketFree ( pPacket, DEBUG_TX );\r
-\r
-  //\r
-  //  Finish the close operation if necessary\r
+  //  Complete the transmit operation\r
   //\r
-  if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {\r
-    //\r
-    //  Indicate that the transmit is complete\r
-    //\r
-    EslTcpPortCloseTxDone4 ( pPort );\r
-  }\r
+  EslSocketTxComplete ( pIo,\r
+                        LengthInBytes,\r
+                        Status,\r
+                        "Urgent ",\r
+                        &pSocket->pTxOobPacketListHead,\r
+                        &pSocket->pTxOobPacketListTail,\r
+                        &pPort->pTxOobActive,\r
+                        &pPort->pTxOobFree );\r
   DBG_EXIT ( );\r
 }\r
 \r
 \r
 /**\r
-  Transmit data using a network connection.\r
+  Verify the adapter's IP address\r
 \r
+  This support routine is called by EslSocketBindTest.\r
 \r
-  @param [in] pPort           Address of a DT_PORT structure\r
-  @param [in] pToken          Address of either the OOB or normal transmit token\r
-  @param [in] ppQueueHead     Transmit queue head address\r
-  @param [in] ppQueueTail     Transmit queue tail address\r
-  @param [in] ppPacket        Active transmit packet address\r
+  @param [in] pPort       Address of an ::ESL_PORT structure.\r
+  @param [in] pConfigData Address of the configuration data\r
+\r
+  @retval EFI_SUCCESS - The IP address is valid\r
+  @retval EFI_NOT_STARTED - The IP address is invalid\r
 \r
  **/\r
-VOID\r
-EslTcpTxStart4 (\r
-  IN DT_PORT * pPort,\r
-  IN EFI_TCP4_IO_TOKEN * pToken,\r
-  IN DT_PACKET ** ppQueueHead,\r
-  IN DT_PACKET ** ppQueueTail,\r
-  IN DT_PACKET ** ppPacket\r
+EFI_STATUS\r
+EslTcp4VerifyLocalIpAddress (\r
+  IN ESL_PORT * pPort,\r
+  IN EFI_TCP4_CONFIG_DATA * pConfigData\r
   )\r
 {\r
-  DT_PACKET * pNextPacket;\r
-  DT_PACKET * pPacket;\r
-  DT_SOCKET * pSocket;\r
-  EFI_TCP4_PROTOCOL * pTcp4Protocol;\r
+  UINTN DataSize;\r
+  EFI_TCP4_ACCESS_POINT * pAccess;\r
+  EFI_IP4_CONFIG2_INTERFACE_INFO * pIfInfo;\r
+  EFI_IP4_CONFIG2_PROTOCOL * pIpConfig2Protocol;\r
+  ESL_SERVICE * pService;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Assume success\r
+  //  Use break instead of goto\r
   //\r
-  Status = EFI_SUCCESS;\r
+  pIfInfo = NULL;\r
+  for ( ; ; ) {\r
+    //\r
+    //  Determine if the IP address is specified\r
+    //\r
+    pAccess = &pConfigData->AccessPoint;\r
+    DEBUG (( DEBUG_BIND,\r
+              "UseDefaultAddress: %s\r\n",\r
+              pAccess->UseDefaultAddress ? L"TRUE" : L"FALSE" ));\r
+    DEBUG (( DEBUG_BIND,\r
+              "Requested IP address: %d.%d.%d.%d\r\n",\r
+              pAccess->StationAddress.Addr [ 0 ],\r
+              pAccess->StationAddress.Addr [ 1 ],\r
+              pAccess->StationAddress.Addr [ 2 ],\r
+              pAccess->StationAddress.Addr [ 3 ]));\r
+    if ( pAccess->UseDefaultAddress\r
+      || (( 0 == pAccess->StationAddress.Addr [ 0 ])\r
+      && ( 0 == pAccess->StationAddress.Addr [ 1 ])\r
+      && ( 0 == pAccess->StationAddress.Addr [ 2 ])\r
+      && ( 0 == pAccess->StationAddress.Addr [ 3 ])))\r
+    {\r
+      Status = EFI_SUCCESS;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Open the configuration protocol\r
+    //\r
+    pService = pPort->pService;\r
+    Status = gBS->OpenProtocol ( \r
+                    pService->Controller,\r
+                    &gEfiIp4Config2ProtocolGuid,\r
+                    (VOID **)&pIpConfig2Protocol,\r
+                    NULL,\r
+                    NULL,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL \r
+                    );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - IP Configuration Protocol not available, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
+    }\r
 \r
-  //\r
-  //  Get the packet from the queue head\r
-  //\r
-  pPacket = *ppQueueHead;\r
-  if ( NULL != pPacket ) {\r
     //\r
-    //  Remove the packet from the queue\r
+    // Get the interface information size.\r
     //\r
-    pNextPacket = pPacket->pNext;\r
-    *ppQueueHead = pNextPacket;\r
-    if ( NULL == pNextPacket ) {\r
-      *ppQueueTail = NULL;\r
+    DataSize = 0;\r
+    Status = pIpConfig2Protocol->GetData ( \r
+                                   pIpConfig2Protocol,\r
+                                   Ip4Config2DataTypeInterfaceInfo,\r
+                                   &DataSize,\r
+                                   NULL\r
+                                   );\r
+    if ( EFI_BUFFER_TOO_SMALL != Status ) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to get the interface information size, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
     }\r
 \r
     //\r
-    //  Set the packet as active\r
+    //  Allocate the interface information buffer\r
     //\r
-    *ppPacket = pPacket;\r
+    pIfInfo = AllocatePool ( DataSize );\r
+    if ( NULL == pIfInfo ) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Not enough memory to allocate the interface information buffer!\r\n" ));\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      break;\r
+    }\r
 \r
     //\r
-    //  Start the transmit operation\r
+    // Get the interface info.\r
     //\r
-    pTcp4Protocol = pPort->Context.Tcp4.pProtocol;\r
-    pToken->Packet.TxData = &pPacket->Op.Tcp4Tx.TxData;\r
-    Status = pTcp4Protocol->Transmit ( pTcp4Protocol, pToken );\r
+    Status = pIpConfig2Protocol->GetData ( \r
+                                  pIpConfig2Protocol,\r
+                                  Ip4Config2DataTypeInterfaceInfo,\r
+                                  &DataSize,\r
+                                  pIfInfo\r
+                                  );\r
     if ( EFI_ERROR ( Status )) {\r
-      pSocket = pPort->pSocket;\r
-      if ( EFI_SUCCESS == pSocket->TxError ) {\r
-        pSocket->TxError = Status;\r
-      }\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to return the interface info, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Display the current configuration\r
+    //\r
+    DEBUG (( DEBUG_BIND,\r
+              "Actual adapter IP address: %d.%d.%d.%d\r\n",\r
+              pIfInfo->StationAddress.Addr [ 0 ],\r
+              pIfInfo->StationAddress.Addr [ 1 ],\r
+              pIfInfo->StationAddress.Addr [ 2 ],\r
+              pIfInfo->StationAddress.Addr [ 3 ]));\r
+\r
+    //\r
+    //  Assume the port is not configured\r
+    //\r
+    Status = EFI_SUCCESS;\r
+    if (( pAccess->StationAddress.Addr [ 0 ] == pIfInfo->StationAddress.Addr [ 0 ])\r
+      && ( pAccess->StationAddress.Addr [ 1 ] == pIfInfo->StationAddress.Addr [ 1 ])\r
+      && ( pAccess->StationAddress.Addr [ 2 ] == pIfInfo->StationAddress.Addr [ 2 ])\r
+      && ( pAccess->StationAddress.Addr [ 3 ] == pIfInfo->StationAddress.Addr [ 3 ])) {\r
+      break;\r
     }\r
+\r
+    //\r
+    //  The IP address did not match\r
+    //\r
+    Status = EFI_NOT_STARTED;\r
+    break;\r
   }\r
 \r
-  DBG_EXIT ( );\r
+  //\r
+  //  Free the buffer if necessary\r
+  //\r
+  if ( NULL != pIfInfo ) {\r
+    FreePool ( pIfInfo );\r
+  }\r
+\r
+  //\r
+  //  Return the IP address status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
 }\r
+\r
+\r
+/**\r
+  Interface between the socket layer and the network specific\r
+  code that supports SOCK_STREAM and SOCK_SEQPACKET sockets\r
+  over TCPv4.\r
+**/\r
+CONST ESL_PROTOCOL_API cEslTcp4Api = {\r
+  "TCPv4",\r
+  IPPROTO_TCP,\r
+  OFFSET_OF ( ESL_PORT, Context.Tcp4.ConfigData ),\r
+  OFFSET_OF ( ESL_LAYER, pTcp4List ),\r
+  OFFSET_OF ( struct sockaddr_in, sin_zero ),\r
+  sizeof ( struct sockaddr_in ),\r
+  AF_INET,\r
+  sizeof (((ESL_PACKET *)0 )->Op.Tcp4Rx ),\r
+  OFFSET_OF ( ESL_PACKET, Op.Tcp4Rx.Buffer ) - OFFSET_OF ( ESL_PACKET, Op ),\r
+  OFFSET_OF ( ESL_IO_MGMT, Token.Tcp4Rx.Packet.RxData ),\r
+  TRUE,\r
+  EADDRINUSE,\r
+  EslTcp4Accept,\r
+  EslTcp4ConnectPoll,\r
+  EslTcp4ConnectStart,\r
+  EslTcp4SocketIsConfigured,\r
+  EslTcp4LocalAddressGet,\r
+  EslTcp4LocalAddressSet,\r
+  EslTcp4Listen,\r
+  NULL,   //  OptionGet\r
+  NULL,   //  OptionSet\r
+  EslTcp4PacketFree,\r
+  EslTcp4PortAllocate,\r
+  EslTcp4PortClose,\r
+  EslTcp4PortCloseOp,\r
+  FALSE,\r
+  EslTcp4Receive,\r
+  EslTcp4RemoteAddressGet,\r
+  EslTcp4RemoteAddressSet,\r
+  EslTcp4RxComplete,\r
+  EslTcp4RxStart,\r
+  EslTcp4TxBuffer,\r
+  EslTcp4TxComplete,\r
+  EslTcp4TxOobComplete,\r
+  (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslTcp4VerifyLocalIpAddress\r
+};\r