\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
\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
\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
+ @param [in] pPort Address of an ::ESL_PORT structure.\r
\r
- This routine releases the resources allocated by\r
- ::UdpPortAllocate4().\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] pBuffer Address of a buffer to receive the data.\r
\r
- @param [in] pPort Address of the port structure.\r
+ @param [in] pDataLength Number of received data bytes in the buffer.\r
\r
- @retval EFI_SUCCESS The port is closed\r
- @retval other Port close error\r
+ @param [out] pAddress Network address to receive the remote system address\r
\r
-**/\r
-EFI_STATUS\r
-EslUdpPortClose4 (\r
- IN DT_PORT * pPort\r
+ @param [out] pSkipBytes Address to receive the number of bytes skipped\r
+\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
+ if ( *pbConsumePacket ) {\r
//\r
- // Remove this port from the head of the socket list\r
+ // Display for the bytes consumed\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
+ 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
- //\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
+ @param [in] pPort Address of an ::ESL_PORT structure.\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
+ @param [out] pAddress Network address to receive the remote system address\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
+VOID\r
+EslUdp4RemoteAddressGet (\r
+ IN ESL_PORT * pPort,\r
+ OUT struct sockaddr * pAddress\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
+ ESL_UDP4_CONTEXT * pUdp4;\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
+ //\r
+ // Return the remote address\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
//\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
//\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
//\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
/**\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
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
\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
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
//\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
sizeof ( pPacket->Op.Udp4Tx )\r
- sizeof ( pPacket->Op.Udp4Tx.Buffer )\r
+ BufferLength,\r
+ 0,\r
DEBUG_TX );\r
if ( !EFI_ERROR ( Status )) {\r
//\r
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
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
// 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
/**\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
//\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
+ 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
- @param [in] pPort Address of a DT_PORT structure\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_IPCONFIG_DATA * pIpConfigData;\r
+ EFI_IP4_CONFIG_PROTOCOL * pIpConfigProtocol;\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
+ pIpConfigData = 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
- // 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
+ // Open the configuration protocol\r
//\r
- pNextPacket = pPacket->pNext;\r
- pSocket->pTxPacketListHead = pNextPacket;\r
- if ( NULL == pNextPacket ) {\r
- pSocket->pTxPacketListTail = NULL;\r
+ pService = pPort->pService;\r
+ Status = gBS->OpenProtocol ( pService->Controller,\r
+ &gEfiIp4ConfigProtocolGuid,\r
+ (VOID **)&pIpConfigProtocol,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL );\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 IP configuration data size\r
+ //\r
+ DataSize = 0;\r
+ Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,\r
+ &DataSize,\r
+ NULL );\r
+ if ( EFI_BUFFER_TOO_SMALL != Status ) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",\r
+ Status ));\r
+ break;\r
}\r
\r
//\r
- // Set the packet as active\r
+ // Allocate the configuration data buffer\r
//\r
- pUdp4 = &pPort->Context.Udp4;\r
- pUdp4->pTxPacket = pPacket;\r
+ pIpConfigData = AllocatePool ( DataSize );\r
+ if ( NULL == pIpConfigData ) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ break;\r
+ }\r
\r
//\r
- // Start the transmit operation\r
+ // Get the IP configuration\r
//\r
- pUdp4Protocol = pUdp4->pProtocol;\r
- pUdp4->TxToken.Packet.TxData = &pPacket->Op.Udp4Tx.TxData;\r
- Status = pUdp4Protocol->Transmit ( pUdp4Protocol, &pUdp4->TxToken );\r
+ Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,\r
+ &DataSize,\r
+ pIpConfigData );\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 IP Configuration data, 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
+ pIpConfigData->StationAddress.Addr [ 0 ],\r
+ pIpConfigData->StationAddress.Addr [ 1 ],\r
+ pIpConfigData->StationAddress.Addr [ 2 ],\r
+ pIpConfigData->StationAddress.Addr [ 3 ]));\r
+\r
+ //\r
+ // Assume the port is not configured\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ if (( pConfigData->StationAddress.Addr [ 0 ] == pIpConfigData->StationAddress.Addr [ 0 ])\r
+ && ( pConfigData->StationAddress.Addr [ 1 ] == pIpConfigData->StationAddress.Addr [ 1 ])\r
+ && ( pConfigData->StationAddress.Addr [ 2 ] == pIpConfigData->StationAddress.Addr [ 2 ])\r
+ && ( pConfigData->StationAddress.Addr [ 3 ] == pIpConfigData->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 != pIpConfigData ) {\r
+ FreePool ( pIpConfigData );\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