]> 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 b489608a5bac5c26687c5c87c2906205c8cdfc9e..68477fba6e70122d173a2ffc918564a4a6432446 100644 (file)
@@ -1,28 +1,97 @@
 /** @file\r
   Implement the TCP4 driver support for the socket layer.\r
 \r
 /** @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
   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
 \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
 /**\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
 \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
   @param [in] pSockAddr       Address of a buffer to receive the remote\r
                               network address.\r
 \r
  **/\r
 EFI_STATUS\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
   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
   struct sockaddr_in * pRemoteAddress;\r
-  DT_TCP4_CONTEXT * pTcp4;\r
+  ESL_TCP4_CONTEXT * pTcp4;\r
   UINT32 RemoteAddress;\r
   EFI_STATUS Status;\r
 \r
   UINT32 RemoteAddress;\r
   EFI_STATUS Status;\r
 \r
@@ -102,302 +171,37 @@ EslTcpAccept4 (
 \r
 \r
 /**\r
 \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
 \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
   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
 \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
 \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
 \r
 **/\r
 VOID\r
-EslTcpConnectComplete4 (\r
+EslTcp4ConnectComplete (\r
   IN EFI_EVENT Event,\r
   IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
+  IN ESL_PORT * pPort\r
   )\r
 {\r
   BOOLEAN bRemoveFirstPort;\r
   BOOLEAN bRemovePorts;\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
   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
     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
               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
     //\r
     //  Remove the rest of the ports\r
     //\r
@@ -437,20 +248,22 @@ EslTcpConnectComplete4 (
     //\r
     //  The connection failed\r
     //\r
     //\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
 \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
     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
     //\r
     //  Try to connect using the next port\r
     //\r
-    Status = EslTcpConnectAttempt4 ( pSocket );\r
+    Status = EslTcp4ConnectStart ( pSocket );\r
     if ( EFI_NOT_READY != Status ) {\r
     if ( EFI_NOT_READY != Status ) {\r
-      pSocket->ConnectStatus = Status;\r
       bRemoveFirstPort = TRUE;\r
     }\r
   }\r
       bRemoveFirstPort = TRUE;\r
     }\r
   }\r
@@ -490,7 +302,7 @@ EslTcpConnectComplete4 (
     //\r
     while ( NULL != pPort ) {\r
       pNextPort = pPort->pLinkSocket;\r
     //\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
       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
 /**\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
 \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
 \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
 \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
   )\r
 {\r
   EFI_STATUS Status;\r
@@ -564,29 +382,47 @@ EslTcpConnectPoll4 (
       break;\r
 \r
     case EFI_ABORTED:\r
       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
       break;\r
 \r
     case EFI_INVALID_PARAMETER:\r
-      pSocket->errno = EINVAL;\r
+      pSocket->errno = EADDRNOTAVAIL;\r
       break;\r
 \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_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_NO_MEDIA:\r
+    case EFI_NETWORK_UNREACHABLE:\r
       pSocket->errno = ENETDOWN;\r
       break;\r
 \r
     case EFI_OUT_OF_RESOURCES:\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
       break;\r
 \r
     case EFI_SUCCESS:\r
       pSocket->errno = 0;\r
-      pSocket->bConfigured = TRUE;\r
       break;\r
 \r
     case EFI_TIMEOUT:\r
       break;\r
 \r
     case EFI_TIMEOUT:\r
@@ -594,13 +430,17 @@ EslTcpConnectPoll4 (
       break;\r
 \r
     case EFI_UNSUPPORTED:\r
       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
       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
   }\r
 \r
   //\r
@@ -612,292 +452,141 @@ EslTcpConnectPoll4 (
 \r
 \r
 /**\r
 \r
 \r
 /**\r
-  Connect to a remote system via the network.\r
+  Attempt to connect to a remote TCP port\r
 \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
 \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
 \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
   @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
   )\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
   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
   //\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
     //\r
-    //  Determine if BIND was already called\r
+    //  Configure the port\r
     //\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
     }\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
       //\r
-      //  Walk the list of ports\r
+      //  Verify the port connection\r
       //\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
         //\r
-        //  Set the next port\r
+        //  Connection error\r
         //\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
-      //\r
-      //  Attempt a connection using the first adapter\r
-      //\r
-      Status = EslTcpConnectAttempt4 ( pSocket );\r
     }\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
       //\r
-      //  Return the local address\r
+      //  Connection in progress\r
       //\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
     }\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
-  //\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
       //\r
-      //  Return the local address\r
+      //  Continue with the next port\r
       //\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
     }\r
+    Status = EFI_NOT_READY;\r
   }\r
   else {\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
   //\r
   //  Return the operation status\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
 /**\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
 \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
 \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
   )\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
   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
         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
                                     pPort,\r
                                     &pTcp4->ListenToken.CompletionToken.Event );\r
         if ( EFI_ERROR ( Status )) {\r
@@ -987,7 +676,7 @@ EslTcpListen4 (
         //\r
         //  Configure the port\r
         //\r
         //\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
         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
         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
 \r
         //\r
         //  Start the listen operation on the port\r
@@ -1078,9 +767,8 @@ EslTcpListen4 (
       //\r
       //  Close the port upon error\r
       //\r
       //\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
       }\r
 \r
       //\r
@@ -1088,7 +776,7 @@ EslTcpListen4 (
       //\r
       pPort = pNextPort;\r
     }\r
       //\r
       pPort = pNextPort;\r
     }\r
-    \r
+\r
     //\r
     //  Determine if any ports are in the listen state\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
     //  Mark the socket as configured\r
     //\r
     pSocket->bConfigured = TRUE;\r
+    Status = EFI_SUCCESS;\r
+    pSocket->errno = 0;\r
 \r
     //\r
     //  All done\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
   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
 \r
-  @param  pPort         The DT_PORT structure address\r
+  @param [in] pPort     Address of an ::ESL_PORT structure.\r
 \r
 **/\r
 VOID\r
 \r
 **/\r
 VOID\r
-EslTcpListenComplete4 (\r
+EslTcp4ListenComplete (\r
   IN EFI_EVENT Event,\r
   IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
+  IN ESL_PORT * pPort\r
   )\r
 {\r
   EFI_HANDLE ChildHandle;\r
   )\r
 {\r
   EFI_HANDLE ChildHandle;\r
+  struct sockaddr_in LocalAddress;\r
   EFI_TCP4_CONFIG_DATA * pConfigData;\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
   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
 \r
   //\r
   //  Assume success\r
@@ -1173,7 +868,6 @@ EslTcpListenComplete4 (
     //  Allocate a socket for this connection\r
     //\r
     ChildHandle = NULL;\r
     //  Allocate a socket for this connection\r
     //\r
     ChildHandle = NULL;\r
-    pLayer = &mEslLayer;\r
     Status = EslSocketAllocate ( &ChildHandle,\r
                                  DEBUG_CONNECTION,\r
                                  &pNewSocket );\r
     Status = EslSocketAllocate ( &ChildHandle,\r
                                  DEBUG_CONNECTION,\r
                                  &pNewSocket );\r
@@ -1181,26 +875,36 @@ EslTcpListenComplete4 (
       //\r
       //  Clone the socket parameters\r
       //\r
       //\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
       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
       //\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
       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
         Status = pTcp4Protocol->Accept ( pTcp4Protocol,\r
                                          &pTcp4->ListenToken );\r
 \r
@@ -1209,7 +913,6 @@ EslTcpListenComplete4 (
         //\r
         TcpPortHandle = NULL;\r
         pTcp4 = &pNewPort->Context.Tcp4;\r
         //\r
         TcpPortHandle = NULL;\r
         pTcp4 = &pNewPort->Context.Tcp4;\r
-        pTcp4->bConfigured = TRUE;\r
 \r
         //\r
         //  Check for an accept call error\r
 \r
         //\r
         //  Check for an accept call error\r
@@ -1218,9 +921,10 @@ EslTcpListenComplete4 (
           //\r
           //  Get the port configuration\r
           //\r
           //\r
           //  Get the port configuration\r
           //\r
+          pNewPort->bConfigured = TRUE;\r
           pConfigData = &pTcp4->ConfigData;\r
           pConfigData->ControlOption = &pTcp4->Option;\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
           Status = pTcp4Protocol->GetModeData ( pTcp4Protocol,\r
                                                 NULL,\r
                                                 pConfigData,\r
@@ -1276,7 +980,7 @@ EslTcpListenComplete4 (
             //\r
             //  Start the receive operation\r
             //\r
             //\r
             //  Start the receive operation\r
             //\r
-            EslTcpRxStart4 ( pNewPort );\r
+            EslSocketRxStart ( pNewPort );\r
           }\r
           else {\r
             DEBUG (( DEBUG_ERROR | DEBUG_CONNECTION | DEBUG_INFO,\r
           }\r
           else {\r
             DEBUG (( DEBUG_ERROR | DEBUG_CONNECTION | DEBUG_INFO,\r
@@ -1297,7 +1001,7 @@ EslTcpListenComplete4 (
           //\r
           //  Close the listening port\r
           //\r
           //\r
           //  Close the listening port\r
           //\r
-          EslTcpPortCloseStart4 ( pPort, TRUE, DEBUG_LISTEN );\r
+          EslSocketPortCloseStart ( pPort, TRUE, DEBUG_LISTEN );\r
         }\r
       }\r
 \r
         }\r
       }\r
 \r
@@ -1335,7 +1039,7 @@ EslTcpListenComplete4 (
     //  Process:\r
     //    Call close\r
     //    Release the resources\r
     //  Process:\r
     //    Call close\r
     //    Release the resources\r
-    \r
+\r
   }\r
 \r
   DBG_EXIT ( );\r
   }\r
 \r
   DBG_EXIT ( );\r
@@ -1343,142 +1047,234 @@ EslTcpListenComplete4 (
 \r
 \r
 /**\r
 \r
 \r
 /**\r
-  Allocate and initialize a DT_PORT structure.\r
+  Get the local socket address.\r
 \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
 \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
 \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
   )\r
 {\r
-  UINTN LengthInBytes;\r
   EFI_TCP4_ACCESS_POINT * pAccessPoint;\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
   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
     //\r
-    //  Allocate a port structure\r
+    //  The local address must not be the broadcast address\r
     //\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
     //\r
-    //  Initialize the port\r
+    //  Set the local address\r
     //\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
 \r
     //\r
-    //  Allocate the receive event\r
+    //  Determine if the default address is used\r
     //\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
 \r
     //\r
-    //  Allocate the urgent transmit event\r
+    //  Set the subnet mask\r
     //\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
     }\r
-    DEBUG (( DEBUG_CLOSE | DEBUG_POOL,\r
-              "0x%08x: Created urgent transmit event\r\n",\r
-              pTcp4->TxOobToken.CompletionToken.Event ));\r
 \r
     //\r
 \r
     //\r
-    //  Allocate the normal transmit event\r
+    //  Validate the IP address\r
     //\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
     }\r
-    DEBUG (( DEBUG_CLOSE | DEBUG_POOL,\r
-              "0x%08x: Created normal transmit event\r\n",\r
-              pTcp4->TxToken.CompletionToken.Event ));\r
+  }\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
                 Status ));\r
       pSocket->errno = ENOMEM;\r
       break;\r
@@ -1492,7 +1288,7 @@ EslTcpPortAllocate4 (
     //\r
     Status = gBS->CreateEvent (  EVT_NOTIFY_SIGNAL,\r
                                  TPL_SOCKETS,\r
     //\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
                                  pPort,\r
                                  &pTcp4->ConnectToken.CompletionToken.Event);\r
     if ( EFI_ERROR ( Status )) {\r
@@ -1507,89 +1303,30 @@ EslTcpPortAllocate4 (
               pTcp4->ConnectToken.CompletionToken.Event ));\r
 \r
     //\r
               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
     //\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
 \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
     //\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
 \r
     //\r
-    //  Return the port\r
+    //  Set the configuration flags\r
     //\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
     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
   //\r
   //  Return the operation status\r
   //\r
@@ -1601,127 +1338,35 @@ EslTcpPortAllocate4 (
 /**\r
   Close a TCP4 port.\r
 \r
 /**\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
 \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
   )\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
   EFI_STATUS Status;\r
-  \r
-  DBG_ENTER ( );\r
 \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
 \r
   //\r
   //  Locate the port in the socket list\r
   //\r
   Status = EFI_SUCCESS;\r
-  pLayer = &mEslLayer;\r
   DebugFlags = pPort->DebugFlags;\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
   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
 \r
   //\r
   //  Done with the connect event\r
@@ -1777,121 +1422,6 @@ EslTcpPortClose4 (
     }\r
   }\r
 \r
     }\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
   //\r
   //  Return the operation status\r
   //\r
@@ -1901,94 +1431,52 @@ EslTcpPortClose4 (
 \r
 \r
 /**\r
 \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
-  //\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
 \r
+  This routine is called by the ::EslSocketPortCloseTxDone\r
+  routine after the port completes all of the transmission.\r
 \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
 \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
   @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
   )\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
   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
   //\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 ));\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
   }\r
 \r
   //\r
@@ -2000,890 +1488,343 @@ EslTcpPortCloseStart4 (
 \r
 \r
 /**\r
 \r
 \r
 /**\r
-  Port close state 3\r
+  Receive data from a network connection.\r
 \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
 \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
 \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
-**/\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
 \r
-  DBG_ENTER ( );\r
+  @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed\r
 \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
   @param [in] BufferLength    Length of the the buffer\r
-  \r
+\r
   @param [in] pBuffer         Address of a buffer to receive the data.\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] 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
 \r
-  @retval EFI_SUCCESS - Socket data successfully received\r
+  @return   Returns the address of the next free byte in the buffer.\r
 \r
  **/\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 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
   )\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
   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
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Assume failure\r
+  //  Return the remote system address if requested\r
   //\r
   //\r
-  Status = EFI_UNSUPPORTED;\r
-  pSocket->errno = ENOTCONN;\r
-\r
-  //\r
-  //  Verify that the socket is connected\r
-  //\r
-  if (( SOCKET_STATE_CONNECTED == pSocket->State )\r
-    || ( PORT_STATE_RX_ERROR == pSocket->State )) {\r
+  if ( NULL != pAddress ) {\r
     //\r
     //\r
-    //  Locate the port\r
+    //  Build the remote address\r
     //\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
-          pSocket->RxError = EFI_SUCCESS;\r
-          switch ( Status ) {\r
-          default:\r
-            pSocket->errno = EIO;\r
-            break;\r
-          \r
-          case EFI_CONNECTION_FIN:\r
-            //\r
-            //  Continue to return zero bytes received when the\r
-            //  peer has successfully closed the connection\r
-            //\r
-            pSocket->RxError = EFI_CONNECTION_FIN;\r
-            *pDataLength = 0;\r
-            pSocket->errno = 0;\r
-            Status = EFI_SUCCESS;\r
-            break;\r
-\r
-          case EFI_CONNECTION_REFUSED:\r
-            pSocket->errno = ECONNREFUSED;\r
-            break;\r
-\r
-          case EFI_CONNECTION_RESET:\r
-            pSocket->errno = ECONNRESET;\r
-            break;\r
-\r
-          case EFI_HOST_UNREACHABLE:\r
-            pSocket->errno = EHOSTUNREACH;\r
-            break;\r
-          \r
-          case EFI_NETWORK_UNREACHABLE:\r
-            pSocket->errno = ENETUNREACH;\r
-            break;\r
-          \r
-          case EFI_PORT_UNREACHABLE:\r
-            pSocket->errno = EPROTONOSUPPORT;\r
-            break;\r
-          \r
-          case EFI_PROTOCOL_UNREACHABLE:\r
-            pSocket->errno = ENOPROTOOPT;\r
-            break;\r
-          }\r
-        }\r
-        else {\r
-          Status = EFI_NOT_READY;\r
-          pSocket->errno = EAGAIN;\r
-        }\r
-      }\r
-    }\r
+    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
   }\r
 \r
   //\r
-  //  Return the operation status\r
+  //  Determine the amount of received data\r
   //\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
 \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
 \r
   //\r
-  //  Assume failure\r
+  //  Set the next buffer address\r
   //\r
   //\r
-  Status = EFI_NOT_FOUND;\r
+  pBuffer += DataLength;\r
 \r
   //\r
 \r
   //\r
-  //  Locate the port\r
+  //  Determine if the data is being read\r
   //\r
   //\r
-  pPort = pSocket->pPortList;\r
-  if ( NULL != pPort ) {\r
+  if ( *pbConsumePacket ) {\r
     //\r
     //\r
-    //  Determine if a receive is pending\r
+    //  Account for the bytes consumed\r
     //\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
       //\r
-      //  Attempt to cancel the receive operation\r
+      //  All done with this packet\r
+      //  Account for any discarded data\r
       //\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
     }\r
   }\r
 \r
   //\r
-  //  Return the operation status\r
+  //  Return the data length and the buffer address\r
   //\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
 }\r
 \r
 \r
 /**\r
-  Process the receive completion\r
+  Get the remote socket address.\r
 \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
 \r
-  @param  Event         The receive completion event\r
+  @param [in] pPort       Address of an ::ESL_PORT structure.\r
 \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
 \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
-{\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
-    //\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
-    //\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
 \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
 \r
-  @param [in] pPort       Address of the DT_PORT structure.\r
+  @retval EFI_SUCCESS     The operation was successful\r
 \r
  **/\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
   )\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
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Determine if a receive is already pending\r
+  //  Set the remote address\r
   //\r
   //\r
-  Status = EFI_SUCCESS;\r
-  pPacket = NULL;\r
-  pSocket = pPort->pSocket;\r
   pTcp4 = &pPort->Context.Tcp4;\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
   }\r
 \r
-  DBG_EXIT ( );\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
 }\r
 \r
 \r
 /**\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
 \r
-  This routine undoes the work performed by ::TcpInitialize4.\r
+  @param [in] Event     The receive completion event\r
 \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
 \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
   )\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
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Verify the socket layer synchronization\r
+  //  Get the operation status.\r
   //\r
   //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
+  Status = pIo->Token.Tcp4Rx.CompletionToken.Status;\r
 \r
   //\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
   //\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
-      //\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
 \r
   //\r
-  //  Remove the service from the service list\r
+  //  Complete this request\r
   //\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
 \r
   DBG_EXIT ( );\r
 }\r
@@ -2892,16 +1833,21 @@ EslTcpShutdown4 (
 /**\r
   Determine if the socket is configured.\r
 \r
 /**\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
 \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
   @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
   )\r
 {\r
   EFI_STATUS Status;\r
@@ -2924,52 +1870,58 @@ EslTcpShutdown4 (
 /**\r
   Buffer data for transmission over a network connection.\r
 \r
 /**\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
 \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
 \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
   @param [in] Flags           Message control flags\r
-  \r
+\r
   @param [in] BufferLength    Length of the the buffer\r
   @param [in] BufferLength    Length of the the buffer\r
-  \r
+\r
   @param [in] pBuffer         Address of a buffer to receive the data.\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] 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
   @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
   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
   )\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
   size_t * pTxBytes;\r
   EFI_TCP4_TRANSMIT_DATA * pTxData;\r
   EFI_STATUS Status;\r
@@ -2982,7 +1934,7 @@ EslTcpTxBuffer4 (
   //\r
   Status = EFI_UNSUPPORTED;\r
   pSocket->errno = ENOTCONN;\r
   //\r
   Status = EFI_UNSUPPORTED;\r
   pSocket->errno = ENOTCONN;\r
-  * pDataLength = 0;\r
+  *pDataLength = 0;\r
 \r
   //\r
   //  Verify that the socket is connected\r
 \r
   //\r
   //  Verify that the socket is connected\r
@@ -2996,20 +1948,22 @@ EslTcpTxBuffer4 (
       //\r
       //  Determine the queue head\r
       //\r
       //\r
       //  Determine the queue head\r
       //\r
-      pTcp4 = &pPort->Context.Tcp4;\r
       bUrgent = (BOOLEAN)( 0 != ( Flags & MSG_OOB ));\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
         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
         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
         pTxBytes = &pSocket->TxBytes;\r
       }\r
 \r
@@ -3018,6 +1972,15 @@ EslTcpTxBuffer4 (
       //  transmit operation\r
       //\r
       if ( pSocket->MaxTxBuf > *pTxBytes ) {\r
       //  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
         //\r
         //  Attempt to allocate the packet\r
         //\r
@@ -3025,13 +1988,14 @@ EslTcpTxBuffer4 (
                                            sizeof ( pPacket->Op.Tcp4Tx )\r
                                            - sizeof ( pPacket->Op.Tcp4Tx.Buffer )\r
                                            + BufferLength,\r
                                            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
                                            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
           pTxData->Urgent = bUrgent;\r
           pTxData->DataLength = (UINT32) BufferLength;\r
           pTxData->FragmentCount = 1;\r
@@ -3078,7 +2042,7 @@ EslTcpTxBuffer4 (
             DEBUG (( DEBUG_TX,\r
                       "0x%08x: Packet on %s transmit list\r\n",\r
                       pPacket,\r
             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
 \r
             //\r
             //  Account for the buffered data\r
@@ -3089,12 +2053,12 @@ EslTcpTxBuffer4 (
             //\r
             //  Start the transmit engine if it is idle\r
             //\r
             //\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
             }\r
           }\r
           else {\r
@@ -3124,6 +2088,14 @@ EslTcpTxBuffer4 (
         }\r
       }\r
       else {\r
         }\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
         //\r
         //  Not enough buffer space available\r
         //\r
@@ -3144,104 +2116,56 @@ EslTcpTxBuffer4 (
 /**\r
   Process the normal data transmit completion\r
 \r
 /**\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
 \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
 \r
 **/\r
 VOID\r
-EslTcpTxComplete4 (\r
+EslTcp4TxComplete (\r
   IN EFI_EVENT Event,\r
   IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
+  IN ESL_IO_MGMT * pIo\r
   )\r
 {\r
   UINT32 LengthInBytes;\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
   EFI_STATUS Status;\r
-  \r
+\r
   DBG_ENTER ( );\r
   DBG_ENTER ( );\r
-  \r
+\r
   //\r
   //  Locate the active transmit packet\r
   //\r
   //\r
   //  Locate the active transmit packet\r
   //\r
+  pPacket = pIo->pPacket;\r
+  pPort = pIo->pPort;\r
   pSocket = pPort->pSocket;\r
   pSocket = pPort->pSocket;\r
-  pTcp4 = &pPort->Context.Tcp4;\r
-  pPacket = pTcp4->pTxPacket;\r
-  \r
+\r
   //\r
   //\r
-  //  Mark this packet as complete\r
+  //  Get the transmit length and status\r
   //\r
   //\r
-  pTcp4->pTxPacket = NULL;\r
   LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength;\r
   pSocket->TxBytes -= LengthInBytes;\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
 \r
   //\r
-  //  Finish the close operation if necessary\r
+  //  Complete the transmit operation\r
   //\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
   DBG_EXIT ( );\r
 }\r
 \r
@@ -3249,23 +2173,27 @@ EslTcpTxComplete4 (
 /**\r
   Process the urgent data transmit completion\r
 \r
 /**\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
 \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
 \r
 **/\r
 VOID\r
-EslTcpTxOobComplete4 (\r
+EslTcp4TxOobComplete (\r
   IN EFI_EVENT Event,\r
   IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
+  IN ESL_IO_MGMT * pIo\r
   )\r
 {\r
   UINT32 LengthInBytes;\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
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
@@ -3273,150 +2201,232 @@ EslTcpTxOobComplete4 (
   //\r
   //  Locate the active transmit packet\r
   //\r
   //\r
   //  Locate the active transmit packet\r
   //\r
+  pPacket = pIo->pPacket;\r
+  pPort = pIo->pPort;\r
   pSocket = pPort->pSocket;\r
   pSocket = pPort->pSocket;\r
-  pTcp4 = &pPort->Context.Tcp4;\r
-  pPacket = pTcp4->pTxOobPacket;\r
 \r
   //\r
 \r
   //\r
-  //  Mark this packet as complete\r
+  //  Get the transmit length and status\r
   //\r
   //\r
-  pTcp4->pTxOobPacket = NULL;\r
   LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength;\r
   pSocket->TxOobBytes -= LengthInBytes;\r
   LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength;\r
   pSocket->TxOobBytes -= LengthInBytes;\r
+  Status = pIo->Token.Tcp4Tx.CompletionToken.Status;\r
 \r
   //\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
   //\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
   DBG_EXIT ( );\r
 }\r
 \r
 \r
 /**\r
-  Transmit data using a network connection.\r
+  Verify the adapter's IP address\r
 \r
 \r
+  This support routine is called by EslSocketBindTest.\r
 \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
 \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
   )\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
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Assume success\r
+  //  Use break instead of goto\r
   //\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
-  //\r
-  //  Get the packet from the queue head\r
-  //\r
-  pPacket = *ppQueueHead;\r
-  if ( NULL != pPacket ) {\r
     //\r
     //\r
-    //  Remove the packet from the queue\r
+    // Get the interface information size.\r
     //\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
     }\r
 \r
     //\r
-    //  Set the packet as active\r
+    //  Allocate the interface information buffer\r
     //\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
 \r
     //\r
-    //  Start the transmit operation\r
+    // Get the interface info.\r
     //\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
     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
+    //\r
+    //  The IP address did not match\r
+    //\r
+    Status = EFI_NOT_STARTED;\r
+    break;\r
   }\r
 \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
+/**\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