]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/EfiSocketLib/Socket.c
Add Socket Libraries.
[mirror_edk2.git] / StdLib / EfiSocketLib / Socket.c
diff --git a/StdLib/EfiSocketLib/Socket.c b/StdLib/EfiSocketLib/Socket.c
new file mode 100644 (file)
index 0000000..bad888c
--- /dev/null
@@ -0,0 +1,3091 @@
+/** @file\r
+  Implement the socket support for the socket layer.\r
+\r
+  Socket States:\r
+  * Bound - pSocket->PortList is not NULL\r
+  * Listen - AcceptWait event is not NULL\r
+\r
+  Copyright (c) 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
+\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
+\r
+#include "Socket.h"\r
+\r
+\r
+/**\r
+  Socket driver connection points\r
+\r
+  List the network stack connection points for the socket driver.\r
+**/\r
+CONST DT_SOCKET_BINDING cEslSocketBinding [] = {\r
+  { L"Tcp4",\r
+    &gEfiTcp4ServiceBindingProtocolGuid,\r
+    &mEslTcp4ServiceGuid,\r
+    EslTcpInitialize4,\r
+    EslTcpShutdown4 },\r
+  { L"Udp4",\r
+    &gEfiUdp4ServiceBindingProtocolGuid,\r
+    &mEslUdp4ServiceGuid,\r
+    EslUdpInitialize4,\r
+    EslUdpShutdown4 }\r
+};\r
+\r
+CONST UINTN cEslSocketBindingEntries = DIM ( cEslSocketBinding );\r
+\r
+DT_LAYER mEslLayer;\r
+\r
+\r
+/**\r
+  Initialize an endpoint for network communication.\r
+\r
+  The ::Socket routine initializes the communication endpoint by providing\r
+  the support for the socket library function ::socket.  The\r
+  <a href="http://www.linuxhowtos.org/manpages/2/socket.htm">Linux</a>,\r
+  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html">POSIX</a>\r
+  and <a href="http://msdn.microsoft.com/en-us/library/ms740506(v=VS.85).aspx">Windows</a>\r
+  documentation for the socket routine are available online for reference.\r
+\r
+  @param [in] pSocketProtocol Address of the socket protocol structure.\r
+  @param [in] domain    Select the family of protocols for the client or server\r
+                        application.\r
+\r
+  @param [in] type      Specifies how to make the network connection.  The following values\r
+                        are supported:\r
+                        <ul>\r
+                          <li>\r
+                            SOCK_STREAM - Connect to TCP, provides a byte stream\r
+                            that is manipluated by read, recv, send and write.\r
+                          </li>\r
+                          <li>\r
+                            SOCK_SEQPACKET - Connect to TCP, provides sequenced packet stream\r
+                            that is manipulated by read, recv, send and write.\r
+                          </li>\r
+                          <li>\r
+                            SOCK_DGRAM - Connect to UDP, provides a datagram service that is\r
+                            manipulated by recvfrom and sendto.\r
+                          </li>\r
+                        </ul>\r
+\r
+  @param [in] protocol  Specifies the lower layer protocol to use.  The following\r
+                        values are supported:\r
+                        <ul>\r
+                          <li>IPPROTO_TCP</li> - This value must be combined with SOCK_STREAM.</li>\r
+                          <li>IPPROTO_UDP</li> - This value must be combined with SOCK_DGRAM.</li>\r
+                        </ul>\r
+\r
+  @param [out] pErrno   Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS - Socket successfully created\r
+  @retval EFI_INVALID_PARAMETER - Invalid domain value, errno = EAFNOSUPPORT\r
+  @retval EFI_INVALID_PARAMETER - Invalid type value, errno = EINVAL\r
+  @retval EFI_INVALID_PARAMETER - Invalid protocol value, errno = EINVAL\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocket (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN int domain,\r
+  IN int type,\r
+  IN int protocol,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  int errno;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Locate the socket\r
+  //\r
+  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+  //\r
+  //  Set the default domain if necessary\r
+  //\r
+  if ( AF_UNSPEC == domain ) {\r
+    domain = AF_INET;\r
+  }\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  errno = 0;\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Use break instead of goto\r
+  //\r
+  for ( ; ; ) {\r
+    //\r
+    //  Validate the domain value\r
+    //\r
+    if (( AF_INET != domain )\r
+      && ( AF_LOCAL != domain ))\r
+    {\r
+      DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r
+                "ERROR - Invalid domain value" ));\r
+      Status = EFI_INVALID_PARAMETER;\r
+      errno = EAFNOSUPPORT;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Set the default type if necessary\r
+    //\r
+    if ( 0 == type ) {\r
+      type = SOCK_STREAM;\r
+    }\r
+\r
+    //\r
+    //  Validate the type value\r
+    //\r
+    if (( SOCK_STREAM == type )\r
+      || ( SOCK_SEQPACKET == type )) {\r
+      //\r
+      //  Set the default protocol if necessary\r
+      //\r
+      if ( 0 == protocol ) {\r
+        protocol = IPPROTO_TCP;\r
+      }\r
+    }\r
+    else if ( SOCK_DGRAM == type ) {\r
+      //\r
+      //  Set the default protocol if necessary\r
+      //\r
+      if ( 0 == protocol ) {\r
+        protocol = IPPROTO_UDP;\r
+      }\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r
+                "ERROR - Invalid type value" ));\r
+      Status = EFI_INVALID_PARAMETER;\r
+      errno = EINVAL;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Validate the protocol value\r
+    //\r
+    if (( IPPROTO_TCP != protocol )\r
+      && ( IPPROTO_UDP != protocol )) {\r
+      DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r
+                "ERROR - Invalid protocol value" ));\r
+      Status = EFI_INVALID_PARAMETER;\r
+      errno = EINVAL;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Save the socket attributes\r
+    //\r
+    pSocket->Domain = domain;\r
+    pSocket->Type = type;\r
+    pSocket->Protocol = protocol;\r
+\r
+    //\r
+    //  Done\r
+    //\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    *pErrno = errno;\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  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
+\r
+  @param [in] pSocketProtocol Address of the socket protocol structure.\r
+\r
+  @param [in] pSockAddr       Address of a buffer to receive the remote\r
+                              network address.\r
+\r
+  @param [in, out] pSockAddrLength  Length in bytes of the address buffer.\r
+                                    On output specifies the length of the\r
+                                    remote network address.\r
+\r
+  @param [out] ppSocketProtocol Address of a buffer to receive the socket protocol\r
+                                instance associated with the new socket.\r
+\r
+  @param [out] pErrno   Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS   New connection successfully created\r
+  @retval EFI_NOT_READY No connection is available\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketAccept (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN struct sockaddr * pSockAddr,\r
+  IN OUT socklen_t * pSockAddrLength,\r
+  IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  DT_SOCKET * pNewSocket;\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pSocket = NULL;\r
+  pNewSocket = NULL;\r
+  if ( NULL != pSocketProtocol ) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+    //\r
+    //  Validate the sockaddr\r
+    //\r
+    if (( NULL != pSockAddr )\r
+      && ( NULL == pSockAddrLength )) {\r
+      DEBUG (( DEBUG_ACCEPT,\r
+                "ERROR - pSockAddr is NULL!\r\n" ));\r
+      Status = EFI_INVALID_PARAMETER;\r
+      pSocket->errno = EFAULT;\r
+    }\r
+    else {\r
+      //\r
+      //  Synchronize with the socket layer\r
+      //\r
+      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+      //\r
+      //  Verify that the socket is in the listen state\r
+      //\r
+      if ( SOCKET_STATE_LISTENING != pSocket->State ) {\r
+        DEBUG (( DEBUG_ACCEPT,\r
+                  "ERROR - Socket is not listening!\r\n" ));\r
+        Status = EFI_NOT_STARTED;\r
+        pSocket->errno = EOPNOTSUPP;\r
+      }\r
+      else {\r
+        //\r
+        //  Determine if a socket is available\r
+        //\r
+        if ( 0 == pSocket->FifoDepth ) {\r
+          //\r
+          //  No connections available\r
+          //  Determine if any ports are available\r
+          //\r
+          if ( NULL == pSocket->pPortList ) {\r
+            //\r
+            //  No ports available\r
+            //\r
+            Status = EFI_DEVICE_ERROR;\r
+            pSocket->errno = EINVAL;\r
+\r
+            //\r
+            //  Update the socket state\r
+            //\r
+            pSocket->State = SOCKET_STATE_NO_PORTS;\r
+          }\r
+          else {\r
+            //\r
+            //  Ports are available\r
+            //  No connection requests at this time\r
+            //\r
+            Status = EFI_NOT_READY;\r
+            pSocket->errno = EAGAIN;\r
+          }\r
+        }\r
+        else {\r
+  \r
+          //\r
+          //  Get the remote network address\r
+          //\r
+          pNewSocket = pSocket->pFifoHead;\r
+          ASSERT ( NULL != pNewSocket );\r
+          switch ( pSocket->Domain ) {\r
+          default:\r
+            DEBUG (( DEBUG_ACCEPT,\r
+                      "ERROR - Invalid socket address family: %d\r\n",\r
+                      pSocket->Domain ));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            pSocket->errno = EADDRNOTAVAIL;\r
+            break;\r
+\r
+          case AF_INET:\r
+            //\r
+            //  Determine the connection point within the network stack\r
+            //\r
+            switch ( pSocket->Type ) {\r
+            default:\r
+              DEBUG (( DEBUG_ACCEPT,\r
+                        "ERROR - Invalid socket type: %d\r\n",\r
+                        pSocket->Type));\r
+              Status = EFI_INVALID_PARAMETER;\r
+              pSocket->errno = EADDRNOTAVAIL;\r
+              break;\r
+\r
+            case SOCK_STREAM:\r
+            case SOCK_SEQPACKET:\r
+              Status = EslTcpAccept4 ( pNewSocket,\r
+                                       pSockAddr,\r
+                                       pSockAddrLength );\r
+              break;\r
+\r
+  /*\r
+            case SOCK_DGRAM:\r
+              Status = UdpAccept4 ( pSocket );\r
+              break;\r
+  */\r
+            }\r
+            break;\r
+          }\r
+          if ( !EFI_ERROR ( Status )) {\r
+            //\r
+            //  Remove the new socket from the list\r
+            //\r
+            pSocket->pFifoHead = pNewSocket->pNextConnection;\r
+            if ( NULL == pSocket->pFifoHead ) {\r
+              pSocket->pFifoTail = NULL;\r
+            }\r
+\r
+            //\r
+            //  Account for this socket\r
+            //\r
+            pSocket->FifoDepth -= 1;\r
+\r
+            //\r
+            //  Update the new socket's state\r
+            //\r
+            pNewSocket->State = SOCKET_STATE_CONNECTED;\r
+            pNewSocket->bConfigured = TRUE;\r
+            DEBUG (( DEBUG_ACCEPT,\r
+                      "0x%08x: Socket connected\r\n",\r
+                      pNewSocket ));\r
+          }\r
+        }\r
+      }\r
+\r
+      //\r
+      //  Release the socket layer synchronization\r
+      //\r
+      RESTORE_TPL ( TplPrevious );\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the new socket\r
+  //\r
+  if (( NULL != ppSocketProtocol )\r
+    && ( NULL != pNewSocket )) {\r
+    *ppSocketProtocol = &pNewSocket->SocketProtocol;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    if ( NULL != pSocket ) {\r
+      *pErrno = pSocket->errno;\r
+    }\r
+    else\r
+    {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      *pErrno = EBADF;\r
+    }\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Allocate and initialize a DT_SOCKET structure.\r
+  \r
+  The ::SocketAllocate() function allocates a DT_SOCKET structure\r
+  and installs a protocol on ChildHandle.  If pChildHandle is a\r
+  pointer to NULL, then a new handle is created and returned in\r
+  pChildHandle.  If pChildHandle is not a pointer to NULL, then\r
+  the protocol installs on the existing pChildHandle.\r
+\r
+  @param [in, out] pChildHandle Pointer to the handle of the child to create.\r
+                                If it is NULL, then a new handle is created.\r
+                                If it is a pointer to an existing UEFI handle, \r
+                                then the protocol is added to the existing UEFI\r
+                                handle.\r
+  @param [in] DebugFlags        Flags for debug messages\r
+  @param [in, out] ppSocket     The buffer to receive the DT_SOCKET structure address.\r
+\r
+  @retval EFI_SUCCESS           The protocol was added to ChildHandle.\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources availabe to create\r
+                                the child\r
+  @retval other                 The child handle was not created\r
+  \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EslSocketAllocate (\r
+  IN OUT EFI_HANDLE * pChildHandle,\r
+  IN     UINTN DebugFlags,\r
+  IN OUT DT_SOCKET ** ppSocket\r
+  )\r
+{\r
+  UINTN LengthInBytes;\r
+  DT_LAYER * pLayer;\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Create a socket structure\r
+  //\r
+  LengthInBytes = sizeof ( *pSocket );\r
+  Status = gBS->AllocatePool (\r
+                  EfiRuntimeServicesData,\r
+                  LengthInBytes,\r
+                  (VOID **) &pSocket\r
+                  );\r
+  if ( !EFI_ERROR ( Status )) {\r
+    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
+              "0x%08x: Allocate pSocket, %d bytes\r\n",\r
+              pSocket,\r
+              LengthInBytes ));\r
+\r
+    //\r
+    //  Initialize the socket protocol\r
+    //\r
+    ZeroMem ( pSocket, LengthInBytes );\r
+\r
+    pSocket->Signature = SOCKET_SIGNATURE;\r
+    pSocket->SocketProtocol.pfnAccept = EslSocketAccept;\r
+    pSocket->SocketProtocol.pfnBind = EslSocketBind;\r
+    pSocket->SocketProtocol.pfnClosePoll = EslSocketClosePoll;\r
+    pSocket->SocketProtocol.pfnCloseStart = EslSocketCloseStart;\r
+    pSocket->SocketProtocol.pfnConnect = EslSocketConnect;\r
+    pSocket->SocketProtocol.pfnGetLocal = EslSocketGetLocalAddress;\r
+    pSocket->SocketProtocol.pfnGetPeer = EslSocketGetPeerAddress;\r
+    pSocket->SocketProtocol.pfnListen = EslSocketListen;\r
+    pSocket->SocketProtocol.pfnOptionGet = EslSocketOptionGet;\r
+    pSocket->SocketProtocol.pfnOptionSet = EslSocketOptionSet;\r
+    pSocket->SocketProtocol.pfnPoll = EslSocketPoll;\r
+    pSocket->SocketProtocol.pfnReceive = EslSocketReceive;\r
+    pSocket->SocketProtocol.pfnSend = EslSocketTransmit;\r
+    pSocket->SocketProtocol.pfnShutdown = EslSocketShutdown;\r
+    pSocket->SocketProtocol.pfnSocket = EslSocket;\r
+\r
+    pSocket->MaxRxBuf = MAX_RX_DATA;\r
+    pSocket->MaxTxBuf = MAX_TX_DATA;\r
+\r
+    //\r
+    //  Install the socket protocol on the specified handle\r
+    //\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    pChildHandle,\r
+                    &gEfiSocketProtocolGuid,\r
+                    &pSocket->SocketProtocol,\r
+                    NULL\r
+                    );\r
+    if ( !EFI_ERROR ( Status )) {\r
+      DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
+                "Installed: gEfiSocketProtocolGuid on   0x%08x\r\n",\r
+                *pChildHandle ));\r
+      pSocket->SocketProtocol.SocketHandle = *pChildHandle;\r
+\r
+      //\r
+      //  Synchronize with the socket layer\r
+      //\r
+      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+      //\r
+      //  Add this socket to the list\r
+      //\r
+      pLayer = &mEslLayer;\r
+      pSocket->pNext = pLayer->pSocketList;\r
+      pLayer->pSocketList = pSocket;\r
+\r
+      //\r
+      //  Release the socket layer synchronization\r
+      //\r
+      RESTORE_TPL ( TplPrevious );\r
+\r
+      //\r
+      //  Return the socket structure address\r
+      //\r
+      *ppSocket = pSocket;\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
+                "ERROR - Failed to install gEfiSocketProtocolGuid on 0x%08x, Status: %r\r\n",\r
+                *pChildHandle,\r
+                Status ));\r
+    }\r
+\r
+    //\r
+    //  Release the socket if necessary\r
+    //\r
+    if ( EFI_ERROR ( Status )) {\r
+      gBS->FreePool ( pSocket );\r
+      DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
+                "0x%08x: Free pSocket, %d bytes\r\n",\r
+                pSocket,\r
+                sizeof ( *pSocket )));\r
+      pSocket = NULL;\r
+    }\r
+  }\r
+  else {\r
+    DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
+              "ERROR - Failed socket allocation, Status: %r\r\n",\r
+              Status ));\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Bind a name to a socket.\r
+\r
+  The ::SocketBind routine connects a name to a socket on the local machine.  The\r
+  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html">POSIX</a>\r
+  documentation for the bind routine is available online for reference.\r
+\r
+  @param [in] pSocketProtocol Address of the socket protocol structure.\r
+\r
+  @param [in] pSockAddr Address of a sockaddr structure that contains the\r
+                        connection point on the local machine.  An IPv4 address\r
+                        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
+  @param [out] pErrno   Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS - Socket successfully created\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketBind (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN const struct sockaddr * pSockAddr,\r
+  IN socklen_t SockAddrLength,\r
+  OUT int * pErrno\r
+  )\r
+{\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pSocket = NULL;\r
+  if ( NULL != pSocketProtocol ) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+    //\r
+    //  Validate the structure pointer\r
+    //\r
+    if ( NULL == pSockAddr ) {\r
+      DEBUG (( DEBUG_BIND,\r
+                "ERROR - pSockAddr is NULL!\r\n" ));\r
+      Status = EFI_INVALID_PARAMETER;\r
+      pSocket->errno = EFAULT;\r
+    }\r
+    else{\r
+      //\r
+      //  Validate the name length\r
+      //\r
+      if (( SockAddrLength < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))\r
+        || ( pSockAddr->sa_len < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))) {\r
+        DEBUG (( DEBUG_BIND,\r
+                  "ERROR - Invalid bind name length: %d, sa_len: %d\r\n",\r
+                  SockAddrLength,\r
+                  pSockAddr->sa_len ));\r
+        Status = EFI_INVALID_PARAMETER;\r
+        pSocket->errno = EINVAL;\r
+      }\r
+      else {\r
+        //\r
+        //  Set the socket address length\r
+        //\r
+        if ( SockAddrLength > pSockAddr->sa_len ) {\r
+          SockAddrLength = pSockAddr->sa_len;\r
+        }\r
+\r
+        //\r
+        //  Synchronize with the socket layer\r
+        //\r
+        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+        //\r
+        //  Validate the local address\r
+        //\r
+        switch ( pSockAddr->sa_family ) {\r
+        default:\r
+          DEBUG (( DEBUG_BIND,\r
+                    "ERROR - Invalid bind address family: %d\r\n",\r
+                    pSockAddr->sa_family ));\r
+          Status = EFI_INVALID_PARAMETER;\r
+          pSocket->errno = EADDRNOTAVAIL;\r
+          break;\r
+\r
+        case AF_INET:\r
+          //\r
+          //  Determine the connection point within the network stack\r
+          //\r
+          switch ( pSocket->Type ) {\r
+          default:\r
+            DEBUG (( DEBUG_BIND,\r
+                      "ERROR - Invalid socket type: %d\r\n",\r
+                      pSocket->Type));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            pSocket->errno = EADDRNOTAVAIL;\r
+            break;\r
+\r
+          case SOCK_STREAM:\r
+          case SOCK_SEQPACKET:\r
+            Status = EslTcpBind4 ( pSocket,\r
+                                   pSockAddr,\r
+                                   SockAddrLength );\r
+            break;\r
+\r
+          case SOCK_DGRAM:\r
+            Status = EslUdpBind4 ( pSocket,\r
+                                   pSockAddr,\r
+                                   SockAddrLength );\r
+            break;\r
+          }\r
+          break;\r
+        }\r
+\r
+        //\r
+        //  Mark this socket as bound if successful\r
+        //\r
+        if ( !EFI_ERROR ( Status )) {\r
+          pSocket->State = SOCKET_STATE_BOUND;\r
+        }\r
+\r
+        //\r
+        //  Release the socket layer synchronization\r
+        //\r
+        RESTORE_TPL ( TplPrevious );\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    if ( NULL != pSocket ) {\r
+      *pErrno = pSocket->errno;\r
+    }\r
+    else\r
+    {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      *pErrno = EBADF;\r
+    }\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Determine if the socket is closed\r
+\r
+  Reverses the operations of the ::SocketAllocate() routine.\r
+\r
+  @param [in] pSocketProtocol Address of the socket protocol structure.\r
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS     Socket successfully closed\r
+  @retval EFI_NOT_READY   Close still in progress\r
+  @retval EFI_ALREADY     Close operation already in progress\r
+  @retval Other           Failed to close the socket\r
+\r
+**/\r
+EFI_STATUS\r
+EslSocketClosePoll (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  int errno;\r
+  DT_LAYER * pLayer;\r
+  DT_SOCKET * pNextSocket;\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  errno = 0;\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Synchronize with the socket layer\r
+  //\r
+  RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+  //\r
+  //  Locate the socket\r
+  //\r
+  pLayer = &mEslLayer;\r
+  pNextSocket = pLayer->pSocketList;\r
+  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+  while ( NULL != pNextSocket ) {\r
+    if ( pNextSocket == pSocket ) {\r
+      //\r
+      //  Determine if the socket is in the closing state\r
+      //\r
+      if ( SOCKET_STATE_CLOSED == pSocket->State ) {\r
+        //\r
+        //  Walk the list of ports\r
+        //\r
+        if ( NULL == pSocket->pPortList ) {\r
+          //\r
+          //  All the ports are closed\r
+          //  Close the WaitAccept event if necessary\r
+          //\r
+          if ( NULL != pSocket->WaitAccept ) {\r
+            Status = gBS->CloseEvent ( pSocket->WaitAccept );\r
+            if ( !EFI_ERROR ( Status )) {\r
+              DEBUG (( DEBUG_SOCKET | DEBUG_CLOSE | DEBUG_POOL,\r
+                        "0x%08x: Closed WaitAccept event\r\n",\r
+                        pSocket->WaitAccept ));\r
+              //\r
+              //  Return the transmit status\r
+              //\r
+              Status = pSocket->TxError;\r
+              if ( EFI_ERROR ( Status )) {\r
+                pSocket->errno = EIO;\r
+              }\r
+            }\r
+            else {\r
+              DEBUG (( DEBUG_ERROR | DEBUG_SOCKET | DEBUG_CLOSE | DEBUG_POOL,\r
+                        "ERROR - Failed to close the WaitAccept event, Status: %r\r\n",\r
+                        Status ));\r
+              ASSERT ( EFI_SUCCESS == Status );\r
+            }\r
+          }\r
+        }\r
+        else {\r
+          //\r
+          //  At least one port is still open\r
+          //\r
+          Status = EFI_NOT_READY;\r
+          errno = EAGAIN;\r
+        }\r
+      }\r
+      else {\r
+        //\r
+        //  SocketCloseStart was not called\r
+        //\r
+        Status = EFI_NOT_STARTED;\r
+        errno = EPERM;\r
+      }\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Set the next socket\r
+    //\r
+    pNextSocket = pNextSocket->pNext;\r
+  }\r
+\r
+  //\r
+  //  Handle the error case where the socket was already closed\r
+  //\r
+  if ( NULL == pSocket ) {\r
+    //\r
+    //  Socket not found\r
+    //\r
+    Status = EFI_NOT_FOUND;\r
+    errno = ENOTSOCK;\r
+  }\r
+\r
+  //\r
+  //  Release the socket layer synchronization\r
+  //\r
+  RESTORE_TPL ( TplPrevious );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    *pErrno = errno;\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Start the close operation on the socket\r
+\r
+  Start closing the socket by closing all of the ports.  Upon\r
+  completion, the ::SocketPoll() routine finishes closing the\r
+  socket.\r
+\r
+  @param [in] pSocketProtocol Address of the socket protocol structure.\r
+  @param [in] bCloseNow       Boolean to control close behavior\r
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS     Socket successfully closed\r
+  @retval EFI_NOT_READY   Close still in progress\r
+  @retval EFI_ALREADY     Close operation already in progress\r
+  @retval Other           Failed to close the socket\r
+\r
+**/\r
+EFI_STATUS\r
+EslSocketCloseStart (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN BOOLEAN bCloseNow,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  int errno;\r
+  DT_PORT * pNextPort;\r
+  DT_PORT * pPort;\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+  errno = 0;\r
+\r
+  //\r
+  //  Synchronize with the socket layer\r
+  //\r
+  RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+  //\r
+  //  Determine if the socket is already closed\r
+  //\r
+  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+  if ( SOCKET_STATE_CLOSED > pSocket->State ) {\r
+    //\r
+    //  Update the socket state\r
+    //\r
+    pSocket->State = SOCKET_STATE_CLOSED;\r
+\r
+    //\r
+    //  Walk the list of ports\r
+    //\r
+    pPort = pSocket->pPortList;\r
+    while ( NULL != pPort ) {\r
+      //\r
+      //  Start closing the ports\r
+      //\r
+      pNextPort = pPort->pLinkSocket;\r
+      Status = pPort->pfnCloseStart ( pPort,\r
+                                      bCloseNow,\r
+                                      DEBUG_CLOSE | DEBUG_LISTEN | DEBUG_CONNECTION );\r
+      if (( EFI_SUCCESS != Status )\r
+        && ( EFI_NOT_READY != Status )) {\r
+        errno = EIO;\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Set the next port\r
+      //\r
+      pPort = pNextPort;\r
+    }\r
+\r
+    //\r
+    //  Attempt to finish closing the socket\r
+    //\r
+    if ( NULL == pPort ) {\r
+      Status = EslSocketClosePoll ( pSocketProtocol, &errno );\r
+    }\r
+  }\r
+  else {\r
+    Status = EFI_ALREADY_STARTED;\r
+    errno = EALREADY;\r
+  }\r
+\r
+  //\r
+  //  Release the socket layer synchronization\r
+  //\r
+  RESTORE_TPL ( TplPrevious );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    *pErrno = errno;\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Connect to a remote system via the network.\r
+\r
+  The ::SocketConnect routine attempts to establish a connection to a\r
+  socket on the local or remote system using the specified address.\r
+  The POSIX\r
+  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html">connect</a>\r
+  documentation is available online.\r
+\r
+  There are three states associated with a connection:\r
+  <ul>\r
+    <li>Not connected</li>\r
+    <li>Connection in progress</li>\r
+    <li>Connected</li>\r
+  </ul>\r
+  In the "Not connected" state, calls to ::connect start the connection\r
+  processing and update the state to "Connection in progress".  During\r
+  the "Connection in progress" state, connect polls for connection completion\r
+  and moves the state to "Connected" after the connection is established.\r
+  Note that these states are only visible when the file descriptor is marked\r
+  with O_NONBLOCK.  Also, the POLL_WRITE bit is set when the connection\r
+  completes and may be used by poll or select as an indicator to call\r
+  connect again.\r
+\r
+  @param [in] pSocketProtocol Address of the socket protocol structure.\r
+\r
+  @param [in] pSockAddr       Network address of the remote system.\r
+    \r
+  @param [in] SockAddrLength  Length in bytes of the network address.\r
+  \r
+  @param [out] pErrno   Address to receive the errno value upon completion.\r
+  \r
+  @retval EFI_SUCCESS   The connection was successfully established.\r
+  @retval EFI_NOT_READY The connection is in progress, call this routine again.\r
+  @retval Others        The connection attempt failed.\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketConnect (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN const struct sockaddr * pSockAddr,\r
+  IN socklen_t SockAddrLength,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+  \r
+  DEBUG (( DEBUG_CONNECT, "Entering SocketConnect\r\n" ));\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pSocket = NULL;\r
+  if ( NULL != pSocketProtocol ) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+    //\r
+    //  Validate the name length\r
+    //\r
+    if (( SockAddrLength < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))\r
+      || ( pSockAddr->sa_len < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))) {\r
+      DEBUG (( DEBUG_CONNECT,\r
+                "ERROR - Invalid bind name length: %d, sa_len: %d\r\n",\r
+                SockAddrLength,\r
+                pSockAddr->sa_len ));\r
+      Status = EFI_INVALID_PARAMETER;\r
+      pSocket->errno = EINVAL;\r
+    }\r
+    else {\r
+      //\r
+      //  Assume success\r
+      //\r
+      pSocket->errno = 0;\r
+\r
+      //\r
+      //  Set the socket address length\r
+      //\r
+      if ( SockAddrLength > pSockAddr->sa_len ) {\r
+        SockAddrLength = pSockAddr->sa_len;\r
+      }\r
+\r
+      //\r
+      //  Synchronize with the socket layer\r
+      //\r
+      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+      //\r
+      //  Validate the socket state\r
+      //\r
+      switch ( pSocket->State ) {\r
+      default:\r
+        //\r
+        //  Wrong socket state\r
+        //\r
+        pSocket->errno = EIO;\r
+        Status = EFI_DEVICE_ERROR;\r
+        break;\r
+\r
+      case SOCKET_STATE_NOT_CONFIGURED:\r
+      case SOCKET_STATE_BOUND:\r
+        //\r
+        //  Validate the local address\r
+        //\r
+        switch ( pSockAddr->sa_family ) {\r
+        default:\r
+          DEBUG (( DEBUG_CONNECT,\r
+                    "ERROR - Invalid bind address family: %d\r\n",\r
+                    pSockAddr->sa_family ));\r
+          Status = EFI_INVALID_PARAMETER;\r
+          pSocket->errno = EADDRNOTAVAIL;\r
+          break;\r
+\r
+        case AF_INET:\r
+          //\r
+          //  Determine the connection point within the network stack\r
+          //\r
+          switch ( pSocket->Type ) {\r
+          default:\r
+            DEBUG (( DEBUG_CONNECT,\r
+                      "ERROR - Invalid socket type: %d\r\n",\r
+                      pSocket->Type));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            pSocket->errno = EADDRNOTAVAIL;\r
+            break;\r
+\r
+          case SOCK_STREAM:\r
+          case SOCK_SEQPACKET:\r
+            //\r
+            //  Start the connection processing\r
+            //\r
+            Status = EslTcpConnectStart4 ( pSocket,\r
+                                           pSockAddr,\r
+                                           SockAddrLength );\r
+\r
+            //\r
+            //  Set the next state if connecting\r
+            //\r
+            if ( EFI_NOT_READY == Status ) {\r
+              pSocket->State = SOCKET_STATE_CONNECTING;\r
+            }\r
+            break;\r
+\r
+          case SOCK_DGRAM:\r
+            Status = EslUdpConnect4 ( pSocket,\r
+                                      pSockAddr,\r
+                                      SockAddrLength );\r
+            break;\r
+          }\r
+          break;\r
+        }\r
+        break;\r
+\r
+      case SOCKET_STATE_CONNECTING:\r
+        //\r
+        //  Validate the local address\r
+        //\r
+        switch ( pSockAddr->sa_family ) {\r
+        default:\r
+          DEBUG (( DEBUG_CONNECT,\r
+                    "ERROR - Invalid bind address family: %d\r\n",\r
+                    pSockAddr->sa_family ));\r
+          Status = EFI_INVALID_PARAMETER;\r
+          pSocket->errno = EADDRNOTAVAIL;\r
+          break;\r
+\r
+        case AF_INET:\r
+          //\r
+          //  Determine the connection point within the network stack\r
+          //\r
+          switch ( pSocket->Type ) {\r
+          default:\r
+            DEBUG (( DEBUG_CONNECT,\r
+                      "ERROR - Invalid socket type: %d\r\n",\r
+                      pSocket->Type));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            pSocket->errno = EADDRNOTAVAIL;\r
+            break;\r
+\r
+          case SOCK_STREAM:\r
+          case SOCK_SEQPACKET:\r
+            //\r
+            //  Determine if the connection processing is completed\r
+            //\r
+            Status = EslTcpConnectPoll4 ( pSocket );\r
+\r
+            //\r
+            //  Set the next state if connected\r
+            //\r
+            if ( EFI_NOT_READY != Status ) {\r
+              if ( !EFI_ERROR ( Status )) {\r
+                pSocket->State = SOCKET_STATE_CONNECTED;\r
+              }\r
+              else {\r
+                pSocket->State = SOCKET_STATE_BOUND;\r
+              }\r
+            }\r
+            break;\r
+\r
+          case SOCK_DGRAM:\r
+            //\r
+            //  Already connected\r
+            //\r
+            pSocket->errno = EISCONN;\r
+            Status = EFI_ALREADY_STARTED;\r
+            break;\r
+          }\r
+          break;\r
+        }\r
+        break;\r
+\r
+      case SOCKET_STATE_CONNECTED:\r
+        //\r
+        //  Already connected\r
+        //\r
+        pSocket->errno = EISCONN;\r
+        Status = EFI_ALREADY_STARTED;\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Release the socket layer synchronization\r
+      //\r
+      RESTORE_TPL ( TplPrevious );\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    if ( NULL != pSocket ) {\r
+      *pErrno = pSocket->errno;\r
+    }\r
+    else\r
+    {\r
+      //\r
+      //  Bad socket protocol\r
+      //\r
+      DEBUG (( DEBUG_ERROR | DEBUG_CONNECT,\r
+                "ERROR - pSocketProtocol invalid!\r\n" ));\r
+      Status = EFI_INVALID_PARAMETER;\r
+      *pErrno = EBADF;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DEBUG (( DEBUG_CONNECT, "Exiting SocketConnect, Status: %r\r\n", Status ));\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Creates a child handle and installs a protocol.\r
+  \r
+  The CreateChild() function installs a protocol on ChildHandle. \r
+  If pChildHandle is a pointer to NULL, then a new handle is created and returned in pChildHandle. \r
+  If pChildHandle is not a pointer to NULL, then the protocol installs on the existing pChildHandle.\r
+\r
+  @param [in] pThis        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
+  @param [in] pChildHandle Pointer to the handle of the child to create. If it is NULL,\r
+                           then a new handle is created. If it is a pointer to an existing UEFI handle, \r
+                           then the protocol is added to the existing UEFI handle.\r
+\r
+  @retval EFI_SUCCESS           The protocol was added to ChildHandle.\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources availabe to create\r
+                                the child\r
+  @retval other                 The child handle was not created\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EslSocketCreateChild (\r
+  IN     EFI_SERVICE_BINDING_PROTOCOL * pThis,\r
+  IN OUT EFI_HANDLE * pChildHandle\r
+  )\r
+{\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Create a socket structure\r
+  //\r
+  Status = EslSocketAllocate ( pChildHandle,\r
+                               DEBUG_SOCKET,\r
+                               &pSocket );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Destroys a child handle with a protocol installed on it.\r
+  \r
+  The DestroyChild() function does the opposite of CreateChild(). It removes a protocol \r
+  that was installed by CreateChild() from ChildHandle. If the removed protocol is the \r
+  last protocol on ChildHandle, then ChildHandle is destroyed.\r
+\r
+  @param [in] pThis       Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
+  @param [in] ChildHandle Handle of the child to destroy\r
+\r
+  @retval EFI_SUCCESS           The protocol was removed from ChildHandle.\r
+  @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.\r
+  @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.\r
+  @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle\r
+                                because its services are being used.\r
+  @retval other                 The child handle was not destroyed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EslSocketDestroyChild (\r
+  IN EFI_SERVICE_BINDING_PROTOCOL * pThis,\r
+  IN EFI_HANDLE ChildHandle\r
+  )\r
+{\r
+  DT_LAYER * pLayer;\r
+  DT_SOCKET * pSocket;\r
+  DT_SOCKET * pSocketPrevious;\r
+  EFI_SOCKET_PROTOCOL * pSocketProtocol;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Locate the socket control structure\r
+  //\r
+  pLayer = &mEslLayer;\r
+  Status = gBS->OpenProtocol (\r
+                  ChildHandle,\r
+                  &gEfiSocketProtocolGuid,\r
+                  (VOID **)&pSocketProtocol,\r
+                  pLayer->ImageHandle,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if ( !EFI_ERROR ( Status )) {\r
+    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
+      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
+        }\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 - Failed to open socket protocol on 0x%08x, Status; %r\r\n",\r
+              ChildHandle,\r
+              Status ));\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
+  @param [in] pSocketProtocol Address of the socket protocol 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
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS - Local address successfully returned\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketGetLocalAddress (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  OUT struct sockaddr * pAddress,\r
+  IN OUT socklen_t * pAddressLength,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+  \r
+  DBG_ENTER ( );\r
+  \r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+  \r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pSocket = NULL;\r
+  if ( NULL != pSocketProtocol ) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+    //\r
+    //  Verify the address buffer and length address\r
+    //\r
+    if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r
+      //\r
+      //  Verify the socket state\r
+      //\r
+      if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
+        //\r
+        //  Synchronize with the socket layer\r
+        //\r
+        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+        //\r
+        //  Validate the local address\r
+        //\r
+        switch ( pSocket->Domain ) {\r
+        default:\r
+          DEBUG (( DEBUG_RX,\r
+                    "ERROR - Invalid socket address family: %d\r\n",\r
+                    pSocket->Domain ));\r
+          Status = EFI_INVALID_PARAMETER;\r
+          pSocket->errno = EADDRNOTAVAIL;\r
+          break;\r
+\r
+        case AF_INET:\r
+          //\r
+          //  Determine the connection point within the network stack\r
+          //\r
+          switch ( pSocket->Type ) {\r
+          default:\r
+            DEBUG (( DEBUG_RX,\r
+                      "ERROR - Invalid socket type: %d\r\n",\r
+                      pSocket->Type));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            break;\r
+\r
+          case SOCK_STREAM:\r
+          case SOCK_SEQPACKET:\r
+            //\r
+            //  Get the local address\r
+            //\r
+            Status = EslTcpGetLocalAddress4 ( pSocket,\r
+                                              pAddress,\r
+                                              pAddressLength );\r
+            break;\r
+\r
+          case SOCK_DGRAM:\r
+            //\r
+            //  Get the local address\r
+            //\r
+            Status = EslUdpGetLocalAddress4 ( pSocket,\r
+                                              pAddress,\r
+                                              pAddressLength );\r
+            break;\r
+          }\r
+          break;\r
+        }\r
+\r
+        //\r
+        //  Release the socket layer synchronization\r
+        //\r
+        RESTORE_TPL ( TplPrevious );\r
+      }\r
+      else {\r
+        pSocket->errno = ENOTCONN;\r
+        Status = EFI_NOT_STARTED;\r
+      }\r
+    }\r
+    else {\r
+      pSocket->errno = EINVAL;\r
+      Status = EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  \r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    if ( NULL != pSocket ) {\r
+      *pErrno = pSocket->errno;\r
+    }\r
+    else\r
+    {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      *pErrno = EBADF;\r
+    }\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Get the peer address.\r
+\r
+  @param [in] pSocketProtocol Address of the socket protocol 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
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS - Remote address successfully returned\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketGetPeerAddress (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  OUT struct sockaddr * pAddress,\r
+  IN OUT socklen_t * pAddressLength,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+  \r
+  DBG_ENTER ( );\r
+  \r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+  \r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pSocket = NULL;\r
+  if ( NULL != pSocketProtocol ) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+    //\r
+    //  Verify the address buffer and length address\r
+    //\r
+    if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r
+      //\r
+      //  Verify the socket state\r
+      //\r
+      if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
+        //\r
+        //  Synchronize with the socket layer\r
+        //\r
+        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+        //\r
+        //  Validate the local address\r
+        //\r
+        switch ( pSocket->Domain ) {\r
+        default:\r
+          DEBUG (( DEBUG_RX,\r
+                    "ERROR - Invalid socket address family: %d\r\n",\r
+                    pSocket->Domain ));\r
+          Status = EFI_INVALID_PARAMETER;\r
+          pSocket->errno = EADDRNOTAVAIL;\r
+          break;\r
+\r
+        case AF_INET:\r
+          //\r
+          //  Determine the connection point within the network stack\r
+          //\r
+          switch ( pSocket->Type ) {\r
+          default:\r
+            DEBUG (( DEBUG_RX,\r
+                      "ERROR - Invalid socket type: %d\r\n",\r
+                      pSocket->Type));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            break;\r
+\r
+          case SOCK_STREAM:\r
+          case SOCK_SEQPACKET:\r
+            //\r
+            //  Verify the port state\r
+            //\r
+            Status = EslTcpGetRemoteAddress4 ( pSocket,\r
+                                               pAddress,\r
+                                               pAddressLength );\r
+            break;\r
+\r
+          case SOCK_DGRAM:\r
+            //\r
+            //  Verify the port state\r
+            //\r
+            Status = EslUdpGetRemoteAddress4 ( pSocket,\r
+                                               pAddress,\r
+                                               pAddressLength );\r
+            break;\r
+          }\r
+          break;\r
+        }\r
+\r
+        //\r
+        //  Release the socket layer synchronization\r
+        //\r
+        RESTORE_TPL ( TplPrevious );\r
+      }\r
+      else {\r
+        pSocket->errno = ENOTCONN;\r
+        Status = EFI_NOT_STARTED;\r
+      }\r
+    }\r
+    else {\r
+      pSocket->errno = EINVAL;\r
+      Status = EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  \r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    if ( NULL != pSocket ) {\r
+      *pErrno = pSocket->errno;\r
+    }\r
+    else\r
+    {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      *pErrno = EBADF;\r
+    }\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Establish the known port to listen for network connections.\r
+\r
+  The ::SocketListen routine places the port into a state that enables connection\r
+  attempts.  Connections are placed into FIFO order in a queue to be serviced\r
+  by the application.  The application calls the ::SocketAccept routine to remove\r
+  the next connection from the queue and get the associated socket.  The\r
+  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html">POSIX</a>\r
+  documentation for the listen routine is available online for reference.\r
+\r
+  @param [in] pSocketProtocol Address of the socket protocol structure.\r
+\r
+  @param [in] Backlog         Backlog specifies the maximum FIFO depth for\r
+                              the connections waiting for the application\r
+                              to call accept.  Connection attempts received\r
+                              while the queue is full are refused.\r
+\r
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS - Socket successfully created\r
+  @retval Other - Failed to enable the socket for listen\r
+\r
+**/\r
+EFI_STATUS\r
+EslSocketListen (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN INT32 Backlog,\r
+  OUT int * pErrno\r
+  )\r
+{\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_STATUS TempStatus;\r
+  EFI_TPL TplPrevious;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pSocket = NULL;\r
+  if ( NULL != pSocketProtocol ) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+    //\r
+    //  Assume success\r
+    //\r
+    pSocket->Status = EFI_SUCCESS;\r
+    pSocket->errno = 0;\r
+\r
+    //\r
+    //  Verify that the bind operation was successful\r
+    //\r
+    if ( SOCKET_STATE_BOUND == pSocket->State ) {\r
+      //\r
+      //  Synchronize with the socket layer\r
+      //\r
+      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+      //\r
+      //  Create the event for SocketAccept completion\r
+      //\r
+      Status = gBS->CreateEvent ( 0,\r
+                                  TplPrevious,\r
+                                  NULL,\r
+                                  NULL,\r
+                                  &pSocket->WaitAccept );\r
+      if ( !EFI_ERROR ( Status )) {\r
+        DEBUG (( DEBUG_POOL,\r
+                  "0x%08x: Created WaitAccept event\r\n",\r
+                  pSocket->WaitAccept ));\r
+        //\r
+        //  Set the maximum FIFO depth\r
+        //\r
+        if ( 0 >= Backlog ) {\r
+          Backlog = MAX_PENDING_CONNECTIONS;\r
+        }\r
+        else {\r
+          if ( SOMAXCONN < Backlog ) {\r
+            Backlog = SOMAXCONN;\r
+          }\r
+          else {\r
+            pSocket->MaxFifoDepth = Backlog;\r
+          }\r
+        }\r
+\r
+        //\r
+        //  Validate the local address\r
+        //\r
+        switch ( pSocket->Domain ) {\r
+        default:\r
+          DEBUG (( DEBUG_BIND,\r
+                    "ERROR - Invalid socket address family: %d\r\n",\r
+                    pSocket->Domain ));\r
+          Status = EFI_INVALID_PARAMETER;\r
+          pSocket->errno = EADDRNOTAVAIL;\r
+          break;\r
+\r
+        case AF_INET:\r
+          //\r
+          //  Determine the connection point within the network stack\r
+          //\r
+          switch ( pSocket->Type ) {\r
+          default:\r
+            DEBUG (( DEBUG_BIND,\r
+                      "ERROR - Invalid socket type: %d\r\n",\r
+                      pSocket->Type));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            pSocket->errno = EADDRNOTAVAIL;\r
+            break;\r
+\r
+          case SOCK_STREAM:\r
+          case SOCK_SEQPACKET:\r
+            Status = EslTcpListen4 ( pSocket );\r
+            break;\r
+\r
+/*\r
+          case SOCK_DGRAM:\r
+            Status = UdpListen4 ( pSocket );\r
+            break;\r
+*/\r
+          }\r
+          break;\r
+        }\r
+\r
+        //\r
+        //  Place the socket in the listen state if successful\r
+        //\r
+        if ( !EFI_ERROR ( Status )) {\r
+          pSocket->State = SOCKET_STATE_LISTENING;\r
+        }\r
+        else {\r
+          //\r
+          //  Not waiting for SocketAccept to complete\r
+          //\r
+          TempStatus = gBS->CloseEvent ( pSocket->WaitAccept );\r
+          if ( !EFI_ERROR ( TempStatus )) {\r
+            DEBUG (( DEBUG_POOL,\r
+                      "0x%08x: Closed WaitAccept event\r\n",\r
+                      pSocket->WaitAccept ));\r
+            pSocket->WaitAccept = NULL;\r
+          }\r
+          else {\r
+            DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
+                      "ERROR - Failed to close WaitAccept event, Status: %r\r\n",\r
+                      TempStatus ));\r
+            ASSERT ( EFI_SUCCESS == TempStatus );\r
+          }\r
+        }\r
+      }\r
+      else {\r
+        DEBUG (( DEBUG_ERROR | DEBUG_LISTEN,\r
+                  "ERROR - Failed to create the WaitAccept event, Status: %r\r\n",\r
+                  Status ));\r
+        pSocket->errno = ENOMEM;\r
+      }\r
+\r
+      //\r
+      //  Release the socket layer synchronization\r
+      //\r
+      RESTORE_TPL ( TplPrevious );\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR | DEBUG_LISTEN,\r
+                "ERROR - Bind operation must be performed first!\r\n" ));\r
+      pSocket->errno = EDESTADDRREQ;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    if ( NULL != pSocket ) {\r
+      *pErrno = pSocket->errno;\r
+    }\r
+    else\r
+    {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      *pErrno = EBADF;\r
+    }\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Get the socket options\r
+\r
+  Retrieve the socket options one at a time by name.  The\r
+  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html">POSIX</a>\r
+  documentation is available online.\r
+\r
+  @param [in] pSocketProtocol   Address of the socket protocol structure.\r
+  @param [in] level             Option protocol level\r
+  @param [in] OptionName        Name of the option\r
+  @param [out] pOptionValue     Buffer to receive the option value\r
+  @param [in,out] pOptionLength Length of the buffer in bytes,\r
+                                upon return length of the option value in bytes\r
+  @param [out] pErrno           Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS - Socket data successfully received\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketOptionGet (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN int level,\r
+  IN int OptionName,\r
+  OUT void * __restrict pOptionValue,\r
+  IN OUT socklen_t * __restrict pOptionLength,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  int errno;\r
+  socklen_t LengthInBytes;\r
+  socklen_t MaxBytes;\r
+  UINT8 * pOptionData;\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume failure\r
+  //\r
+  errno = EINVAL;\r
+  Status = EFI_INVALID_PARAMETER;\r
+\r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pSocket = NULL;\r
+  if (( NULL != pSocketProtocol )\r
+    && ( NULL != pOptionValue )\r
+    && ( NULL != pOptionLength )) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+    LengthInBytes = 0;\r
+    MaxBytes = *pOptionLength;\r
+    pOptionData = NULL;\r
+    switch ( level ) {\r
+    default:\r
+      //\r
+      //  Protocol level not supported\r
+      //\r
+      errno = ENOTSUP;\r
+      Status = EFI_UNSUPPORTED;\r
+      break;\r
+\r
+    case SOL_SOCKET:\r
+      switch ( OptionName ) {\r
+      default:\r
+        //\r
+        //  Option not supported\r
+        //\r
+        errno = ENOTSUP;\r
+        Status = EFI_UNSUPPORTED;\r
+        break;\r
+\r
+      case SO_RCVTIMEO:\r
+        //\r
+        //  Return the receive timeout\r
+        //\r
+        pOptionData = (UINT8 *)&pSocket->RxTimeout;\r
+        LengthInBytes = sizeof ( pSocket->RxTimeout );\r
+        break;\r
+        \r
+      case SO_RCVBUF:\r
+        //\r
+        //  Return the maximum transmit buffer size\r
+        //\r
+        pOptionData = (UINT8 *)&pSocket->MaxRxBuf;\r
+        LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r
+        break;\r
+\r
+      case SO_SNDBUF:\r
+        //\r
+        //  Return the maximum transmit buffer size\r
+        //\r
+        pOptionData = (UINT8 *)&pSocket->MaxTxBuf;\r
+        LengthInBytes = sizeof ( pSocket->MaxTxBuf );\r
+        break;\r
+\r
+      case SO_TYPE:\r
+        //\r
+        //  Return the socket type\r
+        //\r
+        pOptionData = (UINT8 *)&pSocket->Type;\r
+        LengthInBytes = sizeof ( pSocket->Type );\r
+        break;\r
+      }\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Return the option length\r
+    //\r
+    *pOptionLength = LengthInBytes;\r
+\r
+    //\r
+    //  Return the option value\r
+    //\r
+    if ( NULL != pOptionData ) {\r
+      //\r
+      //  Silently truncate the value length\r
+      //\r
+      if ( LengthInBytes > MaxBytes ) {\r
+        LengthInBytes = MaxBytes;\r
+      }\r
+      CopyMem ( pOptionValue, pOptionData, LengthInBytes );\r
+      errno = 0;\r
+      Status = EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    *pErrno = errno;\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Set the socket options\r
+\r
+  Adjust the socket options one at a time by name.  The\r
+  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html">POSIX</a>\r
+  documentation is available online.\r
+\r
+  @param [in] pSocketProtocol Address of the socket protocol structure.\r
+  @param [in] level           Option protocol level\r
+  @param [in] OptionName      Name of the option\r
+  @param [in] pOptionValue    Buffer containing the option value\r
+  @param [in] OptionLength    Length of the buffer in bytes\r
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS - Socket data successfully received\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketOptionSet (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN int level,\r
+  IN int OptionName,\r
+  IN CONST void * pOptionValue,\r
+  IN socklen_t OptionLength,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  int errno;\r
+  socklen_t LengthInBytes;\r
+  UINT8 * pOptionData;\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  \r
+  DBG_ENTER ( );\r
+  \r
+  //\r
+  //  Assume failure\r
+  //\r
+  errno = EINVAL;\r
+  Status = EFI_INVALID_PARAMETER;\r
+  \r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pSocket = NULL;\r
+  if (( NULL != pSocketProtocol )\r
+    && ( NULL != pOptionValue )) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+    LengthInBytes = 0;\r
+    pOptionData = NULL;\r
+    switch ( level ) {\r
+    default:\r
+      //\r
+      //  Protocol level not supported\r
+      //\r
+      errno = ENOTSUP;\r
+      Status = EFI_UNSUPPORTED;\r
+      break;\r
+  \r
+    case SOL_SOCKET:\r
+      switch ( OptionName ) {\r
+      default:\r
+        //\r
+        //  Option not supported\r
+        //\r
+        errno = ENOTSUP;\r
+        Status = EFI_UNSUPPORTED;\r
+        break;\r
+  \r
+      case SO_RCVTIMEO:\r
+        //\r
+        //  Return the receive timeout\r
+        //\r
+        pOptionData = (UINT8 *)&pSocket->RxTimeout;\r
+        LengthInBytes = sizeof ( pSocket->RxTimeout );\r
+        break;\r
+\r
+      case SO_RCVBUF:\r
+        //\r
+        //  Return the maximum transmit buffer size\r
+        //\r
+        pOptionData = (UINT8 *)&pSocket->MaxRxBuf;\r
+        LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r
+        break;\r
+\r
+      case SO_SNDBUF:\r
+        //\r
+        //  Send buffer size\r
+        //\r
+        //\r
+        //  Return the maximum transmit buffer size\r
+        //\r
+        pOptionData = (UINT8 *)&pSocket->MaxTxBuf;\r
+        LengthInBytes = sizeof ( pSocket->MaxTxBuf );\r
+        break;\r
+      }\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Validate the option length\r
+    //\r
+    if ( LengthInBytes <= OptionLength ) {\r
+      //\r
+      //  Set the option value\r
+      //\r
+      if ( NULL != pOptionData ) {\r
+        CopyMem ( pOptionData, pOptionValue, LengthInBytes );\r
+        errno = 0;\r
+        Status = EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+  \r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    *pErrno = errno;\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Allocate a packet for a receive or transmit operation\r
+\r
+  @param [in] ppPacket      Address to receive the DT_PACKET structure\r
+  @param [in] LengthInBytes Length of the packet structure\r
+  @param [in] DebugFlags    Flags for debug messages\r
+\r
+  @retval EFI_SUCCESS - The packet was allocated successfully\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketPacketAllocate (\r
+  IN DT_PACKET ** ppPacket,\r
+  IN size_t LengthInBytes,\r
+  IN UINTN DebugFlags\r
+  )\r
+{\r
+  DT_PACKET * pPacket;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Allocate a packet structure\r
+  //\r
+  LengthInBytes += sizeof ( *pPacket )\r
+                - sizeof ( pPacket->Op );\r
+  Status = gBS->AllocatePool ( EfiRuntimeServicesData,\r
+                               LengthInBytes,\r
+                               (VOID **)&pPacket );\r
+  if ( !EFI_ERROR ( Status )) {\r
+    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
+              "0x%08x: Allocate pPacket, %d bytes\r\n",\r
+              pPacket,\r
+              LengthInBytes ));\r
+    pPacket->PacketSize = LengthInBytes;\r
+  }\r
+  else {\r
+    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INFO,\r
+              "ERROR - Packet allocation failed for %d bytes, Status: %r\r\n",\r
+              LengthInBytes,\r
+              Status ));\r
+    pPacket = NULL;\r
+  }\r
+\r
+  //\r
+  //  Return the packet\r
+  //\r
+  *ppPacket = pPacket;\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Free a packet used for receive or transmit operation\r
+\r
+  @param [in] pPacket     Address of the DT_PACKET structure\r
+  @param [in] DebugFlags  Flags for debug messages\r
+\r
+  @retval EFI_SUCCESS - The packet was allocated successfully\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketPacketFree (\r
+  IN DT_PACKET * pPacket,\r
+  IN UINTN DebugFlags\r
+  )\r
+{\r
+  UINTN LengthInBytes;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Allocate a packet structure\r
+  //\r
+  LengthInBytes = pPacket->PacketSize;\r
+  Status = gBS->FreePool ( pPacket );\r
+  if ( !EFI_ERROR ( Status )) {\r
+    DEBUG (( DebugFlags | DEBUG_POOL,\r
+              "0x%08x: Free pPacket, %d bytes\r\n",\r
+              pPacket,\r
+              LengthInBytes ));\r
+  }\r
+  else {\r
+    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INFO,\r
+              "ERROR - Failed to free packet 0x%08x, Status: %r\r\n",\r
+              pPacket,\r
+              Status ));\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Poll a socket for pending activity.\r
+\r
+  The SocketPoll routine checks a socket for pending activity associated\r
+  with the event mask.  Activity is returned in the detected event buffer.\r
+\r
+  @param [in] pSocketProtocol Address of the socket protocol structure.\r
+\r
+  @param [in] Events    Events of interest for this socket\r
+\r
+  @param [in] pEvents   Address to receive the detected events\r
+\r
+  @param [out] pErrno   Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS - Socket successfully polled\r
+  @retval EFI_INVALID_PARAMETER - When pEvents is NULL\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketPoll (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN short Events,\r
+  IN short * pEvents,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  short DetectedEvents;\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+  short ValidEvents;\r
+\r
+  DEBUG (( DEBUG_POLL, "Entering SocketPoll\r\n" ));\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+  DetectedEvents = 0;\r
+  pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+  pSocket->errno = 0;\r
+\r
+  //\r
+  //  Verify the socket state\r
+  //\r
+  if ( !pSocket->bConfigured ) {\r
+    //\r
+    //  Synchronize with the socket layer\r
+    //\r
+    RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+    //\r
+    //  Validate the local address\r
+    //\r
+    switch ( pSocket->Domain ) {\r
+    default:\r
+      DEBUG (( DEBUG_RX,\r
+                "ERROR - Invalid socket address family: %d\r\n",\r
+                pSocket->Domain ));\r
+      Status = EFI_INVALID_PARAMETER;\r
+      pSocket->errno = EADDRNOTAVAIL;\r
+      break;\r
+\r
+    case AF_INET:\r
+      //\r
+      //  Determine the connection point within the network stack\r
+      //\r
+      switch ( pSocket->Type ) {\r
+      default:\r
+        DEBUG (( DEBUG_RX,\r
+                  "ERROR - Invalid socket type: %d\r\n",\r
+                  pSocket->Type));\r
+        Status = EFI_INVALID_PARAMETER;\r
+        pSocket->errno = EADDRNOTAVAIL;\r
+        break;\r
+\r
+      case SOCK_STREAM:\r
+      case SOCK_SEQPACKET:\r
+        //\r
+        //  Verify the port state\r
+        //\r
+        Status = EslTcpSocketIsConfigured4 ( pSocket );\r
+        break;\r
+\r
+      case SOCK_DGRAM:\r
+        //\r
+        //  Verify the port state\r
+        //\r
+        Status = EslUdpSocketIsConfigured4 ( pSocket );\r
+        break;\r
+      }\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Release the socket layer synchronization\r
+    //\r
+    RESTORE_TPL ( TplPrevious );\r
+  }\r
+  if ( !EFI_ERROR ( Status )) {\r
+    //\r
+    //  Check for invalid events\r
+    //\r
+    ValidEvents = POLLIN\r
+                | POLLPRI\r
+                | POLLOUT | POLLWRNORM\r
+                | POLLERR\r
+                | POLLHUP\r
+                | POLLNVAL\r
+                | POLLRDNORM\r
+                | POLLRDBAND\r
+                | POLLWRBAND ;\r
+    if ( 0 != ( Events & ( ~ValidEvents ))) {\r
+      DetectedEvents |= POLLNVAL;\r
+      DEBUG (( DEBUG_INFO | DEBUG_POLL,\r
+                "ERROR - Invalid event mask, Valid Events: 0x%04x, Invalid Events: 0x%04x\r\n",\r
+                Events & ValidEvents,\r
+                Events & ( ~ValidEvents )));\r
+    }\r
+    else {\r
+      //\r
+      //  Check for pending connections\r
+      //\r
+      if ( 0 != pSocket->FifoDepth ) {\r
+        //\r
+        //  A connection is waiting for an accept call\r
+        //  See posix connect documentation at\r
+        //  http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.htm\r
+        //\r
+        DetectedEvents |= POLLIN | POLLRDNORM;\r
+      }\r
+      if ( pSocket->bConnected ) {\r
+        //\r
+        //  A connection is present\r
+        //  See posix connect documentation at\r
+        //  http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.htm\r
+        //\r
+        DetectedEvents |= POLLOUT | POLLWRNORM;\r
+      }\r
+\r
+      //\r
+      //  The following bits are set based upon the POSIX poll documentation at\r
+      //  http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html\r
+      //\r
+\r
+      //\r
+      //  Check for urgent receive data\r
+      //\r
+      if ( 0 < pSocket->RxOobBytes ) {\r
+        DetectedEvents |= POLLRDBAND | POLLPRI | POLLIN;\r
+      }\r
+\r
+      //\r
+      //  Check for normal receive data\r
+      //\r
+      if (( 0 < pSocket->RxBytes )\r
+        || ( EFI_SUCCESS != pSocket->RxError )) {\r
+        DetectedEvents |= POLLRDNORM | POLLIN;\r
+      }\r
+\r
+      //\r
+      //  Handle the receive errors\r
+      //\r
+      if (( EFI_SUCCESS != pSocket->RxError )\r
+        && ( 0 == ( DetectedEvents & POLLIN ))) {\r
+        DetectedEvents |= POLLERR | POLLIN | POLLRDNORM | POLLRDBAND;\r
+      }\r
+\r
+      //\r
+      //  Check for urgent transmit data buffer space\r
+      //\r
+      if (( MAX_TX_DATA > pSocket->TxOobBytes )\r
+        || ( EFI_SUCCESS != pSocket->TxError )) {\r
+        DetectedEvents |= POLLWRBAND;\r
+      }\r
+\r
+      //\r
+      //  Check for normal transmit data buffer space\r
+      //\r
+      if (( MAX_TX_DATA > pSocket->TxBytes )\r
+        || ( EFI_SUCCESS != pSocket->TxError )) {\r
+        DetectedEvents |= POLLWRNORM;\r
+      }\r
+\r
+      //\r
+      //  Handle the transmit error\r
+      //\r
+      if ( EFI_ERROR ( pSocket->TxError )) {\r
+        DetectedEvents |= POLLERR;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the detected events\r
+  //\r
+  *pEvents = DetectedEvents & ( Events\r
+                              | POLLERR\r
+                              | POLLHUP\r
+                              | POLLNVAL );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DEBUG (( DEBUG_POLL, "Exiting SocketPoll, Status: %r\r\n", Status ));\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Receive data from a network connection.\r
+\r
+\r
+  @param [in] pSocketProtocol Address of the socket protocol structure.\r
+  \r
+  @param [in] Flags           Message control flags\r
+  \r
+  @param [in] BufferLength    Length of the the buffer\r
+  \r
+  @param [in] pBuffer         Address of a buffer to receive the data.\r
+  \r
+  @param [in] pDataLength     Number of received data bytes in the buffer.\r
+\r
+  @param [out] pAddress       Network address to receive the remote system address\r
+\r
+  @param [in,out] pAddressLength  Length of the remote network address structure\r
+\r
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS - Socket data successfully received\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketReceive (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN INT32 Flags,\r
+  IN size_t BufferLength,\r
+  IN UINT8 * pBuffer,\r
+  OUT size_t * pDataLength,\r
+  OUT struct sockaddr * pAddress,\r
+  IN OUT socklen_t * pAddressLength,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pSocket = NULL;\r
+  if ( NULL != pSocketProtocol ) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+    //\r
+    //  Verify the socket state\r
+    //\r
+    if ( !pSocket->bConfigured ) {\r
+      //\r
+      //  Synchronize with the socket layer\r
+      //\r
+      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+      //\r
+      //  Validate the local address\r
+      //\r
+      switch ( pSocket->Domain ) {\r
+      default:\r
+        DEBUG (( DEBUG_RX,\r
+                  "ERROR - Invalid socket address family: %d\r\n",\r
+                  pSocket->Domain ));\r
+        Status = EFI_INVALID_PARAMETER;\r
+        pSocket->errno = EADDRNOTAVAIL;\r
+        break;\r
+\r
+      case AF_INET:\r
+        //\r
+        //  Determine the connection point within the network stack\r
+        //\r
+        switch ( pSocket->Type ) {\r
+        default:\r
+          DEBUG (( DEBUG_RX,\r
+                    "ERROR - Invalid socket type: %d\r\n",\r
+                    pSocket->Type));\r
+          Status = EFI_INVALID_PARAMETER;\r
+          break;\r
+\r
+        case SOCK_STREAM:\r
+        case SOCK_SEQPACKET:\r
+          //\r
+          //  Verify the port state\r
+          //\r
+          Status = EslTcpSocketIsConfigured4 ( pSocket );\r
+          break;\r
+\r
+        case SOCK_DGRAM:\r
+          //\r
+          //  Verify the port state\r
+          //\r
+          Status = EslUdpSocketIsConfigured4 ( pSocket );\r
+          break;\r
+        }\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Release the socket layer synchronization\r
+      //\r
+      RESTORE_TPL ( TplPrevious );\r
+\r
+      //\r
+      //  Set errno if a failure occurs\r
+      //\r
+      if ( EFI_ERROR ( Status )) {\r
+        pSocket->errno = EADDRNOTAVAIL;\r
+      }\r
+    }\r
+    if ( !EFI_ERROR ( Status )) {\r
+      //\r
+      //  Validate the buffer length\r
+      //\r
+      if (( NULL == pDataLength )\r
+        && ( 0 > pDataLength )\r
+        && ( NULL == pBuffer )) {\r
+        if ( NULL == pDataLength ) {\r
+          DEBUG (( DEBUG_RX,\r
+                    "ERROR - pDataLength is NULL!\r\n" ));\r
+        }\r
+        else if ( NULL == pBuffer ) {\r
+          DEBUG (( DEBUG_RX,\r
+                    "ERROR - pBuffer is NULL!\r\n" ));\r
+        }\r
+        else {\r
+          DEBUG (( DEBUG_RX,\r
+                    "ERROR - Data length < 0!\r\n" ));\r
+        }\r
+        Status = EFI_INVALID_PARAMETER;\r
+        pSocket->errno = EFAULT;\r
+      }\r
+      else{\r
+        //\r
+        //  Synchronize with the socket layer\r
+        //\r
+        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+        //\r
+        //  Validate the local address\r
+        //\r
+        switch ( pSocket->Domain ) {\r
+        default:\r
+          DEBUG (( DEBUG_RX,\r
+                    "ERROR - Invalid socket address family: %d\r\n",\r
+                    pSocket->Domain ));\r
+          Status = EFI_INVALID_PARAMETER;\r
+          pSocket->errno = EADDRNOTAVAIL;\r
+          break;\r
+\r
+        case AF_INET:\r
+          //\r
+          //  Determine the connection point within the network stack\r
+          //\r
+          switch ( pSocket->Type ) {\r
+          default:\r
+            DEBUG (( DEBUG_RX,\r
+                      "ERROR - Invalid socket type: %d\r\n",\r
+                      pSocket->Type));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            pSocket->errno = EADDRNOTAVAIL;\r
+            break;\r
+\r
+          case SOCK_STREAM:\r
+          case SOCK_SEQPACKET:\r
+            Status = EslTcpReceive4 ( pSocket,\r
+                                      Flags,\r
+                                      BufferLength,\r
+                                      pBuffer,\r
+                                      pDataLength,\r
+                                      pAddress,\r
+                                      pAddressLength );\r
+            break;\r
+\r
+          case SOCK_DGRAM:\r
+            Status = EslUdpReceive4 ( pSocket,\r
+                                      Flags,\r
+                                      BufferLength,\r
+                                      pBuffer,\r
+                                      pDataLength,\r
+                                      pAddress,\r
+                                      pAddressLength);\r
+            break;\r
+          }\r
+          break;\r
+        }\r
+\r
+        //\r
+        //  Release the socket layer synchronization\r
+        //\r
+        RESTORE_TPL ( TplPrevious );\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    if ( NULL != pSocket ) {\r
+      *pErrno = pSocket->errno;\r
+    }\r
+    else\r
+    {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      *pErrno = EBADF;\r
+    }\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Shutdown the socket receive and transmit operations\r
+\r
+  The SocketShutdown routine stops the socket receive and transmit\r
+  operations.\r
+\r
+  @param [in] pSocketProtocol Address of the socket protocol structure.\r
+  \r
+  @param [in] How             Which operations to stop\r
+  \r
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS - Socket operations successfully shutdown\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketShutdown (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN int How,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+  \r
+  DBG_ENTER ( );\r
+  \r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pSocket = NULL;\r
+  if ( NULL != pSocketProtocol ) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+    //\r
+    //  Verify that the socket is connected\r
+    //\r
+    if ( pSocket->bConnected ) {\r
+      //\r
+      //  Validate the How value\r
+      //\r
+      if (( SHUT_RD <= How ) && ( SHUT_RDWR >= How )) {\r
+        //\r
+        //  Synchronize with the socket layer\r
+        //\r
+        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+        //\r
+        //  Disable the receiver if requested\r
+        //\r
+        if (( SHUT_RD == How ) || ( SHUT_RDWR == How )) {\r
+          pSocket->bRxDisable = TRUE;\r
+        }\r
+\r
+        //\r
+        //  Disable the transmitter if requested\r
+        //\r
+        if (( SHUT_WR == How ) || ( SHUT_RDWR == How )) {\r
+          pSocket->bTxDisable = TRUE;\r
+        }\r
+\r
+        //\r
+        //  Validate the local address\r
+        //\r
+        switch ( pSocket->Domain ) {\r
+        default:\r
+          DEBUG (( DEBUG_RX,\r
+                    "ERROR - Invalid socket address family: %d\r\n",\r
+                    pSocket->Domain ));\r
+          Status = EFI_INVALID_PARAMETER;\r
+          pSocket->errno = EADDRNOTAVAIL;\r
+          break;\r
+        \r
+        case AF_INET:\r
+          //\r
+          //  Determine the connection point within the network stack\r
+          //\r
+          switch ( pSocket->Type ) {\r
+          default:\r
+            DEBUG (( DEBUG_RX,\r
+                      "ERROR - Invalid socket type: %d\r\n",\r
+                      pSocket->Type));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            break;\r
+        \r
+          case SOCK_STREAM:\r
+          case SOCK_SEQPACKET:\r
+            //\r
+            //  Cancel the pending receive operation\r
+            //\r
+            Status = EslTcpRxCancel4 ( pSocket );\r
+            break;\r
+        \r
+          case SOCK_DGRAM:\r
+            //\r
+            //  Cancel the pending receive operation\r
+            //\r
+            Status = EslUdpRxCancel4 ( pSocket );\r
+            break;\r
+          }\r
+          break;\r
+        }\r
+        \r
+        //\r
+        //  Release the socket layer synchronization\r
+        //\r
+        RESTORE_TPL ( TplPrevious );\r
+      }\r
+      else {\r
+        //\r
+        //  The socket is not connected\r
+        //\r
+        pSocket->errno = ENOTCONN;\r
+        Status = EFI_NOT_STARTED;\r
+      }\r
+    }\r
+    else {\r
+      //\r
+      //  Invalid How value\r
+      //\r
+      pSocket->errno = EINVAL;\r
+      Status = EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    if ( NULL != pSocket ) {\r
+      *pErrno = pSocket->errno;\r
+    }\r
+    else\r
+    {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      *pErrno = EBADF;\r
+    }\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Send data using a network connection.\r
+\r
+  The SocketTransmit routine queues the data for transmission to the\r
+  remote network connection.\r
+\r
+  @param [in] pSocketProtocol Address of the socket protocol structure.\r
+  \r
+  @param [in] Flags           Message control flags\r
+  \r
+  @param [in] BufferLength    Length of the the buffer\r
+  \r
+  @param [in] pBuffer         Address of a buffer containing the data to send\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
+\r
+  @param [in] AddressLength   Length of the remote network address structure\r
+\r
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS - Socket data successfully queued for transmit\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketTransmit (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN int Flags,\r
+  IN size_t BufferLength,\r
+  IN CONST UINT8 * pBuffer,\r
+  OUT size_t * pDataLength,\r
+  IN const struct sockaddr * pAddress,\r
+  IN socklen_t AddressLength,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  DT_SOCKET * pSocket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pSocket = NULL;\r
+  if ( NULL != pSocketProtocol ) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+    //\r
+    //  Verify the socket state\r
+    //\r
+    if ( !pSocket->bConfigured ) {\r
+      //\r
+      //  Synchronize with the socket layer\r
+      //\r
+      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+    \r
+      //\r
+      //  Validate the local address\r
+      //\r
+      switch ( pSocket->Domain ) {\r
+      default:\r
+        DEBUG (( DEBUG_RX,\r
+                  "ERROR - Invalid socket address family: %d\r\n",\r
+                  pSocket->Domain ));\r
+        Status = EFI_INVALID_PARAMETER;\r
+        pSocket->errno = EADDRNOTAVAIL;\r
+        break;\r
+    \r
+      case AF_INET:\r
+        //\r
+        //  Determine the connection point within the network stack\r
+        //\r
+        switch ( pSocket->Type ) {\r
+        default:\r
+          DEBUG (( DEBUG_RX,\r
+                    "ERROR - Invalid socket type: %d\r\n",\r
+                    pSocket->Type));\r
+          Status = EFI_INVALID_PARAMETER;\r
+          break;\r
+    \r
+        case SOCK_STREAM:\r
+        case SOCK_SEQPACKET:\r
+          //\r
+          //  Verify the port state\r
+          //\r
+          Status = EslTcpSocketIsConfigured4 ( pSocket );\r
+          break;\r
+    \r
+        case SOCK_DGRAM:\r
+          //\r
+          //  Verify the port state\r
+          //\r
+          Status = EslUdpSocketIsConfigured4 ( pSocket );\r
+          break;\r
+        }\r
+        break;\r
+      }\r
+    \r
+      //\r
+      //  Release the socket layer synchronization\r
+      //\r
+      RESTORE_TPL ( TplPrevious );\r
+    \r
+      //\r
+      //  Set errno if a failure occurs\r
+      //\r
+      if ( EFI_ERROR ( Status )) {\r
+        pSocket->errno = EADDRNOTAVAIL;\r
+      }\r
+    }\r
+    if ( !EFI_ERROR ( Status )) {\r
+      //\r
+      //  Verify that transmit is still allowed\r
+      //\r
+      if ( !pSocket->bTxDisable ) {\r
+        //\r
+        //  Validate the buffer length\r
+        //\r
+        if (( NULL == pDataLength )\r
+          && ( 0 > pDataLength )\r
+          && ( NULL == pBuffer )) {\r
+          if ( NULL == pDataLength ) {\r
+            DEBUG (( DEBUG_RX,\r
+                      "ERROR - pDataLength is NULL!\r\n" ));\r
+          }\r
+          else if ( NULL == pBuffer ) {\r
+            DEBUG (( DEBUG_RX,\r
+                      "ERROR - pBuffer is NULL!\r\n" ));\r
+          }\r
+          else {\r
+            DEBUG (( DEBUG_RX,\r
+                      "ERROR - Data length < 0!\r\n" ));\r
+          }\r
+          Status = EFI_INVALID_PARAMETER;\r
+          pSocket->errno = EFAULT;\r
+        }\r
+        else {\r
+          //\r
+          //  Validate the remote network address\r
+          //\r
+          if (( NULL != pAddress )\r
+            && ( AddressLength < pAddress->sa_len )) {\r
+            DEBUG (( DEBUG_TX,\r
+                      "ERROR - Invalid sin_len field in address\r\n" ));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            pSocket->errno = EFAULT;\r
+          }\r
+          else {\r
+            //\r
+            //  Synchronize with the socket layer\r
+            //\r
+            RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+            //\r
+            //  Validate the local address\r
+            //\r
+            switch ( pSocket->Domain ) {\r
+            default:\r
+              DEBUG (( DEBUG_RX,\r
+                        "ERROR - Invalid socket address family: %d\r\n",\r
+                        pSocket->Domain ));\r
+              Status = EFI_INVALID_PARAMETER;\r
+              pSocket->errno = EADDRNOTAVAIL;\r
+              break;\r
+\r
+            case AF_INET:\r
+              //\r
+              //  Determine the connection point within the network stack\r
+              //\r
+              switch ( pSocket->Type ) {\r
+              default:\r
+                DEBUG (( DEBUG_RX,\r
+                          "ERROR - Invalid socket type: %d\r\n",\r
+                          pSocket->Type));\r
+                Status = EFI_INVALID_PARAMETER;\r
+                pSocket->errno = EADDRNOTAVAIL;\r
+                break;\r
+\r
+              case SOCK_STREAM:\r
+              case SOCK_SEQPACKET:\r
+                Status = EslTcpTxBuffer4 ( pSocket,\r
+                                           Flags,\r
+                                           BufferLength,\r
+                                           pBuffer,\r
+                                           pDataLength );\r
+                break;\r
+\r
+              case SOCK_DGRAM:\r
+                Status = EslUdpTxBuffer4 ( pSocket,\r
+                                           Flags,\r
+                                           BufferLength,\r
+                                           pBuffer,\r
+                                           pDataLength,\r
+                                           pAddress,\r
+                                           AddressLength );\r
+                break;\r
+              }\r
+              break;\r
+            }\r
+\r
+            //\r
+            //  Release the socket layer synchronization\r
+            //\r
+            RESTORE_TPL ( TplPrevious );\r
+          }\r
+        }\r
+      }\r
+      else {\r
+        //\r
+        //  The transmitter was shutdown\r
+        //\r
+        pSocket->errno = EPIPE;\r
+        Status = EFI_NOT_STARTED;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    if ( NULL != pSocket ) {\r
+      *pErrno = pSocket->errno;\r
+    }\r
+    else\r
+    {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      *pErrno = EBADF;\r
+    }\r
+  }\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Socket layer's service binding protocol delcaration.\r
+**/\r
+EFI_SERVICE_BINDING_PROTOCOL mEfiServiceBinding = {\r
+  EslSocketCreateChild,\r
+  EslSocketDestroyChild\r
+};\r