]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/EfiSocketLib/Socket.c
1. Update PXE driver to support PXEv6 boot cross subnet.
[mirror_edk2.git] / StdLib / EfiSocketLib / Socket.c
index acb23677aa6a8650c8c88910f57764ee2282555e..d53473e9c9acd024214531020457d9c4bcaaacfd 100644 (file)
@@ -5,10 +5,10 @@
   * Bound - pSocket->PortList is not NULL\r
   * Listen - AcceptWait event is not NULL\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
+  Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials are licensed and made available under\r
+  the terms and conditions of the BSD License that accompanies this distribution.\r
+  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
 \r
   <code><pre>\r
 \r
-                +-------------+   +-------------+   +-------------+   \r
+                +---------------+   +-------------+   +-------------+\r
   Service Lists | ::ESL_SERVICE |-->| ESL_SERVICE |-->| ESL_SERVICE |--> NULL (pNext)\r
-                +-------------+   +-------------+   +-------------+   \r
+                +---------------+   +-------------+   +-------------+\r
                   ^                       | (pPortList)    |\r
     pUdp4List ^   | pTcp4List             |                |\r
               |   |                       |                |\r
           ^   |   |                       |                |\r
  pIp4List |   |   |                       |                |\r
         +---------------+                 |                |\r
-        |   ::ESL_LAYER   |   ::mEslLayer     |                |\r
+        | ::ESL_LAYER   | ::mEslLayer     |                |\r
         +---------------+                 |                |\r
                   | (pSocketList)         |                |\r
     Socket List   V                       V                V\r
-                +-------------+   +-------------+   +-------------+   \r
-                | ::ESL_SOCKET  |-->|   ::ESL_PORT  |-->|   ESL_PORT  |--> NULL (pLinkSocket)\r
-                +-------------+   +-------------+   +-------------+   \r
+                +---------------+   +-------------+   +-------------+\r
+                | ::ESL_SOCKET  |-->| ::ESL_PORT  |-->|   ESL_PORT  |--> NULL (pLinkSocket)\r
+                +---------------+   +-------------+   +-------------+\r
                   |                       |                |\r
                   |                       |                V\r
                   V                       V               NULL\r
-                +-------------+   +-------------+         \r
+                +-------------+   +-------------+\r
                 | ESL_SOCKET  |-->|   ESL_PORT  |--> NULL\r
                 +-------------+   +-------------+\r
                   |    | | | |            |\r
@@ -53,9 +53,9 @@
                        | `---------------.                  |                |\r
   pTxOobPacketListHead |                 |                  |                |\r
                        V                 V                  V                V\r
-                  +------------+    +------------+    +------------+    +------------+\r
+                  +--------------+    +------------+    +------------+    +------------+\r
                   | ::ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |\r
-                  +------------+    +------------+    +------------+    +------------+\r
+                  +--------------+    +------------+    +------------+    +------------+\r
                          |                 |                |                |\r
                          V                 V                V                V\r
                   +------------+    +------------+    +------------+    +------------+\r
       ::EslTcp4PortCloseOp.\r
     </li>\r
     <li>State: PORT_STATE_CLOSE_TX_DONE</li>\r
-    <li>Arc: ::EslSocketPortCloseComplete - Called when the close operation is \r
+    <li>Arc: ::EslSocketPortCloseComplete - Called when the close operation is\r
       complete.  After the transition to PORT_STATE_CLOSE_DONE,\r
       this routine calls ::EslSocketRxCancel to abort the pending receive operations.\r
     </li>\r
          pPort->pRxActive\r
                 |\r
                 V\r
-          +-------------+   +-------------+   +-------------+   \r
+          +-------------+   +-------------+   +-------------+\r
   Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-          +-------------+   +-------------+   +-------------+   \r
+          +-------------+   +-------------+   +-------------+\r
 \r
-          +-------------+   +-------------+   +-------------+   \r
+          +-------------+   +-------------+   +-------------+\r
   Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-          +-------------+   +-------------+   +-------------+   \r
+          +-------------+   +-------------+   +-------------+\r
                 ^\r
                 |\r
           pPort->pRxFree\r
 \r
 <code><pre>\r
 \r
-                    +------------+   +------------+   \r
+                    +------------+   +------------+\r
     High     .----->| ESL_PACKET |-->| ESL_PACKET |--> NULL (pNext)\r
   Priority   |      +------------+   +------------+\r
              |\r
        +------------+\r
              | pRxPacketListHead\r
     Low      |\r
-  Priority   |      +------------+   +------------+   +------------+   \r
+  Priority   |      +------------+   +------------+   +------------+\r
              `----->| ::ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL\r
-                    +------------+   +------------+   +------------+   \r
+                    +------------+   +------------+   +------------+\r
 \r
 </pre></code>\r
 \r
   ::EslSocketRxStart connects an ::ESL_PACKET structure to the ::ESL_IO_MGMT structure\r
-  and then calls the network layer to start the receive operation.  Upon \r
+  and then calls the network layer to start the receive operation.  Upon\r
   receive completion, ::EslSocketRxComplete breaks the connection between these\r
   structrues and places the ESL_IO_MGMT structure onto the ESL_PORT::pRxFree list to\r
   make token and event available for another receive operation.  EslSocketRxComplete\r
      *ppQueueHead: pSocket->pRxPacketListHead or pSocket->pRxOobPacketListHead\r
           |\r
           V\r
-        +------------+   +------------+   +------------+   \r
+        +------------+   +------------+   +------------+\r
   Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL\r
-        +------------+   +------------+   +------------+   \r
+        +------------+   +------------+   +------------+\r
                                                      ^\r
                                                      |\r
      *ppQueueTail: pSocket->pRxPacketListTail or pSocket->pRxOobPacketListTail\r
          pPort->pTxActive or pTxOobActive\r
                 |\r
                 V\r
-          +-------------+   +-------------+   +-------------+   \r
+          +-------------+   +-------------+   +-------------+\r
   Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-          +-------------+   +-------------+   +-------------+   \r
+          +-------------+   +-------------+   +-------------+\r
 \r
-          +-------------+   +-------------+   +-------------+   \r
+          +-------------+   +-------------+   +-------------+\r
   Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-          +-------------+   +-------------+   +-------------+   \r
+          +-------------+   +-------------+   +-------------+\r
                 ^\r
                 |\r
           pPort->pTxFree or pTxOobFree\r
@@ -956,7 +956,7 @@ EslSocketAccept (
 \r
 /**\r
   Allocate and initialize a ESL_SOCKET structure.\r
-  \r
+\r
   This support function allocates an ::ESL_SOCKET structure\r
   and installs a protocol on ChildHandle.  If pChildHandle is a\r
   pointer to NULL, then a new handle is created and returned in\r
@@ -965,7 +965,7 @@ EslSocketAccept (
 \r
   @param [in, out] pChildHandle Pointer to the handle of the child to create.\r
                                 If it is NULL, then a new handle is created.\r
-                                If it is a pointer to an existing UEFI handle, \r
+                                If it is a pointer to an existing UEFI handle,\r
                                 then the protocol is added to the existing UEFI\r
                                 handle.\r
   @param [in] DebugFlags        Flags for debug messages\r
@@ -976,7 +976,7 @@ EslSocketAccept (
   @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to create\r
                                 the child\r
   @retval other                 The child handle was not created\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -1336,27 +1336,40 @@ EslSocketBindTest (
   pConfigData = (VOID *)pBuffer;\r
 \r
   //\r
-  //  Attempt to use this configuration\r
+  //  Validate that the port is connected\r
   //\r
-  Status = pPort->pfnConfigure ( pPort->pProtocol.v, pConfigData );\r
+  Status = pPort->pSocket->pApi->pfnVerifyLocalIpAddress ( pPort, pBuffer );\r
   if ( EFI_ERROR ( Status )) {\r
     DEBUG (( DEBUG_WARN | DEBUG_BIND,\r
-              "WARNING - Port 0x%08x failed configuration, Status: %r\r\n",\r
+              "WARNING - Port 0x%08x invalid IP address: %r\r\n",\r
               pPort,\r
               Status ));\r
     pPort->pSocket->errno = ErrnoValue;\r
   }\r
   else {\r
     //\r
-    //  Reset the port\r
+    //  Attempt to use this configuration\r
     //\r
-    Status = pPort->pfnConfigure ( pPort->pProtocol.v, NULL );\r
+    Status = pPort->pfnConfigure ( pPort->pProtocol.v, pConfigData );\r
     if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_BIND,\r
-                "ERROR - Port 0x%08x failed configuration reset, Status: %r\r\n",\r
+      DEBUG (( DEBUG_WARN | DEBUG_BIND,\r
+                "WARNING - Port 0x%08x failed configuration, Status: %r\r\n",\r
                 pPort,\r
                 Status ));\r
-      ASSERT ( EFI_SUCCESS == Status );\r
+      pPort->pSocket->errno = ErrnoValue;\r
+    }\r
+    else {\r
+      //\r
+      //  Reset the port\r
+      //\r
+      Status = pPort->pfnConfigure ( pPort->pProtocol.v, NULL );\r
+      if ( EFI_ERROR ( Status )) {\r
+        DEBUG (( DEBUG_ERROR | DEBUG_BIND,\r
+                  "ERROR - Port 0x%08x failed configuration reset, Status: %r\r\n",\r
+                  pPort,\r
+                  Status ));\r
+        ASSERT ( EFI_SUCCESS == Status );\r
+      }\r
     }\r
   }\r
 \r
@@ -1631,15 +1644,15 @@ EslSocketCloseStart (
   connection with the specified remote system.  This routine\r
   is designed to be polled by the connect routine for completion\r
   of the network connection.\r
-  \r
+\r
   @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
 \r
   @param [in] pSockAddr       Network address of the remote system.\r
-    \r
+\r
   @param [in] SockAddrLength  Length in bytes of the network address.\r
-  \r
+\r
   @param [out] pErrno   Address to receive the errno value upon completion.\r
-  \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
@@ -1658,7 +1671,7 @@ EslSocketConnect (
   ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
-  \r
+\r
   DEBUG (( DEBUG_CONNECT, "Entering SocketConnect\r\n" ));\r
 \r
   //\r
@@ -1790,6 +1803,11 @@ EslSocketConnect (
         break;\r
 \r
       case SOCKET_STATE_CONNECTING:\r
+        //\r
+        //  Poll the network adapter\r
+        //\r
+        EslSocketRxPoll ( pSocket );\r
+\r
         //\r
         //  Poll for connection completion\r
         //\r
@@ -1807,15 +1825,7 @@ EslSocketConnect (
           //  Set the next state if connected\r
           //\r
           if ( EFI_NOT_READY != Status ) {\r
-            if ( !EFI_ERROR ( Status )) {\r
-              pSocket->State = SOCKET_STATE_CONNECTED;\r
-\r
-              //\r
-              //  Start the receive operations\r
-              //\r
-              EslSocketRxStart ( pSocket->pPortList );\r
-            }\r
-            else {\r
+            if ( EFI_ERROR ( Status )) {\r
               pSocket->State = SOCKET_STATE_BOUND;\r
             }\r
           }\r
@@ -1824,10 +1834,9 @@ EslSocketConnect (
 \r
       case SOCKET_STATE_CONNECTED:\r
         //\r
-        //  Already connected\r
+        //  Connected\r
         //\r
-        pSocket->errno = EISCONN;\r
-        Status = EFI_ALREADY_STARTED;\r
+        Status = EFI_SUCCESS;\r
         break;\r
       }\r
 \r
@@ -1945,6 +1954,168 @@ EslSocketCopyFragmentedBuffer (
 }\r
 \r
 \r
+/**\r
+  Free the socket.\r
+\r
+  This routine frees the socket structure and handle resources.\r
+\r
+  The ::close routine calls EslServiceFreeProtocol which then calls\r
+  this routine to free the socket context structure and close the\r
+  handle.\r
+\r
+  @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
+\r
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS   The socket resources were returned successfully.\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketFree (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  EFI_HANDLE ChildHandle;\r
+  int errno;\r
+  ESL_LAYER * pLayer;\r
+  ESL_SOCKET * pSocket;\r
+  ESL_SOCKET * pSocketPrevious;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume failure\r
+  //\r
+  errno = EIO;\r
+  pSocket = NULL;\r
+  Status = EFI_INVALID_PARAMETER;\r
+\r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pLayer = &mEslLayer;\r
+  if ( NULL != pSocketProtocol ) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+    //\r
+    //  Synchronize with the socket layer\r
+    //\r
+    RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+    //\r
+    //  Walk the socket list\r
+    //\r
+    pSocketPrevious = pLayer->pSocketList;\r
+    if ( NULL != pSocketPrevious ) {\r
+      if ( pSocket == pSocketPrevious ) {\r
+        //\r
+        //  Remove the socket from the head of the list\r
+        //\r
+        pLayer->pSocketList = pSocket->pNext;\r
+      }\r
+      else {\r
+        //\r
+        //  Find the socket in the middle of the list\r
+        //\r
+        while (( NULL != pSocketPrevious )\r
+          && ( pSocket != pSocketPrevious->pNext )) {\r
+          //\r
+          //  Set the next socket\r
+          //\r
+          pSocketPrevious = pSocketPrevious->pNext;\r
+        }\r
+        if ( NULL != pSocketPrevious ) {\r
+          //\r
+          //  Remove the socket from the middle of the list\r
+          //\r
+          pSocketPrevious = pSocket->pNext;\r
+        }\r
+      }\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
+                "ERROR - Socket list is empty!\r\n" ));\r
+    }\r
+\r
+    //\r
+    //  Release the socket layer synchronization\r
+    //\r
+    RESTORE_TPL ( TplPrevious );\r
+\r
+    //\r
+    //  Determine if the socket was found\r
+    //\r
+    if ( NULL != pSocketPrevious ) {\r
+      pSocket->pNext = NULL;\r
+\r
+      //\r
+      //  Remove the socket protocol\r
+      //\r
+      ChildHandle = pSocket->SocketProtocol.SocketHandle;\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                ChildHandle,\r
+                &gEfiSocketProtocolGuid,\r
+                &pSocket->SocketProtocol,\r
+                NULL );\r
+      if ( !EFI_ERROR ( Status )) {\r
+        DEBUG (( DEBUG_POOL | DEBUG_INFO,\r
+                    "Removed:   gEfiSocketProtocolGuid from 0x%08x\r\n",\r
+                    ChildHandle ));\r
+\r
+        //\r
+        //  Free the socket structure\r
+        //\r
+        Status = gBS->FreePool ( pSocket );\r
+        if ( !EFI_ERROR ( Status )) {\r
+          DEBUG (( DEBUG_POOL,\r
+                    "0x%08x: Free pSocket, %d bytes\r\n",\r
+                    pSocket,\r
+                    sizeof ( *pSocket )));\r
+          errno = 0;\r
+        }\r
+        else {\r
+          DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
+                    "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",\r
+                    pSocket,\r
+                    Status ));\r
+        }\r
+      }\r
+      else {\r
+        DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,\r
+                    "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",\r
+                    ChildHandle,\r
+                    Status ));\r
+      }\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r
+                "ERROR - The socket was not in the socket list!\r\n" ));\r
+      Status = EFI_NOT_FOUND;\r
+    }\r
+  }\r
+  else {\r
+    DEBUG (( DEBUG_ERROR,\r
+              "ERROR - Invalid parameter pSocketProtocol is NULL\r\n" ));\r
+  }\r
+\r
+  //\r
+  //  Return the errno value if possible\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    *pErrno = errno;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
 /**\r
   Get the local address.\r
 \r
@@ -1955,7 +2126,7 @@ EslSocketCopyFragmentedBuffer (
   address associated with the local host connection point.\r
 \r
   @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  \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
@@ -1978,14 +2149,14 @@ EslSocketGetLocalAddress (
   ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
-  \r
+\r
   DBG_ENTER ( );\r
-  \r
+\r
   //\r
   //  Assume success\r
   //\r
   Status = EFI_SUCCESS;\r
-  \r
+\r
   //\r
   //  Validate the socket\r
   //\r
@@ -2024,7 +2195,7 @@ EslSocketGetLocalAddress (
             //  Verify the address length\r
             //\r
             LengthInBytes = pSocket->pApi->AddressLength;\r
-            if (( LengthInBytes <= *pAddressLength ) \r
+            if (( LengthInBytes <= *pAddressLength )\r
               && ( 255 >= LengthInBytes )) {\r
               //\r
               //  Return the local address and address length\r
@@ -2045,7 +2216,7 @@ EslSocketGetLocalAddress (
             pSocket->errno = ENOTCONN;\r
             Status = EFI_NOT_STARTED;\r
           }\r
-          \r
+\r
           //\r
           //  Release the socket layer synchronization\r
           //\r
@@ -2065,7 +2236,7 @@ EslSocketGetLocalAddress (
       pSocket->errno = EADDRNOTAVAIL;\r
     }\r
   }\r
-  \r
+\r
   //\r
   //  Return the operation status\r
   //\r
@@ -2093,7 +2264,7 @@ EslSocketGetLocalAddress (
   address of the remote connection point.\r
 \r
   @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  \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
@@ -2116,14 +2287,14 @@ EslSocketGetPeerAddress (
   ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
-  \r
+\r
   DBG_ENTER ( );\r
-  \r
+\r
   //\r
   //  Assume success\r
   //\r
   Status = EFI_SUCCESS;\r
-  \r
+\r
   //\r
   //  Validate the socket\r
   //\r
@@ -2799,7 +2970,7 @@ EslSocketOptionGet (
         pOptionData = (CONST UINT8 *)&pSocket->RxTimeout;\r
         LengthInBytes = sizeof ( pSocket->RxTimeout );\r
         break;\r
-        \r
+\r
       case SO_RCVBUF:\r
         //\r
         //  Return the maximum receive buffer size\r
@@ -2815,7 +2986,7 @@ EslSocketOptionGet (
         pOptionData = (UINT8 *)&pSocket->bReUseAddr;\r
         LengthInBytes = sizeof ( pSocket->bReUseAddr );\r
         break;\r
-      \r
+\r
       case SO_SNDBUF:\r
         //\r
         //  Return the maximum transmit buffer size\r
@@ -2917,9 +3088,9 @@ EslSocketOptionSet (
   UINT8 * pOptionData;\r
   ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
-  \r
+\r
   DBG_ENTER ( );\r
-  \r
+\r
   //\r
   //  Assume failure\r
   //\r
@@ -2978,7 +3149,7 @@ EslSocketOptionSet (
         errno = ENOPROTOOPT;\r
         Status = EFI_INVALID_PARAMETER;\r
         break;\r
-    \r
+\r
       case SOL_SOCKET:\r
         switch ( OptionName ) {\r
         default:\r
@@ -3191,7 +3362,7 @@ EslSocketPacketFree (
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Allocate a packet structure\r
+  //  Free a packet structure\r
   //\r
   LengthInBytes = pPacket->PacketSize;\r
   Status = gBS->FreePool ( pPacket );\r
@@ -3291,13 +3462,13 @@ EslSocketPoll (
       //  Synchronize with the socket layer\r
       //\r
       RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-      \r
+\r
       //\r
       //  Increase the network performance by extending the\r
       //  polling (idle) loop down into the LAN driver\r
       //\r
       EslSocketRxPoll ( pSocket );\r
-      \r
+\r
       //\r
       //  Release the socket layer synchronization\r
       //\r
@@ -3673,7 +3844,7 @@ EslSocketPortAllocate (
     <li>::EslTcp4ConnectComplete - Connection failure and reducing the port list to a single port</li>\r
   </ul>\r
   See the \ref PortCloseStateMachine section.\r
-  \r
+\r
   @param [in] pPort       Address of an ::ESL_PORT structure.\r
 \r
   @retval EFI_SUCCESS     The port is closed\r
@@ -3694,7 +3865,7 @@ EslSocketPortClose (
   CONST ESL_SOCKET_BINDING * pSocketBinding;\r
   ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
-  \r
+\r
   DBG_ENTER ( );\r
 \r
   //\r
@@ -4289,13 +4460,13 @@ EslSocketPortCloseTxDone (
   ::recv and ::read are layered on top of ::recvfrom.\r
 \r
   @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  \r
+\r
   @param [in] Flags           Message control flags\r
-  \r
+\r
   @param [in] BufferLength    Length of the the buffer\r
-  \r
+\r
   @param [in] pBuffer         Address of a buffer to receive the data.\r
-  \r
+\r
   @param [in] pDataLength     Number of received data bytes in the buffer.\r
 \r
   @param [out] pAddress       Network address to receive the remote system address\r
@@ -4406,7 +4577,7 @@ EslSocketReceive (
                 pRemoteAddress->sa_family = pSocket->pApi->AddressFamily;\r
                 pRemoteAddress->sa_len = (UINT8)pSocket->pApi->AddressLength;\r
               }\r
-              \r
+\r
               //\r
               //  Synchronize with the socket layer\r
               //\r
@@ -4618,7 +4789,7 @@ EslSocketReceive (
         }\r
       }\r
 \r
-      \r
+\r
     }\r
     else {\r
       //\r
@@ -4744,13 +4915,13 @@ EslSocketRxComplete (
   //         pPort->pRxActive\r
   //                |\r
   //                V\r
-  //          +-------------+   +-------------+   +-------------+   \r
+  //          +-------------+   +-------------+   +-------------+\r
   //  Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-  //          +-------------+   +-------------+   +-------------+   \r
+  //          +-------------+   +-------------+   +-------------+\r
   //\r
-  //          +-------------+   +-------------+   +-------------+   \r
+  //          +-------------+   +-------------+   +-------------+\r
   //  Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-  //          +-------------+   +-------------+   +-------------+   \r
+  //          +-------------+   +-------------+   +-------------+\r
   //                ^\r
   //                |\r
   //          pPort->pRxFree\r
@@ -4784,13 +4955,13 @@ EslSocketRxComplete (
   //            pRxOobPacketListHead              pRxOobPacketListTail\r
   //                      |                                 |\r
   //                      V                                 V\r
-  //               +------------+   +------------+   +------------+   \r
+  //               +------------+   +------------+   +------------+\r
   //  Urgent Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL\r
-  //               +------------+   +------------+   +------------+   \r
+  //               +------------+   +------------+   +------------+\r
   //\r
-  //               +------------+   +------------+   +------------+   \r
+  //               +------------+   +------------+   +------------+\r
   //  Normal Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL\r
-  //               +------------+   +------------+   +------------+   \r
+  //               +------------+   +------------+   +------------+\r
   //                      ^                                 ^\r
   //                      |                                 |\r
   //              pRxPacketListHead                pRxPacketListTail\r
@@ -4961,7 +5132,7 @@ EslSocketRxPoll (
   <ul>\r
     <li>::EslIp4Receive to restart the receive engine to release flow control.</li>\r
     <li>::EslIp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>\r
-    <li>::EslIp4SocketIsConfigured to start the recevie engine for the new socket.</li>\r
+    <li>::EslIp4SocketIsConfigured to start the receive engine for the new socket.</li>\r
     <li>::EslTcp4ListenComplete to start the recevie engine for the new socket.</li>\r
     <li>::EslTcp4Receive to restart the receive engine to release flow control.</li>\r
     <li>::EslTcp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>\r
@@ -5076,13 +5247,13 @@ EslSocketRxStart (
           //  Allocate the receive control structure\r
           //\r
           pPort->pRxFree = pIo->pNext;\r
-          \r
+\r
           //\r
           //  Mark this receive as pending\r
           //\r
           pIo->pNext = pPort->pRxActive;\r
           pPort->pRxActive = pIo;\r
-          \r
+\r
         }\r
         else {\r
           DEBUG (( DEBUG_RX | DEBUG_INFO,\r
@@ -5144,9 +5315,9 @@ EslSocketRxStart (
   operations on the socket.\r
 \r
   @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  \r
+\r
   @param [in] How             Which operations to stop\r
-  \r
+\r
   @param [out] pErrno         Address to receive the errno value upon completion.\r
 \r
   @retval EFI_SUCCESS - Socket operations successfully shutdown\r
@@ -5164,9 +5335,9 @@ EslSocketShutdown (
   ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
-  \r
+\r
   DBG_ENTER ( );\r
-  \r
+\r
   //\r
   //  Assume success\r
   //\r
@@ -5283,13 +5454,13 @@ EslSocketShutdown (
   system.  Note that ::send and ::write are layered on top of ::sendto.\r
 \r
   @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
-  \r
+\r
   @param [in] Flags           Message control flags\r
-  \r
+\r
   @param [in] BufferLength    Length of the the buffer\r
-  \r
+\r
   @param [in] pBuffer         Address of a buffer containing the data to send\r
-  \r
+\r
   @param [in] pDataLength     Address to receive the number of data bytes sent\r
 \r
   @param [in] pAddress        Network address of the remote system address\r
@@ -5656,9 +5827,9 @@ EslSocketTxStart (
     //     *ppQueueHead: pSocket->pRxPacketListHead or pSocket->pRxOobPacketListHead\r
     //          |\r
     //          V\r
-    //        +------------+   +------------+   +------------+   \r
+    //        +------------+   +------------+   +------------+\r
     //  Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL\r
-    //        +------------+   +------------+   +------------+   \r
+    //        +------------+   +------------+   +------------+\r
     //                                                     ^\r
     //                                                     |\r
     //     *ppQueueTail: pSocket->pRxPacketListTail or pSocket->pRxOobPacketListTail\r
@@ -5729,9 +5900,9 @@ EslSocketTxStart (
       pIo->pPacket = pPacket;\r
 \r
       //\r
-      //          +-------------+   +-------------+   +-------------+   \r
+      //          +-------------+   +-------------+   +-------------+\r
       //  Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-      //          +-------------+   +-------------+   +-------------+   \r
+      //          +-------------+   +-------------+   +-------------+\r
       //              ^\r
       //              |\r
       //          *ppFree:  pPort->pTxFree or pTxOobFree\r
@@ -5740,14 +5911,14 @@ EslSocketTxStart (
       //  Remove the IO structure from the queue\r
       //\r
       *ppFree = pIo->pNext;\r
-      \r
+\r
       //\r
       //         *ppActive:  pPort->pTxActive or pTxOobActive\r
       //             |\r
       //             V\r
-      //          +-------------+   +-------------+   +-------------+   \r
+      //          +-------------+   +-------------+   +-------------+\r
       //  Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL\r
-      //          +-------------+   +-------------+   +-------------+   \r
+      //          +-------------+   +-------------+   +-------------+\r
       //\r
       //\r
       //  Mark this packet as active\r
@@ -5757,10 +5928,24 @@ EslSocketTxStart (
       *ppActive = pIo;\r
     }\r
     else {\r
+      //\r
+      //  Display the transmit error\r
+      //\r
+      DEBUG (( DEBUG_TX | DEBUG_INFO,\r
+                "0x%08x, 0x%08x: pIo, pPacket transmit failure: %r\r\n",\r
+                pIo,\r
+                pPacket,\r
+                Status ));\r
       if ( EFI_SUCCESS == pSocket->TxError ) {\r
         pSocket->TxError = Status;\r
       }\r
 \r
+      //\r
+      //  Free the IO structure\r
+      //\r
+      pIo->pNext = *ppFree;\r
+      *ppFree = pIo;\r
+\r
       //\r
       //  Discard the transmit buffer\r
       //\r