]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/EfiSocketLib/Udp4.c
Update the sockets library code
[mirror_edk2.git] / StdLib / EfiSocketLib / Udp4.c
index 95fc66517a45c32ed2e79edabdf3d71c2b1d7561..e1500d3f9f92b3fd308dc05d36cb979bcceb9af7 100644 (file)
 \r
 \r
 /**\r
-  Bind a name to a socket.\r
-\r
-  The ::UdpBind4 routine connects a name to a UDP4 stack on the local machine.\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
-\r
-  @param [in] pSockAddr Address of a sockaddr structure that contains the\r
-                        connection point on the local machine.  An IPv4 address\r
-                        of INADDR_ANY specifies that the connection is made to\r
-                        all of the network stacks on the platform.  Specifying a\r
-                        specific IPv4 address restricts the connection to the\r
-                        network stack supporting that address.  Specifying zero\r
-                        for the port causes the network layer to assign a port\r
-                        number from the dynamic range.  Specifying a specific\r
-                        port number causes the network layer to use that port.\r
-\r
-  @param [in] SockAddrLen   Specifies the length in bytes of the sockaddr structure.\r
-\r
-  @retval EFI_SUCCESS - Socket successfully created\r
-\r
- **/\r
-EFI_STATUS\r
-EslUdpBind4 (\r
-  IN DT_SOCKET * pSocket,\r
-  IN const struct sockaddr * pSockAddr,\r
-  IN socklen_t SockAddrLength\r
-  )\r
-{\r
-  EFI_HANDLE ChildHandle;\r
-  DT_LAYER * pLayer;\r
-  DT_PORT * pPort;\r
-  DT_SERVICE * pService;\r
-  CONST struct sockaddr_in * pIp4Address;\r
-  EFI_SERVICE_BINDING_PROTOCOL * pUdp4Service;\r
-  EFI_STATUS Status;\r
-  EFI_STATUS TempStatus;\r
-  \r
-  DBG_ENTER ( );\r
-  \r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-  \r
-  //\r
-  //  Assume success\r
-  //\r
-  pSocket->errno = 0;\r
-  Status = EFI_SUCCESS;\r
-  \r
-  //\r
-  //  Validate the address length\r
-  //\r
-  pIp4Address = (CONST struct sockaddr_in *) pSockAddr;\r
-  if ( SockAddrLength >= ( sizeof ( *pIp4Address )\r
-                           - sizeof ( pIp4Address->sin_zero ))) {\r
-\r
-    //\r
-    //  Walk the list of services\r
-    //\r
-    pLayer = &mEslLayer;\r
-    pService = pLayer->pUdp4List;\r
-    while ( NULL != pService ) {\r
-\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
-      //\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
-      //\r
-      //  Set the next service\r
-      //\r
-      pService = pService->pNext;\r
-    }\r
-  \r
-    //\r
-    //  Verify that at least one network connection was found\r
-    //\r
-    if ( NULL == pSocket->pPortList ) {\r
-      DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,\r
-                "Socket address %d.%d.%d.%d (0x%08x) is not available!\r\n",\r
-                ( pIp4Address->sin_addr.s_addr >> 24 ) & 0xff,\r
-                ( pIp4Address->sin_addr.s_addr >> 16 ) & 0xff,\r
-                ( pIp4Address->sin_addr.s_addr >> 8 ) & 0xff,\r
-                pIp4Address->sin_addr.s_addr & 0xff,\r
-                pIp4Address->sin_addr.s_addr ));\r
-      pSocket->errno = EADDRNOTAVAIL;\r
-      Status = EFI_INVALID_PARAMETER;\r
-    }\r
-  }\r
-  else {\r
-    DEBUG (( DEBUG_BIND,\r
-              "ERROR - Invalid Udp4 address length: %d\r\n",\r
-              SockAddrLength ));\r
-    Status = EFI_INVALID_PARAMETER;\r
-    pSocket->errno = EINVAL;\r
-  }\r
-  \r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
+  Get the local socket address\r
 \r
-/**\r
-  Initialize the UDP4 service.\r
+  This routine returns the IPv4 address and UDP port number associated\r
+  with the local socket.\r
 \r
-  This routine initializes the UDP4 service after its service binding\r
-  protocol was located on a controller.\r
+  This routine is called by ::EslSocketGetLocalAddress to determine the\r
+  network address for the SOCK_DGRAM socket.\r
 \r
-  @param [in] pService        DT_SERVICE structure address\r
+  @param [in] pPort       Address of an ::ESL_PORT structure.\r
 \r
-  @retval EFI_SUCCESS         The service was properly initialized\r
-  @retval other               A failure occurred during the service initialization\r
+  @param [out] pSockAddr  Network address to receive the local system address\r
 \r
 **/\r
-EFI_STATUS\r
-EFIAPI\r
-EslUdpInitialize4 (\r
-  IN DT_SERVICE * pService\r
+VOID\r
+EslUdp4LocalAddressGet (\r
+  IN ESL_PORT * pPort,\r
+  OUT struct sockaddr * pSockAddr\r
   )\r
 {\r
-  DT_LAYER * pLayer;\r
-  EFI_STATUS Status;\r
+  struct sockaddr_in * pLocalAddress;\r
+  ESL_UDP4_CONTEXT * pUdp4;\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
-  //\r
-  pLayer = &mEslLayer;\r
-  pService->pNext = pLayer->pUdp4List;\r
-  pLayer->pUdp4List = pService;\r
-\r
-  //\r
-  //  Assume the list is empty\r
+  //  Return the local address\r
   //\r
-  Status = EFI_SUCCESS;\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
-  //\r
-  //  Return the initialization status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
+  DBG_EXIT ( );\r
 }\r
 \r
 \r
 /**\r
-  Allocate and initialize a DT_PORT structure.\r
+  Set the local port address.\r
 \r
-  @param [in] pSocket     Address of the socket structure.\r
-  @param [in] pService    Address of the DT_SERVICE structure.\r
-  @param [in] ChildHandle Udp4 child handle\r
-  @param [in] pIpAddress  Buffer containing IP4 network address of the local host\r
-  @param [in] PortNumber  Udp4 port number\r
-  @param [in] DebugFlags  Flags for debug messages\r
-  @param [out] ppPort     Buffer to receive new DT_PORT structure address\r
+  This routine sets the local port address.\r
 \r
-  @retval EFI_SUCCESS - Socket successfully created\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
-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
+EslUdp4LocalAddressSet (\r
+  IN ESL_PORT * pPort,\r
+  IN CONST struct sockaddr * pSockAddr,\r
+  IN BOOLEAN bBindTest\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
+  CONST struct sockaddr_in * pIpAddress;\r
+  CONST UINT8 * pIpv4Address;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Use for/break instead of goto\r
-  for ( ; ; ) {\r
-    //\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
+  //  Validate the address\r
+  //\r
+  pIpAddress = (struct sockaddr_in *)pSockAddr;\r
+  if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) {\r
     //\r
-    //  Allocate the receive event\r
+    //  The local address must not be the broadcast address\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
+    Status = EFI_INVALID_PARAMETER;\r
+    pPort->pSocket->errno = EADDRNOTAVAIL;\r
+  }\r
+  else {\r
     //\r
-    //  Allocate the transmit event\r
+    //  Set the local address\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
+    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
-    //  Open the port protocol\r
+    //  Determine if the default address is used\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
+    pConfig->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr );\r
+    \r
     //\r
-    //  Set the port address\r
+    //  Set the subnet mask\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
+    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->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
+    //  Validate the IP address\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
+    pConfig->StationPort = 0;\r
+    Status = bBindTest ? EslSocketBindTest ( pPort, EADDRNOTAVAIL )\r
+                       : EFI_SUCCESS;\r
+    if ( !EFI_ERROR ( Status )) {\r
+      //\r
+      //  Set the port number\r
+      //\r
+      pConfig->StationPort = SwapBytes16 ( pIpAddress->sin_port );\r
 \r
-    //\r
-    //  Return the port\r
-    //\r
-    *ppPort = pPort;\r
-    break;\r
+      //\r
+      //  Display the local address\r
+      //\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
 \r
-  //\r
-  //  Clean up after the error if necessary\r
-  //\r
-  if (( EFI_ERROR ( Status )) && ( NULL != pPort )) {\r
-    //\r
-    //  Close the port\r
-    //\r
-    EslUdpPortClose4 ( pPort );\r
-  }\r
   //\r
   //  Return the operation status\r
   //\r
@@ -423,292 +171,102 @@ EslUdpPortAllocate4 (
 \r
 \r
 /**\r
-  Close a UDP4 port.\r
+  Free a receive packet\r
 \r
-  This routine releases the resources allocated by\r
-  ::UdpPortAllocate4().\r
-  \r
-  @param [in] pPort       Address of the port structure.\r
+  This routine performs the network specific operations necessary\r
+  to free a receive packet.\r
 \r
-  @retval EFI_SUCCESS     The port is closed\r
-  @retval other           Port close error\r
+  This routine is called by ::EslSocketPortCloseTxDone to free a\r
+  receive packet.\r
+\r
+  @param [in] pPacket         Address of an ::ESL_PACKET structure.\r
+  @param [in, out] pRxBytes   Address of the count of RX bytes\r
 \r
 **/\r
-EFI_STATUS\r
-EslUdpPortClose4 (\r
-  IN DT_PORT * pPort\r
+VOID\r
+EslUdp4PacketFree (\r
+  IN ESL_PACKET * pPacket,\r
+  IN OUT size_t * pRxBytes\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
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Verify the socket layer synchronization\r
-  //\r
-  VERIFY_TPL ( TPL_SOCKETS );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
-  pSocket = pPort->pSocket;\r
-  pSocket->errno = 0;\r
-\r
-  //\r
-  //  Locate the port in the socket list\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
-    //\r
-    //  Locate the port in the middle of the socket list\r
-    //\r
-    while (( NULL != pPreviousPort )\r
-      && ( pPreviousPort->pLinkSocket != pPort )) {\r
-      pPreviousPort = pPreviousPort->pLinkSocket;\r
-    }\r
-    if ( NULL != pPreviousPort ) {\r
-      //\r
-      //  Remove the port from the middle of the socket list\r
-      //\r
-      pPreviousPort->pLinkSocket = pPort->pLinkSocket;\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Locate the port in the service list\r
-  //\r
-  pService = pPort->pService;\r
-  pPreviousPort = pService->pPortList;\r
-  if ( pPreviousPort == pPort ) {\r
-    //\r
-    //  Remove this port from the head of the service list\r
-    //\r
-    pService->pPortList = pPort->pLinkService;\r
-  }\r
-  else {\r
-    //\r
-    //  Locate the port in the middle of the service list\r
-    //\r
-    while (( NULL != pPreviousPort )\r
-      && ( pPreviousPort->pLinkService != pPort )) {\r
-      pPreviousPort = pPreviousPort->pLinkService;\r
-    }\r
-    if ( NULL != pPreviousPort ) {\r
-      //\r
-      //  Remove the port from the middle of the service list\r
-      //\r
-      pPreviousPort->pLinkService = pPort->pLinkService;\r
-    }\r
-  }\r
-\r
-  //\r
-  //  Empty the receive queue\r
-  //\r
-  ASSERT ( NULL == pSocket->pRxPacketListHead );\r
-  ASSERT ( NULL == pSocket->pRxPacketListTail );\r
-  ASSERT ( 0 == pSocket->RxBytes );\r
-\r
-  //\r
-  //  Empty the receive free queue\r
-  //\r
-  while ( NULL != pSocket->pRxFree ) {\r
-    pPacket = pSocket->pRxFree;\r
-    pSocket->pRxFree = pPacket->pNext;\r
-    EslSocketPacketFree ( pPacket, DEBUG_RX );\r
-  }\r
-\r
-  //\r
-  //  Done with the 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
-  //\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
-\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
+  EFI_UDP4_RECEIVE_DATA * pRxData;\r
 \r
-  //\r
-  //  Done with the UDP port\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
+  DBG_ENTER ( );\r
 \r
   //\r
-  //  Release the port structure\r
+  //  Account for the receive bytes\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
+  pRxData = pPacket->Op.Udp4Rx.pRxData;\r
+  *pRxBytes -= pRxData->DataLength;\r
 \r
   //\r
-  //  Mark the socket as closed if necessary\r
+  //  Disconnect the buffer from the packet\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
+  pPacket->Op.Udp4Rx.pRxData = NULL;\r
 \r
   //\r
-  //  Return the operation 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
-  Start the close operation on a UDP4 port, state 1.\r
+  Initialize the network specific portions of an ::ESL_PORT structure.\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
+  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
 \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
+  @retval EFI_SUCCESS - Socket successfully created\r
 \r
-**/\r
+ **/\r
 EFI_STATUS\r
-EslUdpPortCloseStart4 (\r
-  IN DT_PORT * pPort,\r
-  IN BOOLEAN bCloseNow,\r
+EslUdp4PortAllocate (\r
+  IN ESL_PORT * pPort,\r
   IN UINTN DebugFlags\r
   )\r
 {\r
-  DT_SOCKET * pSocket;\r
+  EFI_UDP4_CONFIG_DATA * pConfig;\r
+  ESL_SOCKET * pSocket;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Verify the socket layer synchronization\r
+  //  Initialize the port\r
   //\r
-  VERIFY_TPL ( TPL_SOCKETS );\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
-  //  Mark the port as closing\r
+  //  Save the cancel, receive and transmit addresses\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
+  pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.UDPv4->Configure;\r
+  pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Cancel;\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
-    //  Determine if transmits are complete\r
-    //\r
-    Status = EslUdpPortCloseTxDone4 ( pPort );\r
-  }\r
+  //\r
+  //  Set the configuration flags\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 = TRUE;\r
+  Status = EFI_SUCCESS;\r
 \r
   //\r
   //  Return the operation status\r
@@ -719,1184 +277,300 @@ EslUdpPortCloseStart4 (
 \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
+  Receive data from a network connection.\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
+  This routine attempts to return buffered data to the caller.  The\r
+  data is removed from the urgent queue if the message flag MSG_OOB\r
+  is specified, otherwise data is removed from the normal queue.\r
+  See the \ref ReceiveEngine section.\r
 \r
-**/\r
-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
+  This routine is called by ::EslSocketReceive to handle the network\r
+  specific receive operation to support SOCK_DGRAM sockets.\r
 \r
-  DBG_ENTER ( );\r
+  @param [in] pPort           Address of an ::ESL_PORT structure.\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
+  @param [in] pPacket         Address of an ::ESL_PACKET structure.\r
   \r
-  @retval EFI_SUCCESS   The connection was successfully established.\r
-  @retval EFI_NOT_READY The connection is in progress, call this routine again.\r
-  @retval Others        The connection attempt failed.\r
-\r
- **/\r
-EFI_STATUS\r
-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
+  @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed\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
+  \r
   @param [in] pBuffer         Address of a buffer to receive the data.\r
-\r
+  \r
   @param [in] pDataLength     Number of received data bytes in the buffer.\r
 \r
   @param [out] pAddress       Network address to receive the remote system address\r
 \r
-  @param [in,out] pAddressLength  Length of the remote network address structure\r
-\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
+  @param [out] pSkipBytes     Address to receive the number of bytes skipped\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
+  @return   Returns the address of the next free byte in the buffer.\r
 \r
  **/\r
-EFI_STATUS\r
-EslUdpRxCancel4 (\r
-  IN DT_SOCKET * pSocket\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
-  DT_PACKET * pPacket;\r
-  DT_PORT * pPort;\r
-  DT_UDP4_CONTEXT * pUdp4;\r
-  EFI_UDP4_PROTOCOL * pUdp4Protocol;\r
-  EFI_STATUS Status;\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
-  //  Assume failure\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 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
-  Status = EFI_NOT_FOUND;\r
+  //  Copy the received data\r
+  //\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\r
+  //  Determine if the data is being read\r
   //\r
-  pPort = pSocket->pPortList;\r
-  if ( NULL != pPort ) {\r
+  if ( *pbConsumePacket ) {\r
     //\r
-    //  Determine if a receive is pending\r
+    //  Display for the bytes consumed\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
+    DEBUG (( DEBUG_RX,\r
+              "0x%08x: Port account for 0x%08x bytes\r\n",\r
+              pPort,\r
+              DataBytes ));\r
+\r
+    //\r
+    //  Account for any discarded data\r
+    //\r
+    *pSkipBytes = pRxData->DataLength - DataBytes;\r
   }\r
 \r
   //\r
-  //  Return the operation status\r
+  //  Return the data length and the buffer address\r
   //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
+  *pDataLength = DataBytes;\r
+  DBG_EXIT_HEX ( pBuffer );\r
+  return pBuffer;\r
 }\r
 \r
 \r
 /**\r
-  Process the receive completion\r
+  Get the remote socket address\r
 \r
-  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
+  This routine returns the address of the remote connection point\r
+  associated with the SOCK_DGRAM socket.\r
 \r
-  @param  Event         The receive completion event\r
+  This routine is called by ::EslSocketGetPeerAddress to detemine\r
+  the UDPv4 address and port number associated with the network adapter.\r
 \r
-  @param  pPort         The DT_PORT structure address\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
-EslUdpRxComplete4 (\r
-  IN EFI_EVENT Event,\r
-  IN DT_PORT * pPort\r
+EslUdp4RemoteAddressGet (\r
+  IN ESL_PORT * pPort,\r
+  OUT struct sockaddr * pAddress\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
+  struct sockaddr_in * pRemoteAddress;\r
+  ESL_UDP4_CONTEXT * pUdp4;\r
+\r
   DBG_ENTER ( );\r
-  \r
+\r
   //\r
-  //  Mark this receive complete\r
+  //  Return the remote address\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
+  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
-      //\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
+  DBG_EXIT ( );\r
+}\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
+  Set the remote address\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
+  This routine sets the remote address in the port.\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
-  DBG_EXIT ( );\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
-/**\r
-  Start a receive operation\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
+  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 undoes the work performed by ::UdpInitialize4.\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
-  @param [in] pService        DT_SERVICE structure address\r
+  This routine is called by the UDPv4 driver when data is\r
+  received.\r
+\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
@@ -1920,9 +594,10 @@ EslUdpShutdown4 (
       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,9 +610,33 @@ 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
@@ -1970,15 +669,25 @@ EslUdpShutdown4 (
         }\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
 \r
         //\r
         //  Start the first read on the port\r
         //\r
-        EslUdpRxStart4 ( pPort );\r
+        EslSocketRxStart ( pPort );\r
 \r
         //\r
         //  The socket is connected\r
@@ -2018,10 +727,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 +744,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 +762,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 +772,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,7 +789,7 @@ 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
@@ -2092,8 +804,6 @@ EslUdpTxBuffer4 (
       //  Determine the queue head\r
       //\r
       pUdp4 = &pPort->Context.Udp4;\r
-      ppPacket = &pUdp4->pTxPacket;\r
-      pToken = &pUdp4->TxToken;\r
       pTxBytes = &pSocket->TxBytes;\r
 \r
       //\r
@@ -2108,6 +818,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 +831,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
@@ -2192,8 +905,12 @@ EslUdpTxBuffer4 (
             //\r
             //  Start the transmit engine if it is idle\r
             //\r
-            if ( NULL == pUdp4->pTxPacket ) {\r
-              EslUdpTxStart4 ( pSocket->pPortList );\r
+            if ( NULL != pPort->pTxFree ) {\r
+              EslSocketTxStart ( pPort,\r
+                                 &pSocket->pTxPacketListHead,\r
+                                 &pSocket->pTxPacketListTail,\r
+                                 &pPort->pTxActive,\r
+                                 &pPort->pTxFree );\r
             }\r
           }\r
           else {\r
@@ -2243,23 +960,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 +988,69 @@ 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
-  //\r
-  //  Save any 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
-  }\r
-  \r
-  //\r
-  //  Release this packet\r
-  //\r
-  EslSocketPacketFree ( pPacket, DEBUG_TX );\r
-  \r
+  Status = pIo->Token.Udp4Tx.Status;\r
+\r
   //\r
-  //  Finish the close operation if necessary\r
+  //  Complete the transmit operation\r
   //\r
-  if (( PORT_STATE_CLOSE_STARTED <= pPort->State )\r
-    && ( 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
-\r
-  @param [in] pPort           Address of a DT_PORT structure\r
-\r
- **/\r
-VOID\r
-EslUdpTxStart4 (\r
-  IN DT_PORT * pPort\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
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
-\r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\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
-    //\r
-    pNextPacket = pPacket->pNext;\r
-    pSocket->pTxPacketListHead = pNextPacket;\r
-    if ( NULL == pNextPacket ) {\r
-      pSocket->pTxPacketListTail = NULL;\r
-    }\r
-\r
-    //\r
-    //  Set the packet as active\r
-    //\r
-    pUdp4 = &pPort->Context.Udp4;\r
-    pUdp4->pTxPacket = pPacket;\r
-\r
-    //\r
-    //  Start the transmit operation\r
-    //\r
-    pUdp4Protocol = pUdp4->pProtocol;\r
-    pUdp4->TxToken.Packet.TxData = &pPacket->Op.Udp4Tx.TxData;\r
-    Status = pUdp4Protocol->Transmit ( pUdp4Protocol, &pUdp4->TxToken );\r
-    if ( EFI_ERROR ( Status )) {\r
-      pSocket = pPort->pSocket;\r
-      if ( EFI_SUCCESS == pSocket->TxError ) {\r
-        pSocket->TxError = Status;\r
-      }\r
-    }\r
-  }\r
-\r
-  DBG_EXIT ( );\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
+};\r