]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/EfiSocketLib/Udp4.c
Nt32Pkg: Add HttpUtilitiesDxe module
[mirror_edk2.git] / StdLib / EfiSocketLib / Udp4.c
index 95fc66517a45c32ed2e79edabdf3d71c2b1d7561..ef2f9e321b2d50f856009233e21ffcd733b6a1e6 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Implement the UDP4 driver support for the socket layer.\r
 \r
-  Copyright (c) 2011, Intel Corporation\r
+  Copyright (c) 2011 - 2015, 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
 \r
 \r
 /**\r
-  Bind a name to a socket.\r
+  Get the local socket address\r
 \r
-  The ::UdpBind4 routine connects a name to a UDP4 stack on the local machine.\r
+  This routine returns the IPv4 address and UDP port number associated\r
+  with the local socket.\r
 \r
-  The configure call to the UDP4 driver occurs on the first poll, recv, recvfrom,\r
-  send or sentto call.  Until then, all changes are made in the local UDP context\r
-  structure.\r
-  \r
-  @param [in] pSocket   Address of the socket structure.\r
+  This routine is called by ::EslSocketGetLocalAddress to determine the\r
+  network address for the SOCK_DGRAM socket.\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
+  @param [in] pPort       Address of an ::ESL_PORT structure.\r
 \r
-  @param [in] SockAddrLen   Specifies the length in bytes of the sockaddr structure.\r
+  @param [out] pSockAddr  Network address to receive the local system address\r
 \r
-  @retval EFI_SUCCESS - Socket successfully created\r
+**/\r
+VOID\r
+EslUdp4LocalAddressGet (\r
+  IN ESL_PORT * pPort,\r
+  OUT struct sockaddr * pSockAddr\r
+  )\r
+{\r
+  struct sockaddr_in * pLocalAddress;\r
+  ESL_UDP4_CONTEXT * pUdp4;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Return the local address\r
+  //\r
+  pUdp4 = &pPort->Context.Udp4;\r
+  pLocalAddress = (struct sockaddr_in *)pSockAddr;\r
+  pLocalAddress->sin_family = AF_INET;\r
+  pLocalAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.StationPort );\r
+  CopyMem ( &pLocalAddress->sin_addr,\r
+            &pUdp4->ConfigData.StationAddress.Addr[0],\r
+            sizeof ( pLocalAddress->sin_addr ));\r
+\r
+  DBG_EXIT ( );\r
+}\r
+\r
+\r
+/**\r
+  Set the local port address.\r
+\r
+  This routine sets the local port address.\r
+\r
+  This support routine is called by ::EslSocketPortAllocate.\r
+\r
+  @param [in] pPort       Address of an ESL_PORT structure\r
+  @param [in] pSockAddr   Address of a sockaddr structure that contains the\r
+                          connection point on the local machine.  An IPv4 address\r
+                          of INADDR_ANY specifies that the connection is made to\r
+                          all of the network stacks on the platform.  Specifying a\r
+                          specific IPv4 address restricts the connection to the\r
+                          network stack supporting that address.  Specifying zero\r
+                          for the port causes the network layer to assign a port\r
+                          number from the dynamic range.  Specifying a specific\r
+                          port number causes the network layer to use that port.\r
+\r
+  @param [in] bBindTest   TRUE = run bind testing\r
+\r
+  @retval EFI_SUCCESS     The operation was successful\r
 \r
  **/\r
 EFI_STATUS\r
-EslUdpBind4 (\r
-  IN DT_SOCKET * pSocket,\r
-  IN const struct sockaddr * pSockAddr,\r
-  IN socklen_t SockAddrLength\r
+EslUdp4LocalAddressSet (\r
+  IN ESL_PORT * pPort,\r
+  IN CONST struct sockaddr * pSockAddr,\r
+  IN BOOLEAN bBindTest\r
   )\r
 {\r
-  EFI_HANDLE ChildHandle;\r
-  DT_LAYER * pLayer;\r
-  DT_PORT * pPort;\r
-  DT_SERVICE * pService;\r
-  CONST struct sockaddr_in * pIp4Address;\r
-  EFI_SERVICE_BINDING_PROTOCOL * pUdp4Service;\r
+  EFI_UDP4_CONFIG_DATA * pConfig;\r
+  CONST struct sockaddr_in * pIpAddress;\r
+  CONST UINT8 * pIpv4Address;\r
   EFI_STATUS Status;\r
-  EFI_STATUS TempStatus;\r
-  \r
+\r
   DBG_ENTER ( );\r
-  \r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-  \r
-  //\r
-  //  Assume success\r
-  //\r
-  pSocket->errno = 0;\r
-  Status = EFI_SUCCESS;\r
-  \r
+\r
   //\r
-  //  Validate the address length\r
+  //  Validate the address\r
   //\r
-  pIp4Address = (CONST struct sockaddr_in *) pSockAddr;\r
-  if ( SockAddrLength >= ( sizeof ( *pIp4Address )\r
-                           - sizeof ( pIp4Address->sin_zero ))) {\r
+  pIpAddress = (struct sockaddr_in *)pSockAddr;\r
+  if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) {\r
+    //\r
+    //  The local address must not be the broadcast address\r
+    //\r
+    Status = EFI_INVALID_PARAMETER;\r
+    pPort->pSocket->errno = EADDRNOTAVAIL;\r
+  }\r
+  else {\r
+    //\r
+    //  Set the local address\r
+    //\r
+    pIpAddress = (struct sockaddr_in *)pSockAddr;\r
+    pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr;\r
+    pConfig = &pPort->Context.Udp4.ConfigData;\r
+    pConfig->StationAddress.Addr[0] = pIpv4Address[0];\r
+    pConfig->StationAddress.Addr[1] = pIpv4Address[1];\r
+    pConfig->StationAddress.Addr[2] = pIpv4Address[2];\r
+    pConfig->StationAddress.Addr[3] = pIpv4Address[3];\r
 \r
     //\r
-    //  Walk the list of services\r
+    //  Determine if the default address is used\r
+    //\r
+    pConfig->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr );\r
+    \r
+    //\r
+    //  Set the subnet mask\r
     //\r
-    pLayer = &mEslLayer;\r
-    pService = pLayer->pUdp4List;\r
-    while ( NULL != pService ) {\r
+    if ( pConfig->UseDefaultAddress ) {\r
+      pConfig->SubnetMask.Addr[0] = 0;\r
+      pConfig->SubnetMask.Addr[1] = 0;\r
+      pConfig->SubnetMask.Addr[2] = 0;\r
+      pConfig->SubnetMask.Addr[3] = 0;\r
+    }\r
+    else {\r
+      pConfig->SubnetMask.Addr[0] = 0xff;\r
+      pConfig->SubnetMask.Addr[1] = ( 128 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;\r
+      pConfig->SubnetMask.Addr[2] = ( 192 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;\r
+      pConfig->SubnetMask.Addr[3] = ( 224 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;\r
+    }\r
 \r
+    //\r
+    //  Validate the IP address\r
+    //\r
+    pConfig->StationPort = 0;\r
+    Status = bBindTest ? EslSocketBindTest ( pPort, EADDRNOTAVAIL )\r
+                       : EFI_SUCCESS;\r
+    if ( !EFI_ERROR ( Status )) {\r
       //\r
-      //  Create the UDP port\r
-      //\r
-      pUdp4Service = pService->pInterface;\r
-      ChildHandle = NULL;\r
-      Status = pUdp4Service->CreateChild ( pUdp4Service,\r
-                                           &ChildHandle );\r
-      if ( !EFI_ERROR ( Status )) {\r
-        DEBUG (( DEBUG_BIND | DEBUG_POOL,\r
-                  "0x%08x: Udp4 port handle created\r\n",\r
-                  ChildHandle ));\r
-  \r
-        //\r
-        //  Open the port\r
-        //\r
-        Status = EslUdpPortAllocate4 ( pSocket,\r
-                                       pService,\r
-                                       ChildHandle,\r
-                                       (UINT8 *) &pIp4Address->sin_addr.s_addr,\r
-                                       SwapBytes16 ( pIp4Address->sin_port ),\r
-                                       DEBUG_BIND,\r
-                                       &pPort );\r
-      }\r
-      else {\r
-        DEBUG (( DEBUG_BIND | DEBUG_POOL,\r
-                  "ERROR - Failed to open Udp4 port handle, Status: %r\r\n",\r
-                  Status ));\r
-        ChildHandle = NULL;\r
-      }\r
-  \r
-      //\r
-      //  Close the port if necessary\r
+      //  Set the port number\r
       //\r
-      if (( EFI_ERROR ( Status )) && ( NULL != ChildHandle )) {\r
-        TempStatus = pUdp4Service->DestroyChild ( pUdp4Service,\r
-                                                  ChildHandle );\r
-        if ( !EFI_ERROR ( TempStatus )) {\r
-          DEBUG (( DEBUG_BIND | DEBUG_POOL,\r
-                    "0x%08x: Udp4 port handle destroyed\r\n",\r
-                    ChildHandle ));\r
-        }\r
-        else {\r
-          DEBUG (( DEBUG_ERROR | DEBUG_BIND | DEBUG_POOL,\r
-                    "ERROR - Failed to destroy the Udp4 port handle 0x%08x, Status: %r\r\n",\r
-                    ChildHandle,\r
-                    TempStatus ));\r
-          ASSERT ( EFI_SUCCESS == TempStatus );\r
-        }\r
-      }\r
-  \r
+      pConfig->StationPort = SwapBytes16 ( pIpAddress->sin_port );\r
+\r
       //\r
-      //  Set the next service\r
+      //  Display the local address\r
       //\r
-      pService = pService->pNext;\r
-    }\r
-  \r
-    //\r
-    //  Verify that at least one network connection was found\r
-    //\r
-    if ( NULL == pSocket->pPortList ) {\r
-      DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,\r
-                "Socket address %d.%d.%d.%d (0x%08x) is not available!\r\n",\r
-                ( pIp4Address->sin_addr.s_addr >> 24 ) & 0xff,\r
-                ( pIp4Address->sin_addr.s_addr >> 16 ) & 0xff,\r
-                ( pIp4Address->sin_addr.s_addr >> 8 ) & 0xff,\r
-                pIp4Address->sin_addr.s_addr & 0xff,\r
-                pIp4Address->sin_addr.s_addr ));\r
-      pSocket->errno = EADDRNOTAVAIL;\r
-      Status = EFI_INVALID_PARAMETER;\r
+      DEBUG (( DEBUG_BIND,\r
+                "0x%08x: Port, Local UDP4 Address: %d.%d.%d.%d:%d\r\n",\r
+                pPort,\r
+                pConfig->StationAddress.Addr[0],\r
+                pConfig->StationAddress.Addr[1],\r
+                pConfig->StationAddress.Addr[2],\r
+                pConfig->StationAddress.Addr[3],\r
+                pConfig->StationPort ));\r
     }\r
   }\r
-  else {\r
-    DEBUG (( DEBUG_BIND,\r
-              "ERROR - Invalid Udp4 address length: %d\r\n",\r
-              SockAddrLength ));\r
-    Status = EFI_INVALID_PARAMETER;\r
-    pSocket->errno = EINVAL;\r
-  }\r
-  \r
+\r
   //\r
   //  Return the operation status\r
   //\r
@@ -172,248 +171,104 @@ EslUdpBind4 (
 \r
 \r
 /**\r
-  Initialize the UDP4 service.\r
+  Free a receive packet\r
 \r
-  This routine initializes the UDP4 service after its service binding\r
-  protocol was located on a controller.\r
+  This routine performs the network specific operations necessary\r
+  to free a receive packet.\r
 \r
-  @param [in] pService        DT_SERVICE structure address\r
+  This routine is called by ::EslSocketPortCloseTxDone to free a\r
+  receive packet.\r
 \r
-  @retval EFI_SUCCESS         The service was properly initialized\r
-  @retval other               A failure occurred during the service initialization\r
+  @param [in] pPacket         Address of an ::ESL_PACKET structure.\r
+  @param [in, out] pRxBytes   Address of the count of RX bytes\r
 \r
 **/\r
-EFI_STATUS\r
-EFIAPI\r
-EslUdpInitialize4 (\r
-  IN DT_SERVICE * pService\r
+VOID\r
+EslUdp4PacketFree (\r
+  IN ESL_PACKET * pPacket,\r
+  IN OUT size_t * pRxBytes\r
   )\r
 {\r
-  DT_LAYER * pLayer;\r
-  EFI_STATUS Status;\r
+  EFI_UDP4_RECEIVE_DATA * pRxData;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Identify the service\r
-  //\r
-  pService->NetworkType = NETWORK_TYPE_UDP4;\r
-\r
-  //\r
-  //  Connect this service to the service list\r
+  //  Account for the receive bytes\r
   //\r
-  pLayer = &mEslLayer;\r
-  pService->pNext = pLayer->pUdp4List;\r
-  pLayer->pUdp4List = pService;\r
+  pRxData = pPacket->Op.Udp4Rx.pRxData;\r
+  *pRxBytes -= pRxData->DataLength;\r
 \r
   //\r
-  //  Assume the list is empty\r
+  //  Disconnect the buffer from the packet\r
   //\r
-  Status = EFI_SUCCESS;\r
+  pPacket->Op.Udp4Rx.pRxData = NULL;\r
 \r
   //\r
-  //  Return the initialization status\r
+  //  Return the buffer to the UDP4 driver\r
   //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
+  gBS->SignalEvent ( pRxData->RecycleSignal );\r
+  DBG_EXIT ( );\r
 }\r
 \r
 \r
 /**\r
-  Allocate and initialize a DT_PORT structure.\r
+  Initialize the network specific portions of an ::ESL_PORT structure.\r
 \r
-  @param [in] pSocket     Address of the socket structure.\r
-  @param [in] pService    Address of the DT_SERVICE structure.\r
-  @param [in] ChildHandle Udp4 child handle\r
-  @param [in] pIpAddress  Buffer containing IP4 network address of the local host\r
-  @param [in] PortNumber  Udp4 port number\r
+  This routine initializes the network specific portions of an\r
+  ::ESL_PORT structure for use by the socket.\r
+\r
+  This support routine is called by ::EslSocketPortAllocate\r
+  to connect the socket with the underlying network adapter\r
+  running the UDPv4 protocol.\r
+\r
+  @param [in] pPort       Address of an ESL_PORT structure\r
   @param [in] DebugFlags  Flags for debug messages\r
-  @param [out] ppPort     Buffer to receive new DT_PORT structure address\r
 \r
   @retval EFI_SUCCESS - Socket successfully created\r
 \r
  **/\r
 EFI_STATUS\r
-EslUdpPortAllocate4 (\r
-  IN DT_SOCKET * pSocket,\r
-  IN DT_SERVICE * pService,\r
-  IN EFI_HANDLE ChildHandle,\r
-  IN CONST UINT8 * pIpAddress,\r
-  IN UINT16 PortNumber,\r
-  IN UINTN DebugFlags,\r
-  OUT DT_PORT ** ppPort\r
+EslUdp4PortAllocate (\r
+  IN ESL_PORT * pPort,\r
+  IN UINTN DebugFlags\r
   )\r
 {\r
-  UINTN LengthInBytes;\r
   EFI_UDP4_CONFIG_DATA * pConfig;\r
-  DT_LAYER * pLayer;\r
-  DT_PORT * pPort;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Use for/break instead of goto\r
-  for ( ; ; ) {\r
-    //\r
-    //  Allocate a port structure\r
-    //\r
-    pLayer = &mEslLayer;\r
-    LengthInBytes = sizeof ( *pPort );\r
-    Status = gBS->AllocatePool ( EfiRuntimeServicesData,\r
-                                 LengthInBytes,\r
-                                 (VOID **)&pPort );\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
-                "ERROR - Failed to allocate the port structure, Status: %r\r\n",\r
-                Status ));\r
-      pSocket->errno = ENOMEM;\r
-      pPort = NULL;\r
-      break;\r
-    }\r
-    DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
-              "0x%08x: Allocate pPort, %d bytes\r\n",\r
-              pPort,\r
-              LengthInBytes ));\r
-\r
-    //\r
-    //  Initialize the port\r
-    //\r
-    ZeroMem ( pPort, LengthInBytes );\r
-    pPort->Signature = PORT_SIGNATURE;\r
-    pPort->pService = pService;\r
-    pPort->pSocket = pSocket;\r
-    pPort->pfnCloseStart = EslUdpPortCloseStart4;\r
-    pPort->DebugFlags = DebugFlags;\r
-\r
-    //\r
-    //  Allocate the receive event\r
-    //\r
-    pUdp4 = &pPort->Context.Udp4;\r
-    Status = gBS->CreateEvent (  EVT_NOTIFY_SIGNAL,\r
-                                 TPL_SOCKETS,\r
-                                 (EFI_EVENT_NOTIFY)EslUdpRxComplete4,\r
-                                 pPort,\r
-                                 &pUdp4->RxToken.Event);\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to create the receive event, Status: %r\r\n",\r
-                Status ));\r
-      pSocket->errno = ENOMEM;\r
-      break;\r
-    }\r
-    DEBUG (( DEBUG_RX | DEBUG_POOL,\r
-              "0x%08x: Created receive event\r\n",\r
-              pUdp4->RxToken.Event ));\r
-\r
-    //\r
-    //  Allocate the transmit event\r
-    //\r
-    Status = gBS->CreateEvent (  EVT_NOTIFY_SIGNAL,\r
-                                 TPL_SOCKETS,\r
-                                 (EFI_EVENT_NOTIFY)EslUdpTxComplete4,\r
-                                 pPort,\r
-                                 &pUdp4->TxToken.Event);\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to create the transmit event, Status: %r\r\n",\r
-                Status ));\r
-      pSocket->errno = ENOMEM;\r
-      break;\r
-    }\r
-    DEBUG (( DEBUG_CLOSE | DEBUG_POOL,\r
-              "0x%08x: Created transmit event\r\n",\r
-              pUdp4->TxToken.Event ));\r
-\r
-    //\r
-    //  Open the port protocol\r
-    //\r
-    Status = gBS->OpenProtocol (\r
-                    ChildHandle,\r
-                    &gEfiUdp4ProtocolGuid,\r
-                    (VOID **) &pUdp4->pProtocol,\r
-                    pLayer->ImageHandle,\r
-                    NULL,\r
-                    EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to open gEfiUdp4ProtocolGuid on controller 0x%08x\r\n",\r
-                pUdp4->Handle ));\r
-      pSocket->errno = EEXIST;\r
-      break;\r
-    }\r
-    DEBUG (( DebugFlags,\r
-              "0x%08x: gEfiUdp4ProtocolGuid opened on controller 0x%08x\r\n",\r
-              pUdp4->pProtocol,\r
-              ChildHandle ));\r
-\r
-    //\r
-    //  Set the port address\r
-    //\r
-    pUdp4->Handle = ChildHandle;\r
-    pConfig = &pPort->Context.Udp4.ConfigData;\r
-    pConfig->StationPort = PortNumber;\r
-    if (( 0 == pIpAddress[0])\r
-      && ( 0 == pIpAddress[1])\r
-      && ( 0 == pIpAddress[2])\r
-      && ( 0 == pIpAddress[3])) {\r
-      pConfig->UseDefaultAddress = TRUE;\r
-    }\r
-    else {\r
-      pConfig->StationAddress.Addr[0] = pIpAddress[0];\r
-      pConfig->StationAddress.Addr[1] = pIpAddress[1];\r
-      pConfig->StationAddress.Addr[2] = pIpAddress[2];\r
-      pConfig->StationAddress.Addr[3] = pIpAddress[3];\r
-      pConfig->SubnetMask.Addr[0] = 0xff;\r
-      pConfig->SubnetMask.Addr[1] = 0xff;\r
-      pConfig->SubnetMask.Addr[2] = 0xff;\r
-      pConfig->SubnetMask.Addr[3] = 0xff;\r
-    }\r
-    pConfig->TimeToLive = 255;\r
-    pConfig->AcceptAnyPort = FALSE;\r
-    pConfig->AcceptBroadcast = FALSE;\r
-    pConfig->AcceptPromiscuous = FALSE;\r
-    pConfig->AllowDuplicatePort = TRUE;\r
-    pConfig->DoNotFragment = TRUE;\r
-\r
-    //\r
-    //  Verify the socket layer synchronization\r
-    //\r
-    VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-    //\r
-    //  Add this port to the socket\r
-    //\r
-    pPort->pLinkSocket = pSocket->pPortList;\r
-    pSocket->pPortList = pPort;\r
-    DEBUG (( DebugFlags,\r
-              "0x%08x: Socket adding port: 0x%08x\r\n",\r
-              pSocket,\r
-              pPort ));\r
-\r
-    //\r
-    //  Add this port to the service\r
-    //\r
-    pPort->pLinkService = pService->pPortList;\r
-    pService->pPortList = pPort;\r
+  //  Initialize the port\r
+  //\r
+  pSocket = pPort->pSocket;\r
+  pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Udp4Tx.TxData );\r
+  pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Udp4Tx.Event );\r
+  pSocket->TxTokenOffset = OFFSET_OF ( EFI_UDP4_COMPLETION_TOKEN, Packet.TxData );\r
 \r
-    //\r
-    //  Return the port\r
-    //\r
-    *ppPort = pPort;\r
-    break;\r
-  }\r
+  //\r
+  //  Save the cancel, receive and transmit addresses\r
+  //\r
+  pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.UDPv4->Configure;\r
+  pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Cancel;\r
+  pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.UDPv4->Poll;\r
+  pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Receive;\r
+  pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Transmit;\r
 \r
   //\r
-  //  Clean up after the error if necessary\r
+  //  Set the configuration flags\r
   //\r
-  if (( EFI_ERROR ( Status )) && ( NULL != pPort )) {\r
-    //\r
-    //  Close the port\r
-    //\r
-    EslUdpPortClose4 ( pPort );\r
-  }\r
+  pConfig = &pPort->Context.Udp4.ConfigData;\r
+  pConfig->TimeToLive = 255;\r
+  pConfig->AcceptAnyPort = FALSE;\r
+  pConfig->AcceptBroadcast = FALSE;\r
+  pConfig->AcceptPromiscuous = FALSE;\r
+  pConfig->AllowDuplicatePort = TRUE;\r
+  pConfig->DoNotFragment = FALSE;\r
+  Status = EFI_SUCCESS;\r
+\r
   //\r
   //  Return the operation status\r
   //\r
@@ -423,1480 +278,301 @@ EslUdpPortAllocate4 (
 \r
 \r
 /**\r
-  Close a UDP4 port.\r
+  Receive data from a network connection.\r
+\r
+  This routine attempts to return buffered data to the caller.  The\r
+  data is removed from the urgent queue if the message flag MSG_OOB\r
+  is specified, otherwise data is removed from the normal queue.\r
+  See the \ref ReceiveEngine section.\r
+\r
+  This routine is called by ::EslSocketReceive to handle the network\r
+  specific receive operation to support SOCK_DGRAM sockets.\r
 \r
-  This routine releases the resources allocated by\r
-  ::UdpPortAllocate4().\r
+  @param [in] pPort           Address of an ::ESL_PORT structure.\r
+\r
+  @param [in] pPacket         Address of an ::ESL_PACKET structure.\r
+  \r
+  @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed\r
+  \r
+  @param [in] BufferLength    Length of the the buffer\r
   \r
-  @param [in] pPort       Address of the port structure.\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
-  @retval EFI_SUCCESS     The port is closed\r
-  @retval other           Port close error\r
+  @param [out] pSkipBytes     Address to receive the number of bytes skipped\r
 \r
-**/\r
-EFI_STATUS\r
-EslUdpPortClose4 (\r
-  IN DT_PORT * pPort\r
+  @return   Returns the address of the next free byte in the buffer.\r
+\r
+ **/\r
+UINT8 *\r
+EslUdp4Receive (\r
+  IN ESL_PORT * pPort,\r
+  IN ESL_PACKET * pPacket,\r
+  IN BOOLEAN * pbConsumePacket,\r
+  IN size_t BufferLength,\r
+  IN UINT8 * pBuffer,\r
+  OUT size_t * pDataLength,\r
+  OUT struct sockaddr * pAddress,\r
+  OUT size_t * pSkipBytes\r
   )\r
 {\r
-  UINTN DebugFlags;\r
-  DT_LAYER * pLayer;\r
-  DT_PACKET * pPacket;\r
-  DT_PORT * pPreviousPort;\r
-  DT_SERVICE * pService;\r
-  DT_SOCKET * pSocket;\r
-  EFI_SERVICE_BINDING_PROTOCOL * pUdp4Service;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  EFI_STATUS Status;\r
-  \r
+  size_t DataBytes;\r
+  struct sockaddr_in * pRemoteAddress;\r
+  EFI_UDP4_RECEIVE_DATA * pRxData;\r
+\r
   DBG_ENTER ( );\r
 \r
+  pRxData = pPacket->Op.Udp4Rx.pRxData;\r
   //\r
-  //  Verify the socket layer synchronization\r
+  //  Return the remote system address if requested\r
   //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
+  if ( NULL != pAddress ) {\r
+    //\r
+    //  Build the remote address\r
+    //\r
+    DEBUG (( DEBUG_RX,\r
+              "Getting packet remote address: %d.%d.%d.%d:%d\r\n",\r
+              pRxData->UdpSession.SourceAddress.Addr[0],\r
+              pRxData->UdpSession.SourceAddress.Addr[1],\r
+              pRxData->UdpSession.SourceAddress.Addr[2],\r
+              pRxData->UdpSession.SourceAddress.Addr[3],\r
+              pRxData->UdpSession.SourcePort ));\r
+    pRemoteAddress = (struct sockaddr_in *)pAddress;\r
+    CopyMem ( &pRemoteAddress->sin_addr,\r
+              &pRxData->UdpSession.SourceAddress.Addr[0],\r
+              sizeof ( pRemoteAddress->sin_addr ));\r
+    pRemoteAddress->sin_port = SwapBytes16 ( pRxData->UdpSession.SourcePort );\r
+  }\r
 \r
   //\r
-  //  Assume success\r
+  //  Copy the received data\r
   //\r
-  Status = EFI_SUCCESS;\r
-  pSocket = pPort->pSocket;\r
-  pSocket->errno = 0;\r
+  pBuffer = EslSocketCopyFragmentedBuffer ( pRxData->FragmentCount,\r
+                                            (EFI_IP4_FRAGMENT_DATA *)&pRxData->FragmentTable[0],\r
+                                            BufferLength,\r
+                                            pBuffer,\r
+                                            &DataBytes );\r
 \r
   //\r
-  //  Locate the port in the socket list\r
+  //  Determine if the data is being read\r
   //\r
-  pLayer = &mEslLayer;\r
-  DebugFlags = pPort->DebugFlags;\r
-  pPreviousPort = pSocket->pPortList;\r
-  if ( pPreviousPort == pPort ) {\r
-    //\r
-    //  Remove this port from the head of the socket list\r
-    //\r
-    pSocket->pPortList = pPort->pLinkSocket;\r
-  }\r
-  else {\r
+  if ( *pbConsumePacket ) {\r
     //\r
-    //  Locate the port in the middle of the socket list\r
+    //  Display for the bytes consumed\r
     //\r
-    while (( NULL != pPreviousPort )\r
-      && ( pPreviousPort->pLinkSocket != pPort )) {\r
-      pPreviousPort = pPreviousPort->pLinkSocket;\r
-    }\r
-    if ( NULL != pPreviousPort ) {\r
-      //\r
-      //  Remove the port from the middle of the socket list\r
-      //\r
-      pPreviousPort->pLinkSocket = pPort->pLinkSocket;\r
-    }\r
-  }\r
+    DEBUG (( DEBUG_RX,\r
+              "0x%08x: Port account for 0x%08x bytes\r\n",\r
+              pPort,\r
+              DataBytes ));\r
 \r
-  //\r
-  //  Locate the port in the service list\r
-  //\r
-  pService = pPort->pService;\r
-  pPreviousPort = pService->pPortList;\r
-  if ( pPreviousPort == pPort ) {\r
-    //\r
-    //  Remove this port from the head of the service list\r
-    //\r
-    pService->pPortList = pPort->pLinkService;\r
-  }\r
-  else {\r
     //\r
-    //  Locate the port in the middle of the service list\r
+    //  Account for any discarded data\r
     //\r
-    while (( NULL != pPreviousPort )\r
-      && ( pPreviousPort->pLinkService != pPort )) {\r
-      pPreviousPort = pPreviousPort->pLinkService;\r
-    }\r
-    if ( NULL != pPreviousPort ) {\r
-      //\r
-      //  Remove the port from the middle of the service list\r
-      //\r
-      pPreviousPort->pLinkService = pPort->pLinkService;\r
-    }\r
+    *pSkipBytes = pRxData->DataLength - DataBytes;\r
   }\r
 \r
   //\r
-  //  Empty the receive queue\r
+  //  Return the data length and the buffer address\r
   //\r
-  ASSERT ( NULL == pSocket->pRxPacketListHead );\r
-  ASSERT ( NULL == pSocket->pRxPacketListTail );\r
-  ASSERT ( 0 == pSocket->RxBytes );\r
+  *pDataLength = DataBytes;\r
+  DBG_EXIT_HEX ( pBuffer );\r
+  return pBuffer;\r
+}\r
 \r
-  //\r
-  //  Empty the receive free queue\r
-  //\r
-  while ( NULL != pSocket->pRxFree ) {\r
-    pPacket = pSocket->pRxFree;\r
-    pSocket->pRxFree = pPacket->pNext;\r
-    EslSocketPacketFree ( pPacket, DEBUG_RX );\r
-  }\r
 \r
-  //\r
-  //  Done with the receive event\r
-  //\r
-  pUdp4 = &pPort->Context.Udp4;\r
-  if ( NULL != pUdp4->RxToken.Event ) {\r
-    Status = gBS->CloseEvent ( pUdp4->RxToken.Event );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DebugFlags | DEBUG_POOL,\r
-                "0x%08x: Closed receive event\r\n",\r
-                pUdp4->RxToken.Event ));\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to close the receive event, Status: %r\r\n",\r
-                Status ));\r
-      ASSERT ( EFI_SUCCESS == Status );\r
-    }\r
-  }\r
+/**\r
+  Get the remote socket address\r
 \r
-  //\r
-  //  Done with the transmit event\r
-  //\r
-  if ( NULL != pUdp4->TxToken.Event ) {\r
-    Status = gBS->CloseEvent ( pUdp4->TxToken.Event );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DebugFlags | DEBUG_POOL,\r
-                "0x%08x: Closed normal transmit event\r\n",\r
-                pUdp4->TxToken.Event ));\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to close the normal transmit event, Status: %r\r\n",\r
-                Status ));\r
-      ASSERT ( EFI_SUCCESS == Status );\r
-    }\r
-  }\r
+  This routine returns the address of the remote connection point\r
+  associated with the SOCK_DGRAM socket.\r
 \r
-  //\r
-  //  Done with the UDP protocol\r
-  //\r
-  pUdp4Service = pService->pInterface;\r
-  if ( NULL != pUdp4->pProtocol ) {\r
-    Status = gBS->CloseProtocol ( pUdp4->Handle,\r
-                                  &gEfiUdp4ProtocolGuid,\r
-                                  pLayer->ImageHandle,\r
-                                  NULL );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DebugFlags,\r
-                "0x%08x: gEfiUdp4ProtocolGuid closed on controller 0x%08x\r\n",\r
-                pUdp4->pProtocol,\r
-                pUdp4->Handle ));\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags,\r
-                "ERROR - Failed to close gEfiUdp4ProtocolGuid opened on controller 0x%08x, Status: %r\r\n",\r
-                pUdp4->Handle,\r
-                Status ));\r
-      ASSERT ( EFI_SUCCESS == Status );\r
-    }\r
-  }\r
+  This routine is called by ::EslSocketGetPeerAddress to detemine\r
+  the UDPv4 address and port number associated with the network adapter.\r
+\r
+  @param [in] pPort       Address of an ::ESL_PORT structure.\r
+\r
+  @param [out] pAddress   Network address to receive the remote system address\r
+\r
+**/\r
+VOID\r
+EslUdp4RemoteAddressGet (\r
+  IN ESL_PORT * pPort,\r
+  OUT struct sockaddr * pAddress\r
+  )\r
+{\r
+  struct sockaddr_in * pRemoteAddress;\r
+  ESL_UDP4_CONTEXT * pUdp4;\r
+\r
+  DBG_ENTER ( );\r
 \r
   //\r
-  //  Done with the UDP port\r
+  //  Return the remote address\r
   //\r
-  if ( NULL != pUdp4->Handle ) {\r
-    Status = pUdp4Service->DestroyChild ( pUdp4Service,\r
-                                          pUdp4->Handle );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DebugFlags | DEBUG_POOL,\r
-                "0x%08x: Udp4 port handle destroyed\r\n",\r
-                pUdp4->Handle ));\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,\r
-                "ERROR - Failed to destroy the Udp4 port handle, Status: %r\r\n",\r
-                Status ));\r
-      ASSERT ( EFI_SUCCESS == Status );\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Release the port structure\r
-  //\r
-  Status = gBS->FreePool ( pPort );\r
-  if ( !EFI_ERROR ( Status )) {\r
-    DEBUG (( DebugFlags | DEBUG_POOL,\r
-              "0x%08x: Free pPort, %d bytes\r\n",\r
-              pPort,\r
-              sizeof ( *pPort )));\r
-  }\r
-  else {\r
-    DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,\r
-              "ERROR - Failed to free pPort: 0x%08x, Status: %r\r\n",\r
-              pPort,\r
-              Status ));\r
-    ASSERT ( EFI_SUCCESS == Status );\r
-  }\r
-\r
-  //\r
-  //  Mark the socket as closed if necessary\r
-  //\r
-  if ( NULL == pSocket->pPortList ) {\r
-    pSocket->State = SOCKET_STATE_CLOSED;\r
-    DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-              "0x%08x: Socket State: SOCKET_STATE_CLOSED\r\n",\r
-              pSocket ));\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Start the close operation on a UDP4 port, state 1.\r
-\r
-  Closing a port goes through the following states:\r
-  1. Port close starting - Mark the port as closing and wait for transmission to complete\r
-  2. Port TX close done - Transmissions complete, close the port and abort the receives\r
-  3. Port RX close done - Receive operations complete, close the port\r
-  4. Port closed - Release the port resources\r
-  \r
-  @param [in] pPort       Address of the port structure.\r
-  @param [in] bCloseNow   Set TRUE to abort active transfers\r
-  @param [in] DebugFlags  Flags for debug messages\r
-\r
-  @retval EFI_SUCCESS         The port is closed, not normally returned\r
-  @retval EFI_NOT_READY       The port has started the closing process\r
-  @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,\r
-                              most likely the routine was called already.\r
-\r
-**/\r
-EFI_STATUS\r
-EslUdpPortCloseStart4 (\r
-  IN DT_PORT * pPort,\r
-  IN BOOLEAN bCloseNow,\r
-  IN UINTN DebugFlags\r
-  )\r
-{\r
-  DT_SOCKET * pSocket;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  Mark the port as closing\r
-  //\r
-  Status = EFI_ALREADY_STARTED;\r
-  pSocket = pPort->pSocket;\r
-  pSocket->errno = EALREADY;\r
-  if ( PORT_STATE_CLOSE_STARTED > pPort->State ) {\r
-\r
-    //\r
-    //  Update the port state\r
-    //\r
-    pPort->State = PORT_STATE_CLOSE_STARTED;\r
-    DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-              "0x%08x: Port Close State: PORT_STATE_CLOSE_STARTED\r\n",\r
-              pPort ));\r
-    pPort->bCloseNow = bCloseNow;\r
-    pPort->DebugFlags = DebugFlags;\r
-\r
-    //\r
-    //  Determine if transmits are complete\r
-    //\r
-    Status = EslUdpPortCloseTxDone4 ( pPort );\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Port close state 3\r
-\r
-  Continue the close operation after the receive is complete.\r
-\r
-  @param [in] pPort       Address of the port structure.\r
-\r
-  @retval EFI_SUCCESS         The port is closed\r
-  @retval EFI_NOT_READY       The port is still closing\r
-  @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,\r
-                              most likely the routine was called already.\r
-\r
-**/\r
-EFI_STATUS\r
-EslUdpPortCloseRxDone4 (\r
-  IN DT_PORT * pPort\r
-  )\r
-{\r
-  PORT_STATE PortState;\r
-  DT_SOCKET * pSocket;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  Verify that the port is closing\r
-  //\r
-  Status = EFI_ALREADY_STARTED;\r
-  pSocket = pPort->pSocket;\r
-  pSocket->errno = EALREADY;\r
-  PortState = pPort->State;\r
-  if (( PORT_STATE_CLOSE_TX_DONE == PortState )\r
-    || ( PORT_STATE_CLOSE_DONE == PortState )) {\r
-    //\r
-    //  Determine if the receive operation is pending\r
-    //\r
-    Status = EFI_NOT_READY;\r
-    pSocket->errno = EAGAIN;\r
-    pUdp4 = &pPort->Context.Udp4;\r
-    if ( NULL == pUdp4->pReceivePending ) {\r
-      //\r
-      //  The receive operation is complete\r
-      //  Update the port state\r
-      //\r
-      pPort->State = PORT_STATE_CLOSE_RX_DONE;\r
-      DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                "0x%08x: Port Close State: PORT_STATE_CLOSE_RX_DONE\r\n",\r
-                pPort ));\r
-\r
-      //\r
-      //  The close operation has completed\r
-      //  Release the port resources\r
-      //\r
-      Status = EslUdpPortClose4 ( pPort );\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                "0x%08x: Port Close: Receive still pending!\r\n",\r
-                pPort ));\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Port close state 2\r
-\r
-  Continue the close operation after the transmission is complete.\r
-\r
-  @param [in] pPort       Address of the port structure.\r
-\r
-  @retval EFI_SUCCESS         The port is closed, not normally returned\r
-  @retval EFI_NOT_READY       The port is still closing\r
-  @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,\r
-                              most likely the routine was called already.\r
-\r
-**/\r
-EFI_STATUS\r
-EslUdpPortCloseTxDone4 (\r
-  IN DT_PORT * pPort\r
-  )\r
-{\r
-  DT_PACKET * pPacket;\r
-  DT_SOCKET * pSocket;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  EFI_UDP4_PROTOCOL * pUdp4Protocol;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  All transmissions are complete or must be stopped\r
-  //  Mark the port as TX complete\r
-  //\r
-  Status = EFI_ALREADY_STARTED;\r
-  if ( PORT_STATE_CLOSE_STARTED == pPort->State ) {\r
-    //\r
-    //  Verify that the transmissions are complete\r
-    //\r
-    pSocket = pPort->pSocket;\r
-    if ( pPort->bCloseNow\r
-         || ( EFI_SUCCESS != pSocket->TxError )\r
-         || ( 0 == pSocket->TxBytes )) {\r
-      //\r
-      //  Start the close operation on the port\r
-      //\r
-      pUdp4 = &pPort->Context.Udp4;\r
-      pUdp4Protocol = pUdp4->pProtocol;\r
-      if ( !pUdp4->bConfigured ) {\r
-        //\r
-        //  Skip the close operation since the port is not\r
-        //  configured\r
-        //\r
-        //  Update the port state\r
-        //\r
-        pPort->State = PORT_STATE_CLOSE_DONE;\r
-        DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                  "0x%08x: Port Close State: PORT_STATE_CLOSE_DONE\r\n",\r
-                  pPort ));\r
-        Status = EFI_SUCCESS;\r
-      }\r
-      else {\r
-        //\r
-        //  Update the port state\r
-        //\r
-        pPort->State = PORT_STATE_CLOSE_TX_DONE;\r
-        DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                  "0x%08x: Port Close State: PORT_STATE_CLOSE_TX_DONE\r\n",\r
-                  pPort ));\r
-\r
-        //\r
-        //  Empty the receive queue\r
-        //\r
-        while ( NULL != pSocket->pRxPacketListHead ) {\r
-          pPacket = pSocket->pRxPacketListHead;\r
-          pSocket->pRxPacketListHead = pPacket->pNext;\r
-          pSocket->RxBytes -= pPacket->Op.Udp4Rx.pRxData->DataLength;\r
-\r
-          //\r
-          //  Return the buffer to the UDP4 driver\r
-          //\r
-          gBS->SignalEvent ( pPacket->Op.Udp4Rx.pRxData->RecycleSignal );\r
-\r
-          //\r
-          //  Done with this packet\r
-          //\r
-          EslSocketPacketFree ( pPacket, DEBUG_RX );\r
-        }\r
-        pSocket->pRxPacketListTail = NULL;\r
-        ASSERT ( 0 == pSocket->RxBytes );\r
-\r
-        //\r
-        //  Reset the port, cancel the outstanding receive\r
-        //\r
-        Status = pUdp4Protocol->Configure ( pUdp4Protocol,\r
-                                            NULL );\r
-        if ( !EFI_ERROR ( Status )) {\r
-          DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,\r
-                    "0x%08x: Port reset\r\n",\r
-                    pPort ));\r
-\r
-          //\r
-          //  Free the receive packet\r
-          //\r
-          Status = gBS->CheckEvent ( pUdp4->RxToken.Event );\r
-          if ( EFI_SUCCESS != Status ) {\r
-            EslSocketPacketFree ( pUdp4->pReceivePending, DEBUG_CLOSE );\r
-            pUdp4->pReceivePending = NULL;\r
-            Status = EFI_SUCCESS;\r
-          }\r
-        }\r
-        else {\r
-          DEBUG (( DEBUG_ERROR | pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,\r
-                   "ERROR - Port 0x%08x reset failed, Status: %r\r\n",\r
-                   pPort,\r
-                   Status ));\r
-          ASSERT ( EFI_SUCCESS == Status );\r
-        }\r
-      }\r
-\r
-      //\r
-      //  Determine if the receive operation is pending\r
-      //\r
-      if ( !EFI_ERROR ( Status )) {\r
-        Status = EslUdpPortCloseRxDone4 ( pPort );\r
-      }\r
-    }\r
-    else {\r
-      //\r
-      //  Transmissions are still active, exit\r
-      //\r
-      DEBUG (( DEBUG_CLOSE | DEBUG_INFO,\r
-                "0x%08x: Port Close: Transmits are still pending!\r\n",\r
-                pPort ));\r
-      Status = EFI_NOT_READY;\r
-      pSocket->errno = EAGAIN;\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Connect to a remote system via the network.\r
-\r
-  The ::UdpConnectStart4= routine sets the remote address for the connection.\r
-\r
-  @param [in] pSocket         Address of the socket structure.\r
-\r
-  @param [in] pSockAddr       Network address of the remote system.\r
-    \r
-  @param [in] SockAddrLength  Length in bytes of the network address.\r
-  \r
-  @retval EFI_SUCCESS   The connection was successfully established.\r
-  @retval EFI_NOT_READY The connection is in progress, call this routine again.\r
-  @retval Others        The connection attempt failed.\r
-\r
- **/\r
-EFI_STATUS\r
-EslUdpConnect4 (\r
-  IN DT_SOCKET * pSocket,\r
-  IN const struct sockaddr * pSockAddr,\r
-  IN socklen_t SockAddrLength\r
-  )\r
-{\r
-  struct sockaddr_in LocalAddress;\r
-  DT_PORT * pPort;\r
-  struct sockaddr_in * pRemoteAddress;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume failure\r
-  //\r
-  Status = EFI_NETWORK_UNREACHABLE;\r
-  pSocket->errno = ENETUNREACH;\r
-\r
-  //\r
-  //  Get the address\r
-  //\r
-  pRemoteAddress = (struct sockaddr_in *)pSockAddr;\r
-\r
-  //\r
-  //  Validate the address length\r
-  //\r
-  if ( SockAddrLength >= ( sizeof ( *pRemoteAddress )\r
-                           - sizeof ( pRemoteAddress->sin_zero ))) {\r
-    //\r
-    //  Determine if BIND was already called\r
-    //\r
-    if ( NULL == pSocket->pPortList ) {\r
-      //\r
-      //  Allow any local port\r
-      //\r
-      ZeroMem ( &LocalAddress, sizeof ( LocalAddress ));\r
-      LocalAddress.sin_len = sizeof ( LocalAddress );\r
-      LocalAddress.sin_family = AF_INET;\r
-      Status = EslSocketBind ( &pSocket->SocketProtocol,\r
-                               (struct sockaddr *)&LocalAddress,\r
-                               LocalAddress.sin_len,\r
-                               &pSocket->errno );\r
-    }\r
-\r
-    //\r
-    //  Walk the list of ports\r
-    //\r
-    pPort = pSocket->pPortList;\r
-    while ( NULL != pPort ) {\r
-      //\r
-      //  Set the remote address\r
-      //\r
-      pUdp4 = &pPort->Context.Udp4;\r
-      pUdp4->ConfigData.RemoteAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );\r
-      pUdp4->ConfigData.RemoteAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );\r
-      pUdp4->ConfigData.RemoteAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );\r
-      pUdp4->ConfigData.RemoteAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );\r
-      pUdp4->ConfigData.RemotePort = SwapBytes16 ( pRemoteAddress->sin_port );\r
-\r
-      //\r
-      //  At least one path exists\r
-      //\r
-      Status = EFI_SUCCESS;\r
-      pSocket->errno = 0;\r
-\r
-      //\r
-      //  Set the next port\r
-      //\r
-      pPort = pPort->pLinkSocket;\r
-    }\r
-  }\r
-  else {\r
-    DEBUG (( DEBUG_CONNECT,\r
-              "ERROR - Invalid UDP4 address length: %d\r\n",\r
-              SockAddrLength ));\r
-    Status = EFI_INVALID_PARAMETER;\r
-    pSocket->errno = EINVAL;\r
-  }\r
-\r
-  //\r
-  //  Return the connect status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Get the local socket address\r
-\r
-  @param [in] pSocket             Address of the socket structure.\r
-\r
-  @param [out] pAddress           Network address to receive the local system address\r
-\r
-  @param [in,out] pAddressLength  Length of the local network address structure\r
-\r
-  @retval EFI_SUCCESS - Address available\r
-  @retval Other - Failed to get the address\r
-\r
-**/\r
-EFI_STATUS\r
-EslUdpGetLocalAddress4 (\r
-  IN DT_SOCKET * pSocket,\r
-  OUT struct sockaddr * pAddress,\r
-  IN OUT socklen_t * pAddressLength\r
-  )\r
-{\r
-  socklen_t LengthInBytes;\r
-  DT_PORT * pPort;\r
-  struct sockaddr_in * pLocalAddress;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  Verify that there is just a single connection\r
-  //\r
-  pPort = pSocket->pPortList;\r
-  if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {\r
-    //\r
-    //  Verify the address length\r
-    //\r
-    LengthInBytes = sizeof ( struct sockaddr_in );\r
-    if ( LengthInBytes <= * pAddressLength ) {\r
-      //\r
-      //  Return the local address\r
-      //\r
-      pUdp4 = &pPort->Context.Udp4;\r
-      pLocalAddress = (struct sockaddr_in *)pAddress;\r
-      ZeroMem ( pLocalAddress, LengthInBytes );\r
-      pLocalAddress->sin_family = AF_INET;\r
-      pLocalAddress->sin_len = (uint8_t)LengthInBytes;\r
-      pLocalAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.StationPort );\r
-      CopyMem ( &pLocalAddress->sin_addr,\r
-                &pUdp4->ConfigData.StationAddress.Addr[0],\r
-                sizeof ( pLocalAddress->sin_addr ));\r
-      pSocket->errno = 0;\r
-      Status = EFI_SUCCESS;\r
-    }\r
-    else {\r
-      pSocket->errno = EINVAL;\r
-      Status = EFI_INVALID_PARAMETER;\r
-    }\r
-  }\r
-  else {\r
-    pSocket->errno = ENOTCONN;\r
-    Status = EFI_NOT_STARTED;\r
-  }\r
-  \r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Get the remote socket address\r
-\r
-  @param [in] pSocket             Address of the socket structure.\r
-\r
-  @param [out] pAddress           Network address to receive the remote system address\r
-\r
-  @param [in,out] pAddressLength  Length of the remote network address structure\r
-\r
-  @retval EFI_SUCCESS - Address available\r
-  @retval Other - Failed to get the address\r
-\r
-**/\r
-EFI_STATUS\r
-EslUdpGetRemoteAddress4 (\r
-  IN DT_SOCKET * pSocket,\r
-  OUT struct sockaddr * pAddress,\r
-  IN OUT socklen_t * pAddressLength\r
-  )\r
-{\r
-  socklen_t LengthInBytes;\r
-  DT_PORT * pPort;\r
-  struct sockaddr_in * pRemoteAddress;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  Verify that there is just a single connection\r
-  //\r
-  pPort = pSocket->pPortList;\r
-  if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {\r
-    //\r
-    //  Verify the address length\r
-    //\r
-    LengthInBytes = sizeof ( struct sockaddr_in );\r
-    if ( LengthInBytes <= * pAddressLength ) {\r
-      //\r
-      //  Return the local address\r
-      //\r
-      pUdp4 = &pPort->Context.Udp4;\r
-      pRemoteAddress = (struct sockaddr_in *)pAddress;\r
-      ZeroMem ( pRemoteAddress, LengthInBytes );\r
-      pRemoteAddress->sin_family = AF_INET;\r
-      pRemoteAddress->sin_len = (uint8_t)LengthInBytes;\r
-      pRemoteAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.RemotePort );\r
-      CopyMem ( &pRemoteAddress->sin_addr,\r
-                &pUdp4->ConfigData.RemoteAddress.Addr[0],\r
-                sizeof ( pRemoteAddress->sin_addr ));\r
-      pSocket->errno = 0;\r
-      Status = EFI_SUCCESS;\r
-    }\r
-    else {\r
-      pSocket->errno = EINVAL;\r
-      Status = EFI_INVALID_PARAMETER;\r
-    }\r
-  }\r
-  else {\r
-    pSocket->errno = ENOTCONN;\r
-    Status = EFI_NOT_STARTED;\r
-  }\r
-  \r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Receive data from a network connection.\r
-\r
-  To minimize the number of buffer copies, the ::UdpRxComplete4\r
-  routine queues the UDP4 driver's buffer to a list of datagrams\r
-  waiting to be received.  The socket driver holds on to the\r
-  buffers from the UDP4 driver until the application layer requests\r
-  the data or the socket is closed.\r
-\r
-  The application calls this routine in the socket layer to\r
-  receive datagrams from one or more remote systems. This routine\r
-  removes the next available datagram from the list of datagrams\r
-  and copies the data from the UDP4 driver's buffer into the\r
-  application's buffer.  The UDP4 driver's buffer is then returned.\r
-\r
-  @param [in] pSocket         Address of a DT_SOCKET structure\r
-\r
-  @param [in] Flags           Message control flags\r
-\r
-  @param [in] BufferLength    Length of the the buffer\r
-\r
-  @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
-  @retval EFI_SUCCESS - Socket data successfully received\r
-\r
-**/\r
-EFI_STATUS\r
-EslUdpReceive4 (\r
-  IN DT_SOCKET * pSocket,\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
-  )\r
-{\r
-  socklen_t AddressLength;\r
-  size_t BytesToCopy;\r
-  size_t DataBytes;\r
-  UINT32 Fragment;\r
-  in_addr_t IpAddress;\r
-  size_t LengthInBytes;\r
-  UINT8 * pData;\r
-  DT_PACKET * pPacket;\r
-  DT_PORT * pPort;\r
-  struct sockaddr_in * pRemoteAddress;\r
-  EFI_UDP4_RECEIVE_DATA * pRxData;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  struct sockaddr_in RemoteAddress;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume failure\r
-  //\r
-  Status = EFI_UNSUPPORTED;\r
-  pSocket->errno = ENOTCONN;\r
-\r
-  //\r
-  //  Verify that the socket is connected\r
-  //\r
-  if (( SOCKET_STATE_CONNECTED == pSocket->State )\r
-    || ( PORT_STATE_RX_ERROR == pSocket->State )) {\r
-    //\r
-    //  Locate the port\r
-    //\r
-    pPort = pSocket->pPortList;\r
-    if ( NULL != pPort ) {\r
-      //\r
-      //  Determine if there is any data on the queue\r
-      //\r
-      pUdp4 = &pPort->Context.Udp4;\r
-      pPacket = pSocket->pRxPacketListHead;\r
-      if ( NULL != pPacket ) {\r
-        //\r
-        //  Validate the return address parameters\r
-        //\r
-        pRxData = pPacket->Op.Udp4Rx.pRxData;\r
-        if (( NULL == pAddress ) || ( NULL != pAddressLength )) {\r
-          //\r
-          //  Return the remote system address if requested\r
-          //\r
-          if ( NULL != pAddress ) {\r
-            //\r
-            //  Build the remote address\r
-            //\r
-            DEBUG (( DEBUG_RX,\r
-                      "Getting packet source address: %d.%d.%d.%d:%d\r\n",\r
-                      pRxData->UdpSession.SourceAddress.Addr[0],\r
-                      pRxData->UdpSession.SourceAddress.Addr[1],\r
-                      pRxData->UdpSession.SourceAddress.Addr[2],\r
-                      pRxData->UdpSession.SourceAddress.Addr[3],\r
-                      pRxData->UdpSession.SourcePort ));\r
-            ZeroMem ( &RemoteAddress, sizeof ( RemoteAddress ));\r
-            RemoteAddress.sin_len = sizeof ( RemoteAddress );\r
-            RemoteAddress.sin_family = AF_INET;\r
-            IpAddress = pRxData->UdpSession.SourceAddress.Addr[3];\r
-            IpAddress <<= 8;\r
-            IpAddress |= pRxData->UdpSession.SourceAddress.Addr[2];\r
-            IpAddress <<= 8;\r
-            IpAddress |= pRxData->UdpSession.SourceAddress.Addr[1];\r
-            IpAddress <<= 8;\r
-            IpAddress |= pRxData->UdpSession.SourceAddress.Addr[0];\r
-            RemoteAddress.sin_addr.s_addr = IpAddress;\r
-            RemoteAddress.sin_port = SwapBytes16 ( pRxData->UdpSession.SourcePort );\r
-\r
-            //\r
-            //  Copy the address\r
-            //\r
-            pRemoteAddress = (struct sockaddr_in *)pAddress;\r
-            AddressLength = sizeof ( *pRemoteAddress );\r
-            if ( AddressLength > *pAddressLength ) {\r
-              AddressLength = *pAddressLength;\r
-            }\r
-            CopyMem ( pRemoteAddress,\r
-                      &RemoteAddress,\r
-                      AddressLength );\r
-\r
-            //\r
-            //  Update the address length\r
-            //\r
-            *pAddressLength = AddressLength;\r
-          }\r
-\r
-          //\r
-          //  Reduce the buffer length if necessary\r
-          //\r
-          DataBytes = pRxData->DataLength;\r
-          if ( DataBytes < BufferLength ) {\r
-            BufferLength = DataBytes;\r
-          }\r
-\r
-          //\r
-          //  Copy the received data\r
-          //\r
-          LengthInBytes = 0;\r
-          Fragment = 0;\r
-          do {\r
-            //\r
-            //  Determine the amount of received data\r
-            //\r
-            pData = pRxData->FragmentTable[Fragment].FragmentBuffer;\r
-            BytesToCopy = pRxData->FragmentTable[Fragment].FragmentLength;\r
-            if (( BufferLength - LengthInBytes ) < BytesToCopy ) {\r
-              BytesToCopy = BufferLength - LengthInBytes;\r
-            }\r
-            LengthInBytes += BytesToCopy;\r
-\r
-            //\r
-            //  Move the data into the buffer\r
-            //\r
-            DEBUG (( DEBUG_RX,\r
-                      "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",\r
-                      pPort,\r
-                      pPacket,\r
-                      pBuffer,\r
-                      BytesToCopy ));\r
-            CopyMem ( pBuffer, pData, BytesToCopy );\r
-          } while ( BufferLength > LengthInBytes );\r
-\r
-          //\r
-          //  Determine if the data is being read\r
-          //\r
-          if ( 0 == ( Flags & MSG_PEEK )) {\r
-            //\r
-            //  Display for the bytes consumed\r
-            //\r
-            DEBUG (( DEBUG_RX,\r
-                      "0x%08x: Port account for 0x%08x bytes\r\n",\r
-                      pPort,\r
-                      BufferLength ));\r
-\r
-            //\r
-            //  All done with this packet\r
-            //  Account for any discarded data\r
-            //\r
-            pSocket->RxBytes -= DataBytes;\r
-            if ( 0 != ( DataBytes - BufferLength )) {\r
-              DEBUG (( DEBUG_RX,\r
-                        "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n",\r
-                        pPort,\r
-                        DataBytes - BufferLength ));\r
-            }\r
-\r
-            //\r
-            //  Remove this packet from the queue\r
-            //\r
-            pSocket->pRxPacketListHead = pPacket->pNext;\r
-            if ( NULL == pSocket->pRxPacketListHead ) {\r
-              pSocket->pRxPacketListTail = NULL;\r
-            }\r
-\r
-            //\r
-            //  Return this packet to the UDP4 driver\r
-            //\r
-            gBS->SignalEvent ( pRxData->RecycleSignal );\r
-\r
-            //\r
-            //  Move the packet to the free queue\r
-            //\r
-            pPacket->pNext = pSocket->pRxFree;\r
-            pSocket->pRxFree = pPacket;\r
-            DEBUG (( DEBUG_RX,\r
-                      "0x%08x: Port freeing packet 0x%08x\r\n",\r
-                      pPort,\r
-                      pPacket ));\r
-\r
-            //\r
-            //  Restart this receive operation if necessary\r
-            //\r
-            if (( NULL == pUdp4->pReceivePending )\r
-              && ( MAX_RX_DATA > pSocket->RxBytes )) {\r
-                EslUdpRxStart4 ( pPort );\r
-            }\r
-          }\r
-\r
-          //\r
-          //  Return the data length\r
-          //\r
-          *pDataLength = LengthInBytes;\r
-\r
-          //\r
-          //  Successful operation\r
-          //\r
-          Status = EFI_SUCCESS;\r
-          pSocket->errno = 0;\r
-        }\r
-        else {\r
-          //\r
-          //  Bad return address pointer and length\r
-          //\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EINVAL;\r
-        }\r
-      }\r
-      else {\r
-        //\r
-        //  The queue is empty\r
-        //  Determine if it is time to return the receive error\r
-        //\r
-        if ( EFI_ERROR ( pSocket->RxError )) {\r
-          Status = pSocket->RxError;\r
-          switch ( Status ) {\r
-          default:\r
-            pSocket->errno = EIO;\r
-            break;\r
-\r
-          case EFI_HOST_UNREACHABLE:\r
-            pSocket->errno = EHOSTUNREACH;\r
-            break;\r
-\r
-          case EFI_NETWORK_UNREACHABLE:\r
-            pSocket->errno = ENETUNREACH;\r
-            break;\r
-\r
-          case EFI_PORT_UNREACHABLE:\r
-            pSocket->errno = EPROTONOSUPPORT;\r
-            break;\r
-\r
-          case EFI_PROTOCOL_UNREACHABLE:\r
-            pSocket->errno = ENOPROTOOPT;\r
-            break;\r
-          }\r
-          pSocket->RxError = EFI_SUCCESS;\r
-        }\r
-        else {\r
-          Status = EFI_NOT_READY;\r
-          pSocket->errno = EAGAIN;\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Cancel the receive operations\r
-\r
-  @param [in] pSocket         Address of a DT_SOCKET structure\r
-  \r
-  @retval EFI_SUCCESS - The cancel was successful\r
-\r
- **/\r
-EFI_STATUS\r
-EslUdpRxCancel4 (\r
-  IN DT_SOCKET * pSocket\r
-  )\r
-{\r
-  DT_PACKET * pPacket;\r
-  DT_PORT * pPort;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  EFI_UDP4_PROTOCOL * pUdp4Protocol;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume failure\r
-  //\r
-  Status = EFI_NOT_FOUND;\r
-\r
-  //\r
-  //  Locate the port\r
-  //\r
-  pPort = pSocket->pPortList;\r
-  if ( NULL != pPort ) {\r
-    //\r
-    //  Determine if a receive is pending\r
-    //\r
-    pUdp4 = &pPort->Context.Udp4;\r
-    pPacket = pUdp4->pReceivePending;\r
-    if ( NULL != pPacket ) {\r
-      //\r
-      //  Attempt to cancel the receive operation\r
-      //\r
-      pUdp4Protocol = pUdp4->pProtocol;\r
-      Status = pUdp4Protocol->Cancel ( pUdp4Protocol,\r
-                                       &pUdp4->RxToken );\r
-      if ( EFI_NOT_FOUND == Status ) {\r
-        //\r
-        //  The receive is complete\r
-        //\r
-        Status = EFI_SUCCESS;\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Process the receive completion\r
-\r
-  Keep the UDP4 driver's buffer and append it to the list of\r
-  datagrams for the application to receive.  The UDP4 driver's\r
-  buffer will be returned by either ::UdpReceive4 or\r
-  ::UdpPortCloseTxDone4.\r
-\r
-  @param  Event         The receive completion event\r
-\r
-  @param  pPort         The DT_PORT structure address\r
-\r
-**/\r
-VOID\r
-EslUdpRxComplete4 (\r
-  IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
-  )\r
-{\r
-  size_t LengthInBytes;\r
-  DT_PACKET * pPacket;\r
-  DT_PACKET * pPrevious;\r
-  EFI_UDP4_RECEIVE_DATA * pRxData;\r
-  DT_SOCKET * pSocket;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  EFI_STATUS Status;\r
-  \r
-  DBG_ENTER ( );\r
-  \r
-  //\r
-  //  Mark this receive complete\r
-  //\r
-  pUdp4 = &pPort->Context.Udp4;\r
-  pPacket = pUdp4->pReceivePending;\r
-  pUdp4->pReceivePending = NULL;\r
-  \r
-  //\r
-  //  Determine if this receive was successful\r
-  //\r
-  pSocket = pPort->pSocket;\r
-  Status = pUdp4->RxToken.Status;\r
-  if (( !EFI_ERROR ( Status )) && ( !pSocket->bRxDisable )) {\r
-    pRxData = pUdp4->RxToken.Packet.RxData;\r
-    if ( PORT_STATE_CLOSE_STARTED >= pPort->State ) {\r
-      //\r
-      //  Save the data in the packet\r
-      //\r
-      pPacket->Op.Udp4Rx.pRxData = pRxData;\r
-\r
-      //\r
-      //  Queue this packet\r
-      //\r
-      pPrevious = pSocket->pRxPacketListTail;\r
-      if ( NULL == pPrevious ) {\r
-        pSocket->pRxPacketListHead = pPacket;\r
-      }\r
-      else {\r
-        pPrevious->pNext = pPacket;\r
-      }\r
-      pSocket->pRxPacketListTail = pPacket;\r
-\r
-      //\r
-      //  Account for the normal data\r
-      //\r
-      LengthInBytes = pRxData->DataLength;\r
-      pSocket->RxBytes += LengthInBytes;\r
-\r
-      //\r
-      //  Log the received data\r
-      //\r
-      DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-                "Received packet from: %d.%d.%d.%d:%d\r\n",\r
-                pRxData->UdpSession.SourceAddress.Addr[0],\r
-                pRxData->UdpSession.SourceAddress.Addr[1],\r
-                pRxData->UdpSession.SourceAddress.Addr[2],\r
-                pRxData->UdpSession.SourceAddress.Addr[3],\r
-                pRxData->UdpSession.SourcePort ));\r
-      DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-                "Received packet sent to: %d.%d.%d.%d:%d\r\n",\r
-                pRxData->UdpSession.DestinationAddress.Addr[0],\r
-                pRxData->UdpSession.DestinationAddress.Addr[1],\r
-                pRxData->UdpSession.DestinationAddress.Addr[2],\r
-                pRxData->UdpSession.DestinationAddress.Addr[3],\r
-                pRxData->UdpSession.DestinationPort ));\r
-      DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-                "0x%08x: Packet queued on port 0x%08x with 0x%08x bytes of data\r\n",\r
-                pPacket,\r
-                pPort,\r
-                LengthInBytes ));\r
-\r
-      //\r
-      //  Attempt to restart this receive operation\r
-      //\r
-      if ( pSocket->MaxRxBuf > pSocket->RxBytes ) {\r
-        EslUdpRxStart4 ( pPort );\r
-      }\r
-      else {\r
-        DEBUG (( DEBUG_RX,\r
-                  "0x%08x: Port RX suspended, 0x%08x bytes queued\r\n",\r
-                  pPort,\r
-                  pSocket->RxBytes ));\r
-      }\r
-    }\r
-    else {\r
-      //\r
-      //  The port is being closed\r
-      //  Return the buffer to the UDP4 driver\r
-      //\r
-      gBS->SignalEvent ( pRxData->RecycleSignal );\r
-\r
-      //\r
-      //  Free the packet\r
-      //\r
-      EslSocketPacketFree ( pPacket, DEBUG_RX );\r
-    }\r
-  }\r
-  else\r
-  {\r
-    DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-              "ERROR - Receiving packet 0x%08x, on port 0x%08x, Status:%r\r\n",\r
-              pPacket,\r
-              pPort,\r
-              Status ));\r
-  \r
-    //\r
-    //  Receive error, free the packet save the error\r
-    //\r
-    EslSocketPacketFree ( pPacket, DEBUG_RX );\r
-    if ( !EFI_ERROR ( pSocket->RxError )) {\r
-      pSocket->RxError = Status;\r
-    }\r
-  \r
-    //\r
-    //  Update the port state\r
-    //\r
-    if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {\r
-      EslUdpPortCloseRxDone4 ( pPort );\r
-    }\r
-    else {\r
-      if ( EFI_ERROR ( Status )) {\r
-        pPort->State = PORT_STATE_RX_ERROR;\r
-      }\r
-    }\r
-  }\r
-  \r
+  pUdp4 = &pPort->Context.Udp4;\r
+  pRemoteAddress = (struct sockaddr_in *)pAddress;\r
+  pRemoteAddress->sin_family = AF_INET;\r
+  pRemoteAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.RemotePort );\r
+  CopyMem ( &pRemoteAddress->sin_addr,\r
+            &pUdp4->ConfigData.RemoteAddress.Addr[0],\r
+            sizeof ( pRemoteAddress->sin_addr ));\r
+\r
   DBG_EXIT ( );\r
 }\r
 \r
 \r
 /**\r
-  Start a receive operation\r
+  Set the remote address\r
+\r
+  This routine sets the remote address in the port.\r
+\r
+  This routine is called by ::EslSocketConnect to specify the\r
+  remote network address.\r
+\r
+  @param [in] pPort           Address of an ::ESL_PORT structure.\r
+\r
+  @param [in] pSockAddr       Network address of the remote system.\r
+\r
+  @param [in] SockAddrLength  Length in bytes of the network address.\r
 \r
-  @param [in] pPort       Address of the DT_PORT structure.\r
+  @retval EFI_SUCCESS     The operation was successful\r
 \r
  **/\r
-VOID\r
-EslUdpRxStart4 (\r
-  IN DT_PORT * pPort\r
+EFI_STATUS\r
+EslUdp4RemoteAddressSet (\r
+  IN ESL_PORT * pPort,\r
+  IN CONST struct sockaddr * pSockAddr,\r
+  IN socklen_t SockAddrLength\r
   )\r
 {\r
-  DT_PACKET * pPacket;\r
-  DT_SOCKET * pSocket;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  EFI_UDP4_PROTOCOL * pUdp4Protocol;\r
+  CONST struct sockaddr_in * pRemoteAddress;\r
+  ESL_UDP4_CONTEXT * pUdp4;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Determine if a receive is already pending\r
+  //  Set the remote address\r
   //\r
-  Status = EFI_SUCCESS;\r
-  pPacket = NULL;\r
-  pSocket = pPort->pSocket;\r
   pUdp4 = &pPort->Context.Udp4;\r
-  if ( !EFI_ERROR ( pPort->pSocket->RxError )) {\r
-    if (( NULL == pUdp4->pReceivePending )\r
-      && ( PORT_STATE_CLOSE_STARTED > pPort->State )) {\r
-      //\r
-      //  Determine if there are any free packets\r
-      //\r
-      pPacket = pSocket->pRxFree;\r
-      if ( NULL != pPacket ) {\r
-        //\r
-        //  Remove this packet from the free list\r
-        //\r
-        pSocket->pRxFree = pPacket->pNext;\r
-        DEBUG (( DEBUG_RX,\r
-                  "0x%08x: Port removed packet 0x%08x from free list\r\n",\r
-                  pPort,\r
-                  pPacket ));\r
-      }\r
-      else {\r
-        //\r
-        //  Allocate a packet structure\r
-        //\r
-        Status = EslSocketPacketAllocate ( &pPacket,\r
-                                           sizeof ( pPacket->Op.Udp4Rx ),\r
-                                           DEBUG_RX );\r
-        if ( EFI_ERROR ( Status )) {\r
-          pPacket = NULL;\r
-          DEBUG (( DEBUG_ERROR | DEBUG_RX,\r
-                    "0x%08x: Port failed to allocate RX packet, Status: %r\r\n",\r
-                    pPort,\r
-                    Status ));\r
-        }\r
-      }\r
-\r
-      //\r
-      //  Determine if a packet is available\r
-      //\r
-      if ( NULL != pPacket ) {\r
-        //\r
-        //  Initialize the buffer for receive\r
-        //\r
-        pPacket->pNext = NULL;\r
-        pPacket->Op.Udp4Rx.pRxData = NULL;\r
-        pUdp4->RxToken.Packet.RxData = NULL;\r
-        pUdp4->pReceivePending = pPacket;\r
-\r
-        //\r
-        //  Start the receive on the packet\r
-        //\r
-        pUdp4Protocol = pUdp4->pProtocol;\r
-        Status = pUdp4Protocol->Receive ( pUdp4Protocol,\r
-                                          &pUdp4->RxToken );\r
-        if ( !EFI_ERROR ( Status )) {\r
-          DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-                    "0x%08x: Packet receive pending on port 0x%08x\r\n",\r
-                    pPacket,\r
-                    pPort ));\r
-        }\r
-        else {\r
-          DEBUG (( DEBUG_RX | DEBUG_INFO,\r
-                    "ERROR - Failed to post a receive on port 0x%08x, Status: %r\r\n",\r
-                    pPort,\r
-                    Status ));\r
-          if ( !EFI_ERROR ( pSocket->RxError )) {\r
-            //\r
-            //  Save the error status\r
-            //\r
-            pSocket->RxError = Status;\r
-          }\r
-\r
-          //\r
-          //  Free the packet\r
-          //\r
-          pUdp4->pReceivePending = NULL;\r
-          pPacket->pNext = pSocket->pRxFree;\r
-          pSocket->pRxFree = pPacket;\r
-        }\r
-      }\r
-    }\r
-  }\r
+  pRemoteAddress = (struct sockaddr_in *)pSockAddr;\r
+  pUdp4->ConfigData.RemoteAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );\r
+  pUdp4->ConfigData.RemoteAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );\r
+  pUdp4->ConfigData.RemoteAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );\r
+  pUdp4->ConfigData.RemoteAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );\r
+  pUdp4->ConfigData.RemotePort = SwapBytes16 ( pRemoteAddress->sin_port );\r
+  pPort->pSocket->bAddressSet = TRUE;\r
+  Status = EFI_SUCCESS;\r
 \r
-  DBG_EXIT ( );\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
 }\r
 \r
 \r
 /**\r
-  Shutdown the UDP4 service.\r
+  Process the receive completion\r
+\r
+  This routine keeps the UDPv4 driver's buffer and queues it in\r
+  in FIFO order to the data queue.  The UDP4 driver's buffer will\r
+  be returned by either ::EslUdp4Receive or ::EslSocketPortCloseTxDone.\r
+  See the \ref ReceiveEngine section.\r
 \r
-  This routine undoes the work performed by ::UdpInitialize4.\r
+  This routine is called by the UDPv4 driver when data is\r
+  received.\r
 \r
-  @param [in] pService        DT_SERVICE structure address\r
+  @param [in] Event     The receive completion event\r
+\r
+  @param [in] pIo       Address of an ::ESL_IO_MGMT structure\r
 \r
 **/\r
 VOID\r
-EFIAPI\r
-EslUdpShutdown4 (\r
-  IN DT_SERVICE * pService\r
+EslUdp4RxComplete (\r
+  IN EFI_EVENT Event,\r
+  IN ESL_IO_MGMT * pIo\r
   )\r
 {\r
-  DT_LAYER * pLayer;\r
-  DT_PORT * pPort;\r
-  DT_SERVICE * pPreviousService;\r
-\r
+  size_t LengthInBytes;\r
+  ESL_PACKET * pPacket;\r
+  EFI_UDP4_RECEIVE_DATA * pRxData;\r
+  EFI_STATUS Status;\r
+  \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Verify the socket layer synchronization\r
+  //  Get the operation status.\r
   //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-\r
+  Status = pIo->Token.Udp4Rx.Status;\r
+  \r
   //\r
-  //  Walk the list of ports\r
+  //  Get the packet length\r
   //\r
-  do {\r
-    pPort = pService->pPortList;\r
-    if ( NULL != pPort ) {\r
-      //\r
-      //  Remove the port from the port list\r
-      //\r
-      pService->pPortList = pPort->pLinkService;\r
-\r
-      //\r
-      //  Close the port\r
-      // TODO: Fix this\r
-      //\r
-//      pPort->pfnClosePort ( pPort, 0 );\r
-    }\r
-  } while ( NULL != pPort );\r
+  pRxData = pIo->Token.Udp4Rx.Packet.RxData;\r
+  LengthInBytes = pRxData->DataLength;\r
 \r
   //\r
-  //  Remove the service from the service list\r
+  //      +--------------------+   +-----------------------+\r
+  //      | ESL_IO_MGMT        |   |      Data Buffer      |\r
+  //      |                    |   |     (Driver owned)    |\r
+  //      |    +---------------+   +-----------------------+\r
+  //      |    | Token         |               ^\r
+  //      |    |      Rx Event |               |\r
+  //      |    |               |   +-----------------------+\r
+  //      |    |        RxData --> | EFI_UDP4_RECEIVE_DATA |\r
+  //      +----+---------------+   |     (Driver owned)    |\r
+  //                               +-----------------------+\r
+  //      +--------------------+               ^\r
+  //      | ESL_PACKET         |               .\r
+  //      |                    |               .\r
+  //      |    +---------------+               .\r
+  //      |    |       pRxData --> NULL  .......\r
+  //      +----+---------------+\r
   //\r
-  pLayer = &mEslLayer;\r
-  pPreviousService = pLayer->pUdp4List;\r
-  if ( pService == pPreviousService ) {\r
-    //\r
-    //  Remove the service from the beginning of the list\r
-    //\r
-    pLayer->pUdp4List = pService->pNext;\r
-  }\r
-  else {\r
-    //\r
-    //  Remove the service from the middle of the list\r
-    //\r
-    while ( NULL != pPreviousService ) {\r
-      if ( pService == pPreviousService->pNext ) {\r
-        pPreviousService->pNext = pService->pNext;\r
-        break;\r
-      }\r
-    }\r
-  }\r
+  //\r
+  //  Save the data in the packet\r
+  //\r
+  pPacket = pIo->pPacket;\r
+  pPacket->Op.Udp4Rx.pRxData = pRxData;\r
 \r
+  //\r
+  //  Complete this request\r
+  //\r
+  EslSocketRxComplete ( pIo, Status, LengthInBytes, FALSE );\r
   DBG_EXIT ( );\r
 }\r
 \r
 \r
 /**\r
-  Determine if the sockedt is configured.\r
+  Determine if the socket is configured.\r
 \r
+  This routine uses the flag ESL_SOCKET::bConfigured to determine\r
+  if the network layer's configuration routine has been called.\r
+  This routine calls the bind and configuration routines if they\r
+  were not already called.  After the port is configured, the\r
+  \ref ReceiveEngine is started.\r
+\r
+  This routine is called by EslSocketIsConfigured to verify\r
+  that the socket is configured.\r
+\r
+  @param [in] pSocket         Address of an ::ESL_SOCKET structure\r
 \r
-  @param [in] pSocket         Address of a DT_SOCKET structure\r
-  \r
   @retval EFI_SUCCESS - The port is connected\r
   @retval EFI_NOT_STARTED - The port is not connected\r
 \r
  **/\r
  EFI_STATUS\r
- EslUdpSocketIsConfigured4 (\r
-  IN DT_SOCKET * pSocket\r
+ EslUdp4SocketIsConfigured (\r
+  IN ESL_SOCKET * pSocket\r
   )\r
 {\r
-  DT_PORT * pPort;\r
-  DT_PORT * pNextPort;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
+  EFI_UDP4_CONFIG_DATA * pConfigData;\r
+  ESL_PORT * pPort;\r
+  ESL_PORT * pNextPort;\r
+  ESL_UDP4_CONTEXT * pUdp4;\r
   EFI_UDP4_PROTOCOL * pUdp4Protocol;\r
   EFI_STATUS Status;\r
   struct sockaddr_in LocalAddress;\r
@@ -1915,14 +591,16 @@ EslUdpShutdown4 (
     //\r
     //  Fill in the port list if necessary\r
     //\r
+    pSocket->errno = ENETDOWN;\r
     if ( NULL == pSocket->pPortList ) {\r
       LocalAddress.sin_len = sizeof ( LocalAddress );\r
       LocalAddress.sin_family = AF_INET;\r
       LocalAddress.sin_addr.s_addr = 0;\r
       LocalAddress.sin_port = 0;\r
-      Status = EslUdpBind4 ( pSocket,\r
-                             (struct sockaddr *)&LocalAddress,\r
-                             LocalAddress.sin_len );\r
+      Status = EslSocketBind ( &pSocket->SocketProtocol,\r
+                               (struct sockaddr *)&LocalAddress,\r
+                               LocalAddress.sin_len,\r
+                               &pSocket->errno );\r
     }\r
 \r
     //\r
@@ -1935,55 +613,93 @@ EslUdpShutdown4 (
       //\r
       pNextPort = pPort->pLinkSocket;\r
       pUdp4 = &pPort->Context.Udp4;\r
-      pUdp4Protocol = pUdp4->pProtocol;\r
+      pUdp4Protocol = pPort->pProtocol.UDPv4;\r
+      pConfigData = &pUdp4->ConfigData;\r
+      DEBUG (( DEBUG_TX,\r
+                "0x%08x: pPort Configuring for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n",\r
+                pPort,\r
+                pConfigData->StationAddress.Addr[0],\r
+                pConfigData->StationAddress.Addr[1],\r
+                pConfigData->StationAddress.Addr[2],\r
+                pConfigData->StationAddress.Addr[3],\r
+                pConfigData->StationPort,\r
+                pConfigData->RemoteAddress.Addr[0],\r
+                pConfigData->RemoteAddress.Addr[1],\r
+                pConfigData->RemoteAddress.Addr[2],\r
+                pConfigData->RemoteAddress.Addr[3],\r
+                pConfigData->RemotePort ));\r
       Status = pUdp4Protocol->Configure ( pUdp4Protocol,\r
-                                          &pUdp4->ConfigData );\r
+                                          pConfigData );\r
+      if ( !EFI_ERROR ( Status )) {\r
+        //\r
+        //  Update the configuration data\r
+        //\r
+        Status = pUdp4Protocol->GetModeData ( pUdp4Protocol,\r
+                                              pConfigData,\r
+                                              NULL,\r
+                                              NULL,\r
+                                              NULL );\r
+      }\r
       if ( EFI_ERROR ( Status )) {\r
-        DEBUG (( DEBUG_LISTEN,\r
-                  "ERROR - Failed to configure the Udp4 port, Status: %r\r\n",\r
-                  Status ));\r
-        switch ( Status ) {\r
-        case EFI_ACCESS_DENIED:\r
-          pSocket->errno = EACCES;\r
-          break;\r
+        if ( !pSocket->bConfigured ) {\r
+          DEBUG (( DEBUG_LISTEN,\r
+                    "ERROR - Failed to configure the Udp4 port, Status: %r\r\n",\r
+                    Status ));\r
+          switch ( Status ) {\r
+          case EFI_ACCESS_DENIED:\r
+            pSocket->errno = EACCES;\r
+            break;\r
 \r
-        default:\r
-        case EFI_DEVICE_ERROR:\r
-          pSocket->errno = EIO;\r
-          break;\r
+          default:\r
+          case EFI_DEVICE_ERROR:\r
+            pSocket->errno = EIO;\r
+            break;\r
 \r
-        case EFI_INVALID_PARAMETER:\r
-          pSocket->errno = EADDRNOTAVAIL;\r
-          break;\r
+          case EFI_INVALID_PARAMETER:\r
+            pSocket->errno = EADDRNOTAVAIL;\r
+            break;\r
 \r
-        case EFI_NO_MAPPING:\r
-          pSocket->errno = EAFNOSUPPORT;\r
-          break;\r
+          case EFI_NO_MAPPING:\r
+            pSocket->errno = EAFNOSUPPORT;\r
+            break;\r
 \r
-        case EFI_OUT_OF_RESOURCES:\r
-          pSocket->errno = ENOBUFS;\r
-          break;\r
+          case EFI_OUT_OF_RESOURCES:\r
+            pSocket->errno = ENOBUFS;\r
+            break;\r
 \r
-        case EFI_UNSUPPORTED:\r
-          pSocket->errno = EOPNOTSUPP;\r
-          break;\r
+          case EFI_UNSUPPORTED:\r
+            pSocket->errno = EOPNOTSUPP;\r
+            break;\r
+          }\r
         }\r
       }\r
       else {\r
-        DEBUG (( DEBUG_LISTEN,\r
-                  "0x%08x: Port configured\r\n",\r
-                  pPort ));\r
-        pUdp4->bConfigured = TRUE;\r
+        DEBUG (( DEBUG_TX,\r
+                  "0x%08x: pPort Configured for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n",\r
+                  pPort,\r
+                  pConfigData->StationAddress.Addr[0],\r
+                  pConfigData->StationAddress.Addr[1],\r
+                  pConfigData->StationAddress.Addr[2],\r
+                  pConfigData->StationAddress.Addr[3],\r
+                  pConfigData->StationPort,\r
+                  pConfigData->RemoteAddress.Addr[0],\r
+                  pConfigData->RemoteAddress.Addr[1],\r
+                  pConfigData->RemoteAddress.Addr[2],\r
+                  pConfigData->RemoteAddress.Addr[3],\r
+                  pConfigData->RemotePort ));\r
+        pPort->bConfigured = TRUE;\r
+        pSocket->bConfigured = TRUE;\r
 \r
         //\r
         //  Start the first read on the port\r
         //\r
-        EslUdpRxStart4 ( pPort );\r
+        EslSocketRxStart ( pPort );\r
 \r
         //\r
         //  The socket is connected\r
         //\r
         pSocket->State = SOCKET_STATE_CONNECTED;\r
+        pSocket->errno = 0;\r
       }\r
 \r
       //\r
@@ -1991,21 +707,12 @@ EslUdpShutdown4 (
       //\r
       pPort = pNextPort;\r
     }\r
-\r
-    //\r
-    //  Determine the configuration status\r
-    //\r
-    if ( NULL != pSocket->pPortList ) {\r
-      pSocket->bConfigured = TRUE;\r
-    }\r
   }\r
 \r
   //\r
   //  Determine the socket configuration status\r
   //\r
-  if ( !EFI_ERROR ( Status )) {\r
-    Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED;\r
-  }\r
+  Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED;\r
   \r
   //\r
   //  Return the port connected state.\r
@@ -2018,10 +725,15 @@ EslUdpShutdown4 (
 /**\r
   Buffer data for transmission over a network connection.\r
 \r
-  This routine is called by the socket layer API to buffer\r
+  This routine buffers data for the transmit engine in the normal\r
+  data queue.  When the \ref TransmitEngine has resources, this\r
+  routine will start the transmission of the next buffer on the\r
+  network connection.\r
+\r
+  This routine is called by ::EslSocketTransmit to buffer\r
   data for transmission.  The data is copied into a local buffer\r
   freeing the application buffer for reuse upon return.  When\r
-  necessary, this routine will start the transmit engine that\r
+  necessary, this routine starts the transmit engine that\r
   performs the data transmission on the network connection.  The\r
   transmit engine transmits the data a packet at a time over the\r
   network connection.\r
@@ -2030,7 +742,7 @@ EslUdpShutdown4 (
   during the close operation.  Only buffering errors are returned\r
   during the current transmission attempt.\r
 \r
-  @param [in] pSocket         Address of a DT_SOCKET structure\r
+  @param [in] pSocket         Address of an ::ESL_SOCKET structure\r
 \r
   @param [in] Flags           Message control flags\r
 \r
@@ -2048,8 +760,8 @@ EslUdpShutdown4 (
 \r
 **/\r
 EFI_STATUS\r
-EslUdpTxBuffer4 (\r
-  IN DT_SOCKET * pSocket,\r
+EslUdp4TxBuffer (\r
+  IN ESL_SOCKET * pSocket,\r
   IN int Flags,\r
   IN size_t BufferLength,\r
   IN CONST UINT8 * pBuffer,\r
@@ -2058,15 +770,13 @@ EslUdpTxBuffer4 (
   IN socklen_t AddressLength\r
   )\r
 {\r
-  DT_PACKET * pPacket;\r
-  DT_PACKET * pPreviousPacket;\r
-  DT_PACKET ** ppPacket;\r
-  DT_PORT * pPort;\r
+  ESL_PACKET * pPacket;\r
+  ESL_PACKET * pPreviousPacket;\r
+  ESL_PORT * pPort;\r
   const struct sockaddr_in * pRemoteAddress;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  EFI_UDP4_COMPLETION_TOKEN * pToken;\r
+  ESL_UDP4_CONTEXT * pUdp4;\r
   size_t * pTxBytes;\r
-  DT_UDP4_TX_DATA * pTxData;\r
+  ESL_UDP4_TX_DATA * pTxData;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
 \r
@@ -2077,30 +787,28 @@ EslUdpTxBuffer4 (
   //\r
   Status = EFI_UNSUPPORTED;\r
   pSocket->errno = ENOTCONN;\r
-  * pDataLength = 0;\r
+  *pDataLength = 0;\r
 \r
   //\r
   //  Verify that the socket is connected\r
   //\r
   if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
     //\r
-    //  Locate the port\r
+    //  Verify that there is enough room to buffer another\r
+    //  transmit operation\r
     //\r
-    pPort = pSocket->pPortList;\r
-    if ( NULL != pPort ) {\r
+    pTxBytes = &pSocket->TxBytes;\r
+    if ( pSocket->MaxTxBuf > *pTxBytes ) {\r
       //\r
-      //  Determine the queue head\r
+      //  Locate the port\r
       //\r
-      pUdp4 = &pPort->Context.Udp4;\r
-      ppPacket = &pUdp4->pTxPacket;\r
-      pToken = &pUdp4->TxToken;\r
-      pTxBytes = &pSocket->TxBytes;\r
+      pPort = pSocket->pPortList;\r
+      while ( NULL != pPort ) {\r
+        //\r
+        //  Determine the queue head\r
+        //\r
+        pUdp4 = &pPort->Context.Udp4;\r
 \r
-      //\r
-      //  Verify that there is enough room to buffer another\r
-      //  transmit operation\r
-      //\r
-      if ( pSocket->MaxTxBuf > *pTxBytes ) {\r
         //\r
         //  Attempt to allocate the packet\r
         //\r
@@ -2108,6 +816,7 @@ EslUdpTxBuffer4 (
                                            sizeof ( pPacket->Op.Udp4Tx )\r
                                            - sizeof ( pPacket->Op.Udp4Tx.Buffer )\r
                                            + BufferLength,\r
+                                           0,\r
                                            DEBUG_TX );\r
         if ( !EFI_ERROR ( Status )) {\r
           //\r
@@ -2120,16 +829,18 @@ EslUdpTxBuffer4 (
           pTxData->TxData.FragmentCount = 1;\r
           pTxData->TxData.FragmentTable[0].FragmentLength = (UINT32) BufferLength;\r
           pTxData->TxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Udp4Tx.Buffer[0];\r
+          pTxData->RetransmitCount = 0;\r
 \r
           //\r
           //  Set the remote system address if necessary\r
           //\r
+          pTxData->TxData.UdpSessionData = NULL;\r
           if ( NULL != pAddress ) {\r
             pRemoteAddress = (const struct sockaddr_in *)pAddress;\r
-            pTxData->Session.SourceAddress.Addr[0] = 0;\r
-            pTxData->Session.SourceAddress.Addr[1] = 0;\r
-            pTxData->Session.SourceAddress.Addr[2] = 0;\r
-            pTxData->Session.SourceAddress.Addr[3] = 0;\r
+            pTxData->Session.SourceAddress.Addr[0] = pUdp4->ConfigData.StationAddress.Addr[0];\r
+            pTxData->Session.SourceAddress.Addr[1] = pUdp4->ConfigData.StationAddress.Addr[1];\r
+            pTxData->Session.SourceAddress.Addr[2] = pUdp4->ConfigData.StationAddress.Addr[2];\r
+            pTxData->Session.SourceAddress.Addr[3] = pUdp4->ConfigData.StationAddress.Addr[3];\r
             pTxData->Session.SourcePort = 0;\r
             pTxData->Session.DestinationAddress.Addr[0] = (UINT8)pRemoteAddress->sin_addr.s_addr;\r
             pTxData->Session.DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );\r
@@ -2156,58 +867,62 @@ EslUdpTxBuffer4 (
           RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
 \r
           //\r
-          //  Stop transmission after an error\r
+          //  Display the request\r
           //\r
-          if ( !EFI_ERROR ( pSocket->TxError )) {\r
-            //\r
-            //  Display the request\r
-            //\r
-            DEBUG (( DEBUG_TX,\r
-                      "Send %d %s bytes from 0x%08x\r\n",\r
-                      BufferLength,\r
-                      pBuffer ));\r
-\r
-            //\r
-            //  Queue the data for transmission\r
-            //\r
-            pPacket->pNext = NULL;\r
-            pPreviousPacket = pSocket->pTxPacketListTail;\r
-            if ( NULL == pPreviousPacket ) {\r
-              pSocket->pTxPacketListHead = pPacket;\r
-            }\r
-            else {\r
-              pPreviousPacket->pNext = pPacket;\r
-            }\r
-            pSocket->pTxPacketListTail = pPacket;\r
-            DEBUG (( DEBUG_TX,\r
-                      "0x%08x: Packet on transmit list\r\n",\r
-                      pPacket ));\r
-\r
-            //\r
-            //  Account for the buffered data\r
-            //\r
-            *pTxBytes += BufferLength;\r
-            *pDataLength = BufferLength;\r
+          DEBUG (( DEBUG_TX,\r
+                    "Send %d bytes from 0x%08x to %d.%d.%d.%d:%d\r\n",\r
+                    BufferLength,\r
+                    pBuffer,\r
+                    pTxData->Session.DestinationAddress.Addr[0],\r
+                    pTxData->Session.DestinationAddress.Addr[1],\r
+                    pTxData->Session.DestinationAddress.Addr[2],\r
+                    pTxData->Session.DestinationAddress.Addr[3],\r
+                    pTxData->Session.DestinationPort ));\r
 \r
-            //\r
-            //  Start the transmit engine if it is idle\r
-            //\r
-            if ( NULL == pUdp4->pTxPacket ) {\r
-              EslUdpTxStart4 ( pSocket->pPortList );\r
-            }\r
+          //\r
+          //  Queue the data for transmission\r
+          //\r
+          pPacket->pNext = NULL;\r
+          pPreviousPacket = pSocket->pTxPacketListTail;\r
+          if ( NULL == pPreviousPacket ) {\r
+            pSocket->pTxPacketListHead = pPacket;\r
           }\r
           else {\r
-            //\r
-            //  Previous transmit error\r
-            //  Stop transmission\r
-            //\r
-            Status = pSocket->TxError;\r
-            pSocket->errno = EIO;\r
+            pPreviousPacket->pNext = pPacket;\r
+          }\r
+          pSocket->pTxPacketListTail = pPacket;\r
+          DEBUG (( DEBUG_TX,\r
+                    "0x%08x: Packet on transmit list\r\n",\r
+                    pPacket ));\r
+\r
+          //\r
+          //  Account for the buffered data\r
+          //\r
+          *pTxBytes += BufferLength;\r
+          *pDataLength = BufferLength;\r
+\r
+          //\r
+          //  Start the transmit engine if it is idle\r
+          //\r
+          if ( NULL != pPort->pTxFree ) {\r
+            pPacket = pSocket->pTxPacketListHead;\r
+            EslSocketTxStart ( pPort,\r
+                               &pSocket->pTxPacketListHead,\r
+                               &pSocket->pTxPacketListTail,\r
+                               &pPort->pTxActive,\r
+                               &pPort->pTxFree );\r
 \r
             //\r
-            //  Free the packet\r
+            //  Ignore any transmit error\r
             //\r
-            EslSocketPacketFree ( pPacket, DEBUG_TX );\r
+            if ( EFI_ERROR ( pSocket->TxError )) {\r
+              DEBUG (( DEBUG_TX,\r
+                       "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",\r
+                       pPort,\r
+                       pPacket,\r
+                       pSocket->TxError ));\r
+            }\r
+            pSocket->TxError = EFI_SUCCESS;\r
           }\r
 \r
           //\r
@@ -2220,16 +935,22 @@ EslUdpTxBuffer4 (
           //  Packet allocation failed\r
           //\r
           pSocket->errno = ENOMEM;\r
+          break;\r
         }\r
-      }\r
-      else {\r
+\r
         //\r
-        //  Not enough buffer space available\r
+        //  Set the next port\r
         //\r
-        pSocket->errno = EAGAIN;\r
-        Status = EFI_NOT_READY;\r
+        pPort = pPort->pLinkSocket;\r
       }\r
     }\r
+    else {\r
+      //\r
+      //  Not enough buffer space available\r
+      //\r
+      pSocket->errno = EAGAIN;\r
+      Status = EFI_NOT_READY;\r
+    }\r
   }\r
 \r
   //\r
@@ -2243,23 +964,27 @@ EslUdpTxBuffer4 (
 /**\r
   Process the transmit completion\r
 \r
-  @param  Event         The normal transmit completion event\r
+  This routine use ::EslSocketTxComplete to perform the transmit\r
+  completion processing for data packets.\r
+\r
+  This routine is called by the UDPv4 network layer when a data\r
+  transmit request completes.\r
 \r
-  @param  pPort         The DT_PORT structure address\r
+  @param [in] Event     The normal transmit completion event\r
+\r
+  @param [in] pIo       Address of an ::ESL_IO_MGMT structure\r
 \r
 **/\r
 VOID\r
-EslUdpTxComplete4 (\r
+EslUdp4TxComplete (\r
   IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
+  IN ESL_IO_MGMT * pIo\r
   )\r
 {\r
   UINT32 LengthInBytes;\r
-  DT_PACKET * pCurrentPacket;\r
-  DT_PACKET * pNextPacket;\r
-  DT_PACKET * pPacket;\r
-  DT_SOCKET * pSocket;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
+  ESL_PORT * pPort;\r
+  ESL_PACKET * pPacket;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
   \r
   DBG_ENTER ( );\r
@@ -2267,142 +992,241 @@ EslUdpTxComplete4 (
   //\r
   //  Locate the active transmit packet\r
   //\r
+  pPacket = pIo->pPacket;\r
+  pPort = pIo->pPort;\r
   pSocket = pPort->pSocket;\r
-  pUdp4 = &pPort->Context.Udp4;\r
-  pPacket = pUdp4->pTxPacket;\r
-  \r
+\r
   //\r
-  //  Mark this packet as complete\r
+  //  Get the transmit length and status\r
   //\r
-  pUdp4->pTxPacket = NULL;\r
   LengthInBytes = pPacket->Op.Udp4Tx.TxData.DataLength;\r
   pSocket->TxBytes -= LengthInBytes;\r
-  \r
+  Status = pIo->Token.Udp4Tx.Status;\r
+\r
   //\r
-  //  Save any transmit error\r
+  //  Ignore the transmit error\r
   //\r
-  Status = pUdp4->TxToken.Status;\r
   if ( EFI_ERROR ( Status )) {\r
-    if ( !EFI_ERROR ( pSocket->TxError )) {\r
-      pSocket->TxError = Status;\r
-    }\r
-    DEBUG (( DEBUG_TX | DEBUG_INFO,\r
-              "ERROR - Transmit failure for packet 0x%08x, Status: %r\r\n",\r
-              pPacket,\r
-              Status ));\r
-  \r
-    //\r
-    //  Empty the normal transmit list\r
-    //\r
-    pCurrentPacket = pPacket;\r
-    pNextPacket = pSocket->pTxPacketListHead;\r
-    while ( NULL != pNextPacket ) {\r
-      pPacket = pNextPacket;\r
-      pNextPacket = pPacket->pNext;\r
-      EslSocketPacketFree ( pPacket, DEBUG_TX );\r
-    }\r
-    pSocket->pTxPacketListHead = NULL;\r
-    pSocket->pTxPacketListTail = NULL;\r
-    pPacket = pCurrentPacket;\r
-  }\r
-  else\r
-  {\r
-    DEBUG (( DEBUG_TX | DEBUG_INFO,\r
-              "0x%08x: Packet transmitted %d bytes successfully\r\n",\r
-              pPacket,\r
-              LengthInBytes ));\r
-  \r
-    //\r
-    //  Verify the transmit engine is still running\r
-    //\r
-    if ( !pPort->bCloseNow ) {\r
-      //\r
-      //  Start the next packet transmission\r
-      //\r
-      EslUdpTxStart4 ( pPort );\r
-    }\r
+    DEBUG (( DEBUG_TX,\r
+             "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",\r
+             pPort,\r
+             pPacket,\r
+             Status ));\r
+    Status = EFI_SUCCESS;\r
   }\r
-  \r
-  //\r
-  //  Release this packet\r
-  //\r
-  EslSocketPacketFree ( pPacket, DEBUG_TX );\r
-  \r
+\r
   //\r
-  //  Finish the close operation if necessary\r
+  //  Complete the transmit operation\r
   //\r
-  if (( PORT_STATE_CLOSE_STARTED <= pPort->State )\r
-    && ( NULL == pSocket->pTxPacketListHead )\r
-    && ( NULL == pUdp4->pTxPacket )) {\r
-    //\r
-    //  Indicate that the transmit is complete\r
-    //\r
-    EslUdpPortCloseTxDone4 ( pPort );\r
-  }\r
+  EslSocketTxComplete ( pIo,\r
+                        LengthInBytes,\r
+                        Status,\r
+                        "UDP ",\r
+                        &pSocket->pTxPacketListHead,\r
+                        &pSocket->pTxPacketListTail,\r
+                        &pPort->pTxActive,\r
+                        &pPort->pTxFree );\r
   DBG_EXIT ( );\r
 }\r
 \r
 \r
 /**\r
-  Transmit data using a network connection.\r
+  Verify the adapter's IP address\r
 \r
-  @param [in] pPort           Address of a DT_PORT structure\r
+  This support routine is called by EslSocketBindTest.\r
+\r
+  @param [in] pPort       Address of an ::ESL_PORT structure.\r
+  @param [in] pConfigData Address of the configuration data\r
+\r
+  @retval EFI_SUCCESS - The IP address is valid\r
+  @retval EFI_NOT_STARTED - The IP address is invalid\r
 \r
  **/\r
-VOID\r
-EslUdpTxStart4 (\r
-  IN DT_PORT * pPort\r
+EFI_STATUS\r
+EslUdp4VerifyLocalIpAddress (\r
+  IN ESL_PORT * pPort,\r
+  IN EFI_UDP4_CONFIG_DATA * pConfigData\r
   )\r
 {\r
-  DT_PACKET * pNextPacket;\r
-  DT_PACKET * pPacket;\r
-  DT_SOCKET * pSocket;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  EFI_UDP4_PROTOCOL * pUdp4Protocol;\r
+  UINTN DataSize;\r
+  EFI_IP4_CONFIG2_INTERFACE_INFO * pIfInfo;\r
+  EFI_IP4_CONFIG2_PROTOCOL * pIpConfig2Protocol;\r
+  ESL_SERVICE * pService;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Assume success\r
+  //  Use break instead of goto\r
   //\r
-  Status = EFI_SUCCESS;\r
+  pIfInfo = NULL;\r
+  for ( ; ; ) {\r
+    //\r
+    //  Determine if the IP address is specified\r
+    //\r
+    DEBUG (( DEBUG_BIND,\r
+              "UseDefaultAddress: %s\r\n",\r
+              pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" ));\r
+    DEBUG (( DEBUG_BIND,\r
+              "Requested IP address: %d.%d.%d.%d\r\n",\r
+              pConfigData->StationAddress.Addr [ 0 ],\r
+              pConfigData->StationAddress.Addr [ 1 ],\r
+              pConfigData->StationAddress.Addr [ 2 ],\r
+              pConfigData->StationAddress.Addr [ 3 ]));\r
+    if ( pConfigData->UseDefaultAddress\r
+      || (( 0 == pConfigData->StationAddress.Addr [ 0 ])\r
+      && ( 0 == pConfigData->StationAddress.Addr [ 1 ])\r
+      && ( 0 == pConfigData->StationAddress.Addr [ 2 ])\r
+      && ( 0 == pConfigData->StationAddress.Addr [ 3 ])))\r
+    {\r
+      Status = EFI_SUCCESS;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Open the configuration protocol\r
+    //\r
+    pService = pPort->pService;\r
+    Status = gBS->OpenProtocol ( \r
+                    pService->Controller,\r
+                    &gEfiIp4Config2ProtocolGuid,\r
+                    (VOID **)&pIpConfig2Protocol,\r
+                    NULL,\r
+                    NULL,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL \r
+                    );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - IP Configuration Protocol not available, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
+    }\r
 \r
-  //\r
-  //  Get the packet from the queue head\r
-  //\r
-  pSocket = pPort->pSocket;\r
-  pPacket = pSocket->pTxPacketListHead;\r
-  if ( NULL != pPacket ) {\r
     //\r
-    //  Remove the packet from the queue\r
+    //  Get the interface information size\r
     //\r
-    pNextPacket = pPacket->pNext;\r
-    pSocket->pTxPacketListHead = pNextPacket;\r
-    if ( NULL == pNextPacket ) {\r
-      pSocket->pTxPacketListTail = NULL;\r
+    DataSize = 0;\r
+    Status = pIpConfig2Protocol->GetData ( \r
+                                   pIpConfig2Protocol,\r
+                                   Ip4Config2DataTypeInterfaceInfo,\r
+                                   &DataSize,\r
+                                   NULL\r
+                                   );\r
+    if ( EFI_BUFFER_TOO_SMALL != Status ) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to get the interface information size, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
     }\r
 \r
     //\r
-    //  Set the packet as active\r
+    //  Allocate the interface information buffer\r
     //\r
-    pUdp4 = &pPort->Context.Udp4;\r
-    pUdp4->pTxPacket = pPacket;\r
+    pIfInfo = AllocatePool ( DataSize );\r
+    if ( NULL == pIfInfo ) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Not enough memory to allocate the interface information buffer!\r\n" ));\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      break;\r
+    }\r
 \r
     //\r
-    //  Start the transmit operation\r
+    // Get the interface info.\r
     //\r
-    pUdp4Protocol = pUdp4->pProtocol;\r
-    pUdp4->TxToken.Packet.TxData = &pPacket->Op.Udp4Tx.TxData;\r
-    Status = pUdp4Protocol->Transmit ( pUdp4Protocol, &pUdp4->TxToken );\r
+    Status = pIpConfig2Protocol->GetData ( \r
+                                  pIpConfig2Protocol,\r
+                                  Ip4Config2DataTypeInterfaceInfo,\r
+                                  &DataSize,\r
+                                  pIfInfo\r
+                                  );\r
     if ( EFI_ERROR ( Status )) {\r
-      pSocket = pPort->pSocket;\r
-      if ( EFI_SUCCESS == pSocket->TxError ) {\r
-        pSocket->TxError = Status;\r
-      }\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to return the interface info, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Display the current configuration\r
+    //\r
+    DEBUG (( DEBUG_BIND,\r
+              "Actual adapter IP address: %d.%d.%d.%d\r\n",\r
+              pIfInfo->StationAddress.Addr [ 0 ],\r
+              pIfInfo->StationAddress.Addr [ 1 ],\r
+              pIfInfo->StationAddress.Addr [ 2 ],\r
+              pIfInfo->StationAddress.Addr [ 3 ]));\r
+\r
+    //\r
+    //  Assume the port is not configured\r
+    //\r
+    Status = EFI_SUCCESS;\r
+    if (( pConfigData->StationAddress.Addr [ 0 ] == pIfInfo->StationAddress.Addr [ 0 ])\r
+      && ( pConfigData->StationAddress.Addr [ 1 ] == pIfInfo->StationAddress.Addr [ 1 ])\r
+      && ( pConfigData->StationAddress.Addr [ 2 ] == pIfInfo->StationAddress.Addr [ 2 ])\r
+      && ( pConfigData->StationAddress.Addr [ 3 ] == pIfInfo->StationAddress.Addr [ 3 ])) {\r
+      break;\r
     }\r
+\r
+    //\r
+    //  The IP address did not match\r
+    //\r
+    Status = EFI_NOT_STARTED;\r
+    break;\r
   }\r
 \r
-  DBG_EXIT ( );\r
+  //\r
+  //  Free the buffer if necessary\r
+  //\r
+  if ( NULL != pIfInfo ) {\r
+    FreePool ( pIfInfo );\r
+  }\r
+\r
+  //\r
+  //  Return the IP address status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
 }\r
 \r
+\r
+/**\r
+  Interface between the socket layer and the network specific\r
+  code that supports SOCK_DGRAM sockets over UDPv4.\r
+**/\r
+CONST ESL_PROTOCOL_API cEslUdp4Api = {\r
+  "UDPv4",\r
+  IPPROTO_UDP,\r
+  OFFSET_OF ( ESL_PORT, Context.Udp4.ConfigData ),\r
+  OFFSET_OF ( ESL_LAYER, pUdp4List ),\r
+  OFFSET_OF ( struct sockaddr_in, sin_zero ),\r
+  sizeof ( struct sockaddr_in ),\r
+  AF_INET,\r
+  sizeof (((ESL_PACKET *)0 )->Op.Udp4Rx ),\r
+  sizeof (((ESL_PACKET *)0 )->Op.Udp4Rx ),\r
+  OFFSET_OF ( ESL_IO_MGMT, Token.Udp4Rx.Packet.RxData ),\r
+  FALSE,\r
+  EADDRINUSE,\r
+  NULL,   //  Accept\r
+  NULL,   //  ConnectPoll\r
+  NULL,   //  ConnectStart\r
+  EslUdp4SocketIsConfigured,\r
+  EslUdp4LocalAddressGet,\r
+  EslUdp4LocalAddressSet,\r
+  NULL,   //  Listen\r
+  NULL,   //  OptionGet\r
+  NULL,   //  OptionSet\r
+  EslUdp4PacketFree,\r
+  EslUdp4PortAllocate,\r
+  NULL,   //  PortClose,\r
+  NULL,   //  PortCloseOp\r
+  TRUE,\r
+  EslUdp4Receive,\r
+  EslUdp4RemoteAddressGet,\r
+  EslUdp4RemoteAddressSet,\r
+  EslUdp4RxComplete,\r
+  NULL,   //  RxStart\r
+  EslUdp4TxBuffer,\r
+  EslUdp4TxComplete,\r
+  NULL,   //  TxOobComplete\r
+  (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslUdp4VerifyLocalIpAddress\r
+};\r