+++ /dev/null
-/** @file\r
- Implement the UDP4 driver support for the socket layer.\r
-\r
- Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "Socket.h"\r
-\r
-\r
-/**\r
- Get the local socket address\r
-\r
- This routine returns the IPv4 address and UDP port number associated\r
- with the local socket.\r
-\r
- This routine is called by ::EslSocketGetLocalAddress to determine the\r
- network address for the SOCK_DGRAM socket.\r
-\r
- @param [in] pPort Address of an ::ESL_PORT structure.\r
-\r
- @param [out] pSockAddr Network address to receive the local system address\r
-\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
-EslUdp4LocalAddressSet (\r
- IN ESL_PORT * pPort,\r
- IN CONST struct sockaddr * pSockAddr,\r
- IN BOOLEAN bBindTest\r
- )\r
-{\r
- EFI_UDP4_CONFIG_DATA * pConfig;\r
- CONST struct sockaddr_in * pIpAddress;\r
- CONST UINT8 * pIpv4Address;\r
- EFI_STATUS Status;\r
-\r
- DBG_ENTER ( );\r
-\r
- //\r
- // Validate the address\r
- //\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
- // 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
- 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
- // Set the port number\r
- //\r
- pConfig->StationPort = SwapBytes16 ( pIpAddress->sin_port );\r
-\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
- // Return the operation status\r
- //\r
- DBG_EXIT_STATUS ( Status );\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Free a receive packet\r
-\r
- This routine performs the network specific operations necessary\r
- to free a receive packet.\r
-\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
-VOID\r
-EslUdp4PacketFree (\r
- IN ESL_PACKET * pPacket,\r
- IN OUT size_t * pRxBytes\r
- )\r
-{\r
- EFI_UDP4_RECEIVE_DATA * pRxData;\r
-\r
- DBG_ENTER ( );\r
-\r
- //\r
- // Account for the receive bytes\r
- //\r
- pRxData = pPacket->Op.Udp4Rx.pRxData;\r
- *pRxBytes -= pRxData->DataLength;\r
-\r
- //\r
- // Disconnect the buffer from the packet\r
- //\r
- pPacket->Op.Udp4Rx.pRxData = NULL;\r
-\r
- //\r
- // Return the buffer to the UDP4 driver\r
- //\r
- gBS->SignalEvent ( pRxData->RecycleSignal );\r
- DBG_EXIT ( );\r
-}\r
-\r
-\r
-/**\r
- Initialize the network specific portions of an ::ESL_PORT structure.\r
-\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 - Socket successfully created\r
-\r
- **/\r
-EFI_STATUS\r
-EslUdp4PortAllocate (\r
- IN ESL_PORT * pPort,\r
- IN UINTN DebugFlags\r
- )\r
-{\r
- EFI_UDP4_CONFIG_DATA * pConfig;\r
- ESL_SOCKET * pSocket;\r
- EFI_STATUS Status;\r
-\r
- DBG_ENTER ( );\r
-\r
- //\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
- // 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
- // 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 = FALSE;\r
- Status = EFI_SUCCESS;\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
- 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
- @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] 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 [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
- 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
- // 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
- // 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
- // Determine if the data is being read\r
- //\r
- if ( *pbConsumePacket ) {\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
- DataBytes ));\r
-\r
- //\r
- // Account for any discarded data\r
- //\r
- *pSkipBytes = pRxData->DataLength - DataBytes;\r
- }\r
-\r
- //\r
- // Return the data length and the buffer address\r
- //\r
- *pDataLength = DataBytes;\r
- DBG_EXIT_HEX ( pBuffer );\r
- return pBuffer;\r
-}\r
-\r
-\r
-/**\r
- Get the remote socket address\r
-\r
- This routine returns the address of the remote connection point\r
- associated with the SOCK_DGRAM socket.\r
-\r
- This routine is called by ::EslSocketGetPeerAddress to detemine\r
- the UDPv4 address and port number associated with the network adapter.\r
-\r
- @param [in] pPort Address of an ::ESL_PORT structure.\r
-\r
- @param [out] pAddress Network address to receive the remote system address\r
-\r
-**/\r
-VOID\r
-EslUdp4RemoteAddressGet (\r
- IN ESL_PORT * pPort,\r
- OUT struct sockaddr * pAddress\r
- )\r
-{\r
- struct sockaddr_in * pRemoteAddress;\r
- ESL_UDP4_CONTEXT * pUdp4;\r
-\r
- DBG_ENTER ( );\r
-\r
- //\r
- // 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
- 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
- @retval EFI_SUCCESS The operation was successful\r
-\r
- **/\r
-EFI_STATUS\r
-EslUdp4RemoteAddressSet (\r
- IN ESL_PORT * pPort,\r
- IN CONST struct sockaddr * pSockAddr,\r
- IN socklen_t SockAddrLength\r
- )\r
-{\r
- CONST struct sockaddr_in * pRemoteAddress;\r
- ESL_UDP4_CONTEXT * pUdp4;\r
- EFI_STATUS Status;\r
-\r
- DBG_ENTER ( );\r
-\r
- //\r
- // Set the remote address\r
- //\r
- pUdp4 = &pPort->Context.Udp4;\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
- //\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
- 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 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
-EslUdp4RxComplete (\r
- IN EFI_EVENT Event,\r
- IN ESL_IO_MGMT * pIo\r
- )\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
- // Get the operation status.\r
- //\r
- Status = pIo->Token.Udp4Rx.Status;\r
- \r
- //\r
- // Get the packet length\r
- //\r
- pRxData = pIo->Token.Udp4Rx.Packet.RxData;\r
- LengthInBytes = pRxData->DataLength;\r
-\r
- //\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
- //\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 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
- @retval EFI_SUCCESS - The port is connected\r
- @retval EFI_NOT_STARTED - The port is not connected\r
-\r
- **/\r
- EFI_STATUS\r
- EslUdp4SocketIsConfigured (\r
- IN ESL_SOCKET * pSocket\r
- )\r
-{\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
- DBG_ENTER ( );\r
-\r
- //\r
- // Assume success\r
- //\r
- Status = EFI_SUCCESS;\r
-\r
- //\r
- // Configure the port if necessary\r
- //\r
- if ( !pSocket->bConfigured ) {\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 = EslSocketBind ( &pSocket->SocketProtocol,\r
- (struct sockaddr *)&LocalAddress,\r
- LocalAddress.sin_len,\r
- &pSocket->errno );\r
- }\r
-\r
- //\r
- // Walk the port list\r
- //\r
- pPort = pSocket->pPortList;\r
- while ( NULL != pPort ) {\r
- //\r
- // Attempt to configure the port\r
- //\r
- pNextPort = pPort->pLinkSocket;\r
- pUdp4 = &pPort->Context.Udp4;\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
- 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
- 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
-\r
- case EFI_INVALID_PARAMETER:\r
- pSocket->errno = EADDRNOTAVAIL;\r
- break;\r
-\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
-\r
- case EFI_UNSUPPORTED:\r
- pSocket->errno = EOPNOTSUPP;\r
- break;\r
- }\r
- }\r
- }\r
- else {\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
- EslSocketRxStart ( pPort );\r
-\r
- //\r
- // The socket is connected\r
- //\r
- pSocket->State = SOCKET_STATE_CONNECTED;\r
- pSocket->errno = 0;\r
- }\r
-\r
- //\r
- // Set the next port\r
- //\r
- pPort = pNextPort;\r
- }\r
- }\r
-\r
- //\r
- // Determine the socket configuration status\r
- //\r
- Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED;\r
- \r
- //\r
- // Return the port connected state.\r
- //\r
- DBG_EXIT_STATUS ( Status );\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Buffer data for transmission over a network connection.\r
-\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 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
-\r
- Transmission errors are returned during the next transmission or\r
- during the close operation. Only buffering errors are returned\r
- during the current transmission attempt.\r
-\r
- @param [in] pSocket Address of an ::ESL_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 [in] pAddress Network address of the remote system address\r
-\r
- @param [in] AddressLength Length of the remote network address structure\r
-\r
- @retval EFI_SUCCESS - Socket data successfully buffered\r
-\r
-**/\r
-EFI_STATUS\r
-EslUdp4TxBuffer (\r
- IN ESL_SOCKET * pSocket,\r
- IN int Flags,\r
- IN size_t BufferLength,\r
- IN CONST UINT8 * pBuffer,\r
- OUT size_t * pDataLength,\r
- IN const struct sockaddr * pAddress,\r
- IN socklen_t AddressLength\r
- )\r
-{\r
- ESL_PACKET * pPacket;\r
- ESL_PACKET * pPreviousPacket;\r
- ESL_PORT * pPort;\r
- const struct sockaddr_in * pRemoteAddress;\r
- ESL_UDP4_CONTEXT * pUdp4;\r
- size_t * pTxBytes;\r
- ESL_UDP4_TX_DATA * pTxData;\r
- EFI_STATUS Status;\r
- EFI_TPL TplPrevious;\r
-\r
- DBG_ENTER ( );\r
-\r
- //\r
- // Assume failure\r
- //\r
- Status = EFI_UNSUPPORTED;\r
- pSocket->errno = ENOTCONN;\r
- *pDataLength = 0;\r
-\r
- //\r
- // Verify that the socket is connected\r
- //\r
- if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
- //\r
- // Verify that there is enough room to buffer another\r
- // transmit operation\r
- //\r
- pTxBytes = &pSocket->TxBytes;\r
- if ( pSocket->MaxTxBuf > *pTxBytes ) {\r
- //\r
- // Locate the port\r
- //\r
- pPort = pSocket->pPortList;\r
- while ( NULL != pPort ) {\r
- //\r
- // Determine the queue head\r
- //\r
- pUdp4 = &pPort->Context.Udp4;\r
-\r
- //\r
- // Attempt to allocate the packet\r
- //\r
- Status = EslSocketPacketAllocate ( &pPacket,\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
- // Initialize the transmit operation\r
- //\r
- pTxData = &pPacket->Op.Udp4Tx;\r
- pTxData->TxData.GatewayAddress = NULL;\r
- pTxData->TxData.UdpSessionData = NULL;\r
- pTxData->TxData.DataLength = (UINT32) BufferLength;\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] = 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
- pTxData->Session.DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );\r
- pTxData->Session.DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );\r
- pTxData->Session.DestinationPort = SwapBytes16 ( pRemoteAddress->sin_port );\r
-\r
- //\r
- // Use the remote system address when sending this packet\r
- //\r
- pTxData->TxData.UdpSessionData = &pTxData->Session;\r
- }\r
-\r
- //\r
- // Copy the data into the buffer\r
- //\r
- CopyMem ( &pPacket->Op.Udp4Tx.Buffer[0],\r
- pBuffer,\r
- BufferLength );\r
-\r
- //\r
- // Synchronize with the socket layer\r
- //\r
- RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
- //\r
- // Display the request\r
- //\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
- // 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
-\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
- // Ignore any transmit error\r
- //\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
- // Release the socket layer synchronization\r
- //\r
- RESTORE_TPL ( TplPrevious );\r
- }\r
- else {\r
- //\r
- // Packet allocation failed\r
- //\r
- pSocket->errno = ENOMEM;\r
- break;\r
- }\r
-\r
- //\r
- // Set the next port\r
- //\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
- // Return the operation status\r
- //\r
- DBG_EXIT_STATUS ( Status );\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Process the transmit completion\r
-\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 [in] Event The normal transmit completion event\r
-\r
- @param [in] pIo Address of an ::ESL_IO_MGMT structure\r
-\r
-**/\r
-VOID\r
-EslUdp4TxComplete (\r
- IN EFI_EVENT Event,\r
- IN ESL_IO_MGMT * pIo\r
- )\r
-{\r
- UINT32 LengthInBytes;\r
- ESL_PORT * pPort;\r
- ESL_PACKET * pPacket;\r
- ESL_SOCKET * pSocket;\r
- EFI_STATUS Status;\r
- \r
- DBG_ENTER ( );\r
- \r
- //\r
- // Locate the active transmit packet\r
- //\r
- pPacket = pIo->pPacket;\r
- pPort = pIo->pPort;\r
- pSocket = pPort->pSocket;\r
-\r
- //\r
- // Get the transmit length and status\r
- //\r
- LengthInBytes = pPacket->Op.Udp4Tx.TxData.DataLength;\r
- pSocket->TxBytes -= LengthInBytes;\r
- Status = pIo->Token.Udp4Tx.Status;\r
-\r
- //\r
- // Ignore the transmit error\r
- //\r
- if ( EFI_ERROR ( Status )) {\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
- // Complete the transmit operation\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
- 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
- @retval EFI_SUCCESS - The IP address is valid\r
- @retval EFI_NOT_STARTED - The IP address is invalid\r
-\r
- **/\r
-EFI_STATUS\r
-EslUdp4VerifyLocalIpAddress (\r
- IN ESL_PORT * pPort,\r
- IN EFI_UDP4_CONFIG_DATA * pConfigData\r
- )\r
-{\r
- UINTN DataSize;\r
- EFI_IP4_CONFIG2_INTERFACE_INFO * pIfInfo;\r
- EFI_IP4_CONFIG2_PROTOCOL * pIpConfig2Protocol;\r
- ESL_SERVICE * pService;\r
- EFI_STATUS Status;\r
-\r
- DBG_ENTER ( );\r
-\r
- //\r
- // Use break instead of goto\r
- //\r
- pIfInfo = NULL;\r
- for ( ; ; ) {\r
- //\r
- // Determine if the IP address is specified\r
- //\r
- DEBUG (( DEBUG_BIND,\r
- "UseDefaultAddress: %s\r\n",\r
- pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" ));\r
- DEBUG (( DEBUG_BIND,\r
- "Requested IP address: %d.%d.%d.%d\r\n",\r
- pConfigData->StationAddress.Addr [ 0 ],\r
- pConfigData->StationAddress.Addr [ 1 ],\r
- pConfigData->StationAddress.Addr [ 2 ],\r
- pConfigData->StationAddress.Addr [ 3 ]));\r
- if ( pConfigData->UseDefaultAddress\r
- || (( 0 == pConfigData->StationAddress.Addr [ 0 ])\r
- && ( 0 == pConfigData->StationAddress.Addr [ 1 ])\r
- && ( 0 == pConfigData->StationAddress.Addr [ 2 ])\r
- && ( 0 == pConfigData->StationAddress.Addr [ 3 ])))\r
- {\r
- Status = EFI_SUCCESS;\r
- break;\r
- }\r
-\r
- //\r
- // Open the configuration protocol\r
- //\r
- pService = pPort->pService;\r
- Status = gBS->OpenProtocol ( \r
- pService->Controller,\r
- &gEfiIp4Config2ProtocolGuid,\r
- (VOID **)&pIpConfig2Protocol,\r
- NULL,\r
- NULL,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL \r
- );\r
- if ( EFI_ERROR ( Status )) {\r
- DEBUG (( DEBUG_ERROR,\r
- "ERROR - IP Configuration Protocol not available, Status: %r\r\n",\r
- Status ));\r
- break;\r
- }\r
-\r
- //\r
- // Get the interface information size\r
- //\r
- DataSize = 0;\r
- Status = pIpConfig2Protocol->GetData ( \r
- pIpConfig2Protocol,\r
- Ip4Config2DataTypeInterfaceInfo,\r
- &DataSize,\r
- NULL\r
- );\r
- if ( EFI_BUFFER_TOO_SMALL != Status ) {\r
- DEBUG (( DEBUG_ERROR,\r
- "ERROR - Failed to get the interface information size, Status: %r\r\n",\r
- Status ));\r
- break;\r
- }\r
-\r
- //\r
- // Allocate the interface information buffer\r
- //\r
- pIfInfo = AllocatePool ( DataSize );\r
- if ( NULL == pIfInfo ) {\r
- DEBUG (( DEBUG_ERROR,\r
- "ERROR - Not enough memory to allocate the interface information buffer!\r\n" ));\r
- Status = EFI_OUT_OF_RESOURCES;\r
- break;\r
- }\r
-\r
- //\r
- // Get the interface info.\r
- //\r
- Status = pIpConfig2Protocol->GetData ( \r
- pIpConfig2Protocol,\r
- Ip4Config2DataTypeInterfaceInfo,\r
- &DataSize,\r
- pIfInfo\r
- );\r
- if ( EFI_ERROR ( Status )) {\r
- DEBUG (( DEBUG_ERROR,\r
- "ERROR - Failed to return the interface info, Status: %r\r\n",\r
- Status ));\r
- break;\r
- }\r
-\r
- //\r
- // Display the current configuration\r
- //\r
- DEBUG (( DEBUG_BIND,\r
- "Actual adapter IP address: %d.%d.%d.%d\r\n",\r
- pIfInfo->StationAddress.Addr [ 0 ],\r
- pIfInfo->StationAddress.Addr [ 1 ],\r
- pIfInfo->StationAddress.Addr [ 2 ],\r
- pIfInfo->StationAddress.Addr [ 3 ]));\r
-\r
- //\r
- // Assume the port is not configured\r
- //\r
- Status = EFI_SUCCESS;\r
- if (( pConfigData->StationAddress.Addr [ 0 ] == pIfInfo->StationAddress.Addr [ 0 ])\r
- && ( pConfigData->StationAddress.Addr [ 1 ] == pIfInfo->StationAddress.Addr [ 1 ])\r
- && ( pConfigData->StationAddress.Addr [ 2 ] == pIfInfo->StationAddress.Addr [ 2 ])\r
- && ( pConfigData->StationAddress.Addr [ 3 ] == pIfInfo->StationAddress.Addr [ 3 ])) {\r
- break;\r
- }\r
-\r
- //\r
- // The IP address did not match\r
- //\r
- Status = EFI_NOT_STARTED;\r
- break;\r
- }\r
-\r
- //\r
- // Free the buffer if necessary\r
- //\r
- if ( NULL != pIfInfo ) {\r
- FreePool ( pIfInfo );\r
- }\r
-\r
- //\r
- // Return the IP address status\r
- //\r
- DBG_EXIT_STATUS ( Status );\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Interface between the socket layer and the network specific\r
- code that supports SOCK_DGRAM sockets over UDPv4.\r
-**/\r
-CONST ESL_PROTOCOL_API cEslUdp4Api = {\r
- "UDPv4",\r
- IPPROTO_UDP,\r
- OFFSET_OF ( ESL_PORT, Context.Udp4.ConfigData ),\r
- OFFSET_OF ( ESL_LAYER, pUdp4List ),\r
- OFFSET_OF ( struct sockaddr_in, sin_zero ),\r
- sizeof ( struct sockaddr_in ),\r
- AF_INET,\r
- sizeof (((ESL_PACKET *)0 )->Op.Udp4Rx ),\r
- sizeof (((ESL_PACKET *)0 )->Op.Udp4Rx ),\r
- OFFSET_OF ( ESL_IO_MGMT, Token.Udp4Rx.Packet.RxData ),\r
- FALSE,\r
- EADDRINUSE,\r
- NULL, // Accept\r
- NULL, // ConnectPoll\r
- NULL, // ConnectStart\r
- EslUdp4SocketIsConfigured,\r
- EslUdp4LocalAddressGet,\r
- EslUdp4LocalAddressSet,\r
- NULL, // Listen\r
- NULL, // OptionGet\r
- NULL, // OptionSet\r
- EslUdp4PacketFree,\r
- EslUdp4PortAllocate,\r
- NULL, // PortClose,\r
- NULL, // PortCloseOp\r
- TRUE,\r
- EslUdp4Receive,\r
- EslUdp4RemoteAddressGet,\r
- EslUdp4RemoteAddressSet,\r
- EslUdp4RxComplete,\r
- NULL, // RxStart\r
- EslUdp4TxBuffer,\r
- EslUdp4TxComplete,\r
- NULL, // TxOobComplete\r
- (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslUdp4VerifyLocalIpAddress\r
-};\r