From a5cd246f513b5d7e9b6f8f2fde75f379e7eba2c3 Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 27 Apr 2017 11:38:57 +0800 Subject: StdLib: Remove unused Package Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- StdLib/EfiSocketLib/DxeSupport.c | 228 -- StdLib/EfiSocketLib/EfiSocketLib.inf | 70 - StdLib/EfiSocketLib/Init.c | 117 - StdLib/EfiSocketLib/Ip4.c | 1380 -------- StdLib/EfiSocketLib/ReleaseNotes.txt | 34 - StdLib/EfiSocketLib/Service.c | 479 --- StdLib/EfiSocketLib/Socket.c | 5795 --------------------------------- StdLib/EfiSocketLib/Socket.h | 1688 ---------- StdLib/EfiSocketLib/Tcp4.c | 2432 -------------- StdLib/EfiSocketLib/Tcp6.c | 2596 --------------- StdLib/EfiSocketLib/Udp4.c | 1232 ------- StdLib/EfiSocketLib/Udp6.c | 1379 -------- StdLib/EfiSocketLib/UseEfiSocketLib.c | 376 --- 13 files changed, 17806 deletions(-) delete mode 100644 StdLib/EfiSocketLib/DxeSupport.c delete mode 100644 StdLib/EfiSocketLib/EfiSocketLib.inf delete mode 100644 StdLib/EfiSocketLib/Init.c delete mode 100644 StdLib/EfiSocketLib/Ip4.c delete mode 100644 StdLib/EfiSocketLib/ReleaseNotes.txt delete mode 100644 StdLib/EfiSocketLib/Service.c delete mode 100644 StdLib/EfiSocketLib/Socket.c delete mode 100644 StdLib/EfiSocketLib/Socket.h delete mode 100644 StdLib/EfiSocketLib/Tcp4.c delete mode 100644 StdLib/EfiSocketLib/Tcp6.c delete mode 100644 StdLib/EfiSocketLib/Udp4.c delete mode 100644 StdLib/EfiSocketLib/Udp6.c delete mode 100644 StdLib/EfiSocketLib/UseEfiSocketLib.c (limited to 'StdLib/EfiSocketLib') diff --git a/StdLib/EfiSocketLib/DxeSupport.c b/StdLib/EfiSocketLib/DxeSupport.c deleted file mode 100644 index 9630aedcf8..0000000000 --- a/StdLib/EfiSocketLib/DxeSupport.c +++ /dev/null @@ -1,228 +0,0 @@ -/** @file - SocketDxe support routines - - Copyright (c) 2011, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "Socket.h" - - -/** - Creates a child handle and installs gEfiSocketProtocolGuid. - - This routine creates a child handle for the socket driver and - installs the ::gEfiSocketProtocolGuid on that handle with a pointer - to the ::EFI_SOCKET_PROTOCOL structure address. - - This routine is called by ::EslServiceGetProtocol in UseSocketDxe - when the socket application is linked with UseSocketDxe. - - @param [in] pThis Address of the EFI_SERVICE_BINDING_PROTOCOL structure. - @param [in] pChildHandle Pointer to the handle of the child to create. If it is NULL, - then a new handle is created. If it is a pointer to an existing UEFI handle, - then the protocol is added to the existing UEFI handle. - - @retval EFI_SUCCESS The protocol was added to ChildHandle. - @retval EFI_INVALID_PARAMETER ChildHandle is NULL. - @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create - the child - @retval other The child handle was not created - -**/ -EFI_STATUS -EFIAPI -EslDxeCreateChild ( - IN EFI_SERVICE_BINDING_PROTOCOL * pThis, - IN OUT EFI_HANDLE * pChildHandle - ) -{ - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Create a socket structure - // - Status = EslSocketAllocate ( pChildHandle, - DEBUG_SOCKET, - &pSocket ); - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Removes gEfiSocketProtocolGuid and destroys the child handle. - - This routine uninstalls ::gEfiSocketProtocolGuid from the child handle - and destroys the child handle if necessary. - - This routine is called from ???. - - @param [in] pThis Address of the EFI_SERVICE_BINDING_PROTOCOL structure. - @param [in] ChildHandle Handle of the child to destroy - - @retval EFI_SUCCESS The protocol was removed from ChildHandle. - @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed. - @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle. - @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle - because its services are being used. - @retval other The child handle was not destroyed - -**/ -EFI_STATUS -EFIAPI -EslDxeDestroyChild ( - IN EFI_SERVICE_BINDING_PROTOCOL * pThis, - IN EFI_HANDLE ChildHandle - ) -{ - ESL_LAYER * pLayer; - EFI_SOCKET_PROTOCOL * pSocketProtocol; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the socket control structure - // - pLayer = &mEslLayer; - Status = gBS->OpenProtocol ( - ChildHandle, - &gEfiSocketProtocolGuid, - (VOID **)&pSocketProtocol, - pLayer->ImageHandle, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if ( !EFI_ERROR ( Status )) { - // - // Free the socket resources - // - Status = EslSocketFree ( pSocketProtocol, NULL ); - } - else { - DEBUG (( DEBUG_ERROR, - "ERROR - Failed to open socket protocol on 0x%08x, Status; %r\r\n", - ChildHandle, - Status )); - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** -Install the socket service - -This routine installs the ::gEfiSocketServiceBindingProtocolGuid -on the SocketDxe image handle to announce the availability -of the socket layer to the rest of EFI. - -SocketDxe's EntryPoint routine calls this routine to -make the socket layer available. - -@param [in] pImageHandle Address of the image handle - -@retval EFI_SUCCESS Service installed successfully -**/ -EFI_STATUS -EFIAPI -EslDxeInstall ( - IN EFI_HANDLE * pImageHandle - ) -{ - EFI_STATUS Status; - - // - // Install the socket service binding protocol - // - Status = gBS->InstallMultipleProtocolInterfaces ( - pImageHandle, - &gEfiSocketServiceBindingProtocolGuid, - mEslLayer.pServiceBinding, - NULL - ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, - "Installed: gEfiSocketServiceBindingProtocolGuid on 0x%08x\r\n", - *pImageHandle )); - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT, - "ERROR - InstallMultipleProtocolInterfaces failed, Status: %r\r\n", - Status )); - } - - // - // Return the operation status - // - return Status; -} - - -/** -Uninstall the socket service - -This routine removes the gEfiSocketServiceBindingProtocolGuid from -the SocketDxe image handle to notify EFI that the socket layer -is no longer available. - -SocketDxe's DriverUnload routine calls this routine to remove the -socket layer. - -@param [in] ImageHandle Handle for the image. - -@retval EFI_SUCCESS Service installed successfully -**/ -EFI_STATUS -EFIAPI -EslDxeUninstall ( - IN EFI_HANDLE ImageHandle - ) -{ - EFI_STATUS Status; - - // - // Install the socket service binding protocol - // - Status = gBS->UninstallMultipleProtocolInterfaces ( - ImageHandle, - &gEfiSocketServiceBindingProtocolGuid, - mEslLayer.pServiceBinding, - NULL - ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_POOL | DEBUG_INIT, - "Removed: gEfiSocketServiceBindingProtocolGuid from 0x%08x\r\n", - ImageHandle )); - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT, - "ERROR - Failed to remove gEfiSocketServiceBindingProtocolGuid from 0x%08x, Status: %r\r\n", - ImageHandle, - Status )); - } - - // - // Return the operation status - // - return Status; -} diff --git a/StdLib/EfiSocketLib/EfiSocketLib.inf b/StdLib/EfiSocketLib/EfiSocketLib.inf deleted file mode 100644 index 29e06ec3e1..0000000000 --- a/StdLib/EfiSocketLib/EfiSocketLib.inf +++ /dev/null @@ -1,70 +0,0 @@ -#/** @file -# Component description file for the EFI socket library. -# -# This module implements the socket layer. -# Copyright (c) 2011 - 2015, Intel Corporation -# -# All rights reserved. This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# -#**/ - -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = EfiSocketLib - FILE_GUID = C33E0B7C-9D0F-41df-BDFD-08F5E4C39EE8 - MODULE_TYPE = BASE - VERSION_STRING = 1.0 - LIBRARY_CLASS = EfiSocketLib - CONSTRUCTOR = EslConstructor - DESTRUCTOR = EslDestructor - -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources.common] - DxeSupport.c - Init.c - Ip4.c - Service.c - Socket.c - Tcp4.c - Tcp6.c - Udp4.c - Udp6.c - UseEfiSocketLib.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - StdLib/StdLib.dec - -[LibraryClasses] - BaseMemoryLib - DebugLib - MemoryAllocationLib - UefiBootServicesTableLib - UefiLib - -[Protocols] - gEfiIp4Config2ProtocolGuid - gEfiIp6ConfigProtocolGuid - gEfiIp4ProtocolGuid - gEfiIp4ServiceBindingProtocolGuid - gEfiIp6ProtocolGuid - gEfiIp6ServiceBindingProtocolGuid - gEfiTcp4ProtocolGuid - gEfiTcp4ServiceBindingProtocolGuid - gEfiTcp6ProtocolGuid - gEfiTcp6ServiceBindingProtocolGuid - gEfiUdp4ProtocolGuid - gEfiUdp4ServiceBindingProtocolGuid - gEfiUdp6ProtocolGuid - gEfiUdp6ServiceBindingProtocolGuid - gEfiSocketProtocolGuid - gEfiSocketServiceBindingProtocolGuid diff --git a/StdLib/EfiSocketLib/Init.c b/StdLib/EfiSocketLib/Init.c deleted file mode 100644 index 88d2065c21..0000000000 --- a/StdLib/EfiSocketLib/Init.c +++ /dev/null @@ -1,117 +0,0 @@ -/** @file - Implement the constructor and destructor for the EFI socket library - - Copyright (c) 2011, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license. - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "Socket.h" - - -/** - EFI Socket Library Constructor - - This routine supports an implementation dependent constructor - depending upon whether the library is linked to a socket - application or the SocketDxe driver. The following modules - declare the redirection for the constructor in ::mpfnEslConstructor: - - - The EfiSocketLib.inf file lists ::EslConstructor as the CONSTRUCTOR - in the [Defines] section. As a result, this routine is called by - the ProcessLibraryConstructorList routine of the AutoGen.c module - in the Build directory associated with the socket application or - the SocketDxe driver. - - @retval EFI_SUCCESS The socket layer initialization was successful - - **/ -EFI_STATUS -EFIAPI -EslConstructor ( - VOID - ) -{ - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Call the image dependent constructor if available - // - if ( NULL != mpfnEslConstructor ) { - Status = mpfnEslConstructor ( ); - } - - // - // Return the constructor status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - EFI Socket Library Destructor - - This routine supports an implementation dependent destructor - depending upon whether the library is linked to a socket - application or the SocketDxe driver. The following modules - declare the redirection for the destructor in ::mpfnEslDestructor: - - - The EfiSocketLib.inf file lists ::EslDestructor as the DESTRUCTOR - in the [Defines] section. As a result, this routine is called by - the ProcessLibraryDestructorList routine of the AutoGen.c module - in the Build directory associated with the socket application or - the SocketDxe driver. - - @retval EFI_SUCCESS The socket layer shutdown was successful - - **/ -EFI_STATUS -EFIAPI -EslDestructor ( - VOID - ) -{ - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Call the image dependent destructor if available - // - if ( NULL != mpfnEslDestructor ) { - Status = mpfnEslDestructor ( ); - } - - // - // Return the constructor status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} diff --git a/StdLib/EfiSocketLib/Ip4.c b/StdLib/EfiSocketLib/Ip4.c deleted file mode 100644 index d3531b8928..0000000000 --- a/StdLib/EfiSocketLib/Ip4.c +++ /dev/null @@ -1,1380 +0,0 @@ -/** @file - Implement the IP4 driver support for the socket layer. - - Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
- This program and the accompanying materials are licensed and made available - under the terms and conditions of the BSD License which accompanies this - distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php. - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -**/ -#include "Socket.h" - - -/** Get the local socket address. - - This routine returns the IPv4 address associated with the local - socket. - - This routine is called by ::EslSocketGetLocalAddress to determine the - network address for the SOCK_RAW socket. - - @param [in] pPort Address of an ::ESL_PORT structure. - @param [out] pAddress Network address to receive the local system address -**/ -VOID -EslIp4LocalAddressGet ( - IN ESL_PORT * pPort, - OUT struct sockaddr * pAddress - ) -{ - struct sockaddr_in * pLocalAddress; - ESL_IP4_CONTEXT * pIp4; - - DBG_ENTER ( ); - - // Return the local address - pIp4 = &pPort->Context.Ip4; - pLocalAddress = (struct sockaddr_in *)pAddress; - pLocalAddress->sin_family = AF_INET; - CopyMem ( &pLocalAddress->sin_addr, - &pIp4->ModeData.ConfigData.StationAddress.Addr[0], - sizeof ( pLocalAddress->sin_addr )); - - DBG_EXIT ( ); -} - - -/** Set the local port address. - - This routine sets the local port address. - - This support routine is called by ::EslSocketPortAllocate. - - @param [in] pPort Address of an ESL_PORT structure - @param [in] pSockAddr Address of a sockaddr structure that contains the - connection point on the local machine. An IPv4 address - of INADDR_ANY specifies that the connection is made to - all of the network stacks on the platform. Specifying a - specific IPv4 address restricts the connection to the - network stack supporting that address. Specifying zero - for the port causes the network layer to assign a port - number from the dynamic range. Specifying a specific - port number causes the network layer to use that port. - - @param [in] bBindTest TRUE = run bind testing - - @retval EFI_SUCCESS The operation was successful - **/ -EFI_STATUS -EslIp4LocalAddressSet ( - IN ESL_PORT * pPort, - IN CONST struct sockaddr * pSockAddr, - IN BOOLEAN bBindTest - ) -{ - EFI_IP4_CONFIG_DATA * pConfig; - CONST struct sockaddr_in * pIpAddress; - CONST UINT8 * pIpv4Address; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // Validate the address - pIpAddress = (struct sockaddr_in *)pSockAddr; - if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) { - // The local address must not be the broadcast address - Status = EFI_INVALID_PARAMETER; - pPort->pSocket->errno = EADDRNOTAVAIL; - } - else { - Status = EFI_SUCCESS; - - // Set the local address - pIpAddress = (struct sockaddr_in *)pSockAddr; - pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr; - pConfig = &pPort->Context.Ip4.ModeData.ConfigData; - pConfig->StationAddress.Addr[0] = pIpv4Address[0]; - pConfig->StationAddress.Addr[1] = pIpv4Address[1]; - pConfig->StationAddress.Addr[2] = pIpv4Address[2]; - pConfig->StationAddress.Addr[3] = pIpv4Address[3]; - - // Determine if the default address is used - pConfig->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr ); - - // Display the local address - DEBUG (( DEBUG_BIND, - "0x%08x: Port, Local IP4 Address: %d.%d.%d.%d\r\n", - pPort, - pConfig->StationAddress.Addr[0], - pConfig->StationAddress.Addr[1], - pConfig->StationAddress.Addr[2], - pConfig->StationAddress.Addr[3])); - - // Set the subnet mask - if ( pConfig->UseDefaultAddress ) { - pConfig->SubnetMask.Addr[0] = 0; - pConfig->SubnetMask.Addr[1] = 0; - pConfig->SubnetMask.Addr[2] = 0; - pConfig->SubnetMask.Addr[3] = 0; - } - else { - pConfig->SubnetMask.Addr[0] = 0xff; - pConfig->SubnetMask.Addr[1] = ( 128 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0; - pConfig->SubnetMask.Addr[2] = ( 192 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0; - pConfig->SubnetMask.Addr[3] = ( 224 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0; - } - } - // Return the operation status - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Get the option value. - - This routine handles the IPv4 level options. - - The ::EslSocketOptionGet routine calls this routine to retrieve - the IPv4 options one at a time by name. - - @param [in] pSocket Address of an ::ESL_SOCKET structure - @param [in] OptionName Name of the option - @param [out] ppOptionData Buffer to receive address of option value - @param [out] pOptionLength Buffer to receive the option length - - @retval EFI_SUCCESS - Socket data successfully received - **/ -EFI_STATUS -EslIp4OptionGet ( - IN ESL_SOCKET * pSocket, - IN int OptionName, - OUT CONST void ** __restrict ppOptionData, - OUT socklen_t * __restrict pOptionLength - ) -{ - EFI_STATUS Status; - - DBG_ENTER ( ); - - // Assume success - pSocket->errno = 0; - Status = EFI_SUCCESS; - - // Attempt to get the option - switch ( OptionName ) { - default: - // Option not supported - pSocket->errno = ENOPROTOOPT; - Status = EFI_INVALID_PARAMETER; - break; - - case IP_HDRINCL: - *ppOptionData = (void *)&pSocket->bIncludeHeader; - *pOptionLength = sizeof ( pSocket->bIncludeHeader ); - break; - } - // Return the operation status - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Set the option value. - - This routine handles the IPv4 level options. - - The ::EslSocketOptionSet routine calls this routine to adjust - the IPv4 options one at a time by name. - - @param [in] pSocket Address of an ::ESL_SOCKET structure - @param [in] OptionName Name of the option - @param [in] pOptionValue Buffer containing the option value - @param [in] OptionLength Length of the buffer in bytes - - @retval EFI_SUCCESS - Option successfully set - **/ -EFI_STATUS -EslIp4OptionSet ( - IN ESL_SOCKET * pSocket, - IN int OptionName, - IN CONST void * pOptionValue, - IN socklen_t OptionLength - ) -{ - BOOLEAN bTrueFalse; - //socklen_t LengthInBytes; - //UINT8 * pOptionData; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // Assume success - pSocket->errno = 0; - Status = EFI_SUCCESS; - - // Determine if the option protocol matches - //LengthInBytes = 0; - //pOptionData = NULL; - switch ( OptionName ) { - default: - // Protocol level not supported - DEBUG (( DEBUG_INFO | DEBUG_OPTION, "ERROR - Invalid protocol option\r\n" )); - pSocket->errno = ENOTSUP; - Status = EFI_UNSUPPORTED; - break; - - case IP_HDRINCL: - - // Validate the option length - if ( sizeof ( UINT32 ) == OptionLength ) { - // Restrict the input to TRUE or FALSE - bTrueFalse = TRUE; - if ( 0 == *(UINT32 *)pOptionValue ) { - bTrueFalse = FALSE; - } - pOptionValue = &bTrueFalse; - - // Set the option value - //pOptionData = (UINT8 *)&pSocket->bIncludeHeader; - //LengthInBytes = sizeof ( pSocket->bIncludeHeader ); - } - break; - } - // Return the operation status - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Free a receive packet - - This routine performs the network specific operations necessary - to free a receive packet. - - This routine is called by ::EslSocketPortCloseTxDone to free a - receive packet. - - @param [in] pPacket Address of an ::ESL_PACKET structure. - @param [in, out] pRxBytes Address of the count of RX bytes - -**/ -VOID -EslIp4PacketFree ( - IN ESL_PACKET * pPacket, - IN OUT size_t * pRxBytes - ) -{ - EFI_IP4_RECEIVE_DATA * pRxData; - DBG_ENTER ( ); - - // - // Account for the receive bytes - // - pRxData = pPacket->Op.Ip4Rx.pRxData; - *pRxBytes -= pRxData->HeaderLength + pRxData->DataLength; - - // - // Disconnect the buffer from the packet - // - pPacket->Op.Ip4Rx.pRxData = NULL; - - // - // Return the buffer to the IP4 driver - // - gBS->SignalEvent ( pRxData->RecycleSignal ); - DBG_EXIT ( ); -} - - -/** - Initialize the network specific portions of an ::ESL_PORT structure. - - This routine initializes the network specific portions of an - ::ESL_PORT structure for use by the socket. - - This support routine is called by ::EslSocketPortAllocate - to connect the socket with the underlying network adapter - running the IPv4 protocol. - - @param [in] pPort Address of an ESL_PORT structure - @param [in] DebugFlags Flags for debug messages - - @retval EFI_SUCCESS - Socket successfully created - - **/ -EFI_STATUS -EslIp4PortAllocate ( - IN ESL_PORT * pPort, - IN UINTN DebugFlags - ) -{ - EFI_IP4_CONFIG_DATA * pConfig; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Initialize the port - // - pSocket = pPort->pSocket; - pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Ip4Tx.TxData ); - pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Tx.Event ); - pSocket->TxTokenOffset = OFFSET_OF ( EFI_IP4_COMPLETION_TOKEN, Packet.TxData ); - - // - // Save the cancel, receive and transmit addresses - // - pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.IPv4->Configure; - pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Cancel; - pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.IPv4->Poll; - pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Receive; - pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Transmit; - - // - // Set the configuration flags - // - pConfig = &pPort->Context.Ip4.ModeData.ConfigData; - pConfig->AcceptIcmpErrors = FALSE; - pConfig->AcceptBroadcast = FALSE; - pConfig->AcceptPromiscuous = FALSE; - pConfig->TypeOfService = 0; - pConfig->TimeToLive = 255; - pConfig->DoNotFragment = FALSE; - pConfig->RawData = FALSE; - pConfig->ReceiveTimeout = 0; - pConfig->TransmitTimeout = 0; - - // - // Set the default protocol - // - pConfig->DefaultProtocol = (UINT8)pSocket->Protocol; - pConfig->AcceptAnyProtocol = (BOOLEAN)( 0 == pConfig->DefaultProtocol ); - Status = EFI_SUCCESS; - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Receive data from a network connection. - - This routine attempts to return buffered data to the caller. The - data is removed from the urgent queue if the message flag MSG_OOB - is specified, otherwise data is removed from the normal queue. - See the \ref ReceiveEngine section. - - This routine is called by ::EslSocketReceive to handle the network - specific receive operation to support SOCK_RAW sockets. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [in] pPacket Address of an ::ESL_PACKET structure. - - @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @param [out] pAddress Network address to receive the remote system address - - @param [out] pSkipBytes Address to receive the number of bytes skipped - - @return Returns the address of the next free byte in the buffer. - - **/ -UINT8 * -EslIp4Receive ( - IN ESL_PORT * pPort, - IN ESL_PACKET * pPacket, - IN BOOLEAN * pbConsumePacket, - IN size_t BufferLength, - IN UINT8 * pBuffer, - OUT size_t * pDataLength, - OUT struct sockaddr * pAddress, - OUT size_t * pSkipBytes - ) -{ - size_t DataBytes; - size_t HeaderBytes; - size_t LengthInBytes; - struct sockaddr_in * pRemoteAddress; - EFI_IP4_RECEIVE_DATA * pRxData; - - DBG_ENTER ( ); - - // - // Return the remote system address if requested - // - pRxData = pPacket->Op.Ip4Rx.pRxData; - if ( NULL != pAddress ) { - // - // Build the remote address - // - DEBUG (( DEBUG_RX, - "Getting packet remote address: %d.%d.%d.%d\r\n", - pRxData->Header->SourceAddress.Addr[0], - pRxData->Header->SourceAddress.Addr[1], - pRxData->Header->SourceAddress.Addr[2], - pRxData->Header->SourceAddress.Addr[3])); - pRemoteAddress = (struct sockaddr_in *)pAddress; - CopyMem ( &pRemoteAddress->sin_addr, - &pRxData->Header->SourceAddress.Addr[0], - sizeof ( pRemoteAddress->sin_addr )); - } - - // - // Copy the IP header - // - HeaderBytes = pRxData->HeaderLength; - if ( HeaderBytes > BufferLength ) { - HeaderBytes = BufferLength; - } - DEBUG (( DEBUG_RX, - "0x%08x --> 0x%08x: Copy header 0x%08x bytes\r\n", - pRxData->Header, - pBuffer, - HeaderBytes )); - CopyMem ( pBuffer, pRxData->Header, HeaderBytes ); - pBuffer += HeaderBytes; - LengthInBytes = HeaderBytes; - - // - // Copy the received data - // - if ( 0 < ( BufferLength - LengthInBytes )) { - pBuffer = EslSocketCopyFragmentedBuffer ( pRxData->FragmentCount, - &pRxData->FragmentTable[0], - BufferLength - LengthInBytes, - pBuffer, - &DataBytes ); - LengthInBytes += DataBytes; - } - - // - // Determine if the data is being read - // - if ( *pbConsumePacket ) { - // - // Display for the bytes consumed - // - DEBUG (( DEBUG_RX, - "0x%08x: Port account for 0x%08x bytes\r\n", - pPort, - LengthInBytes )); - - // - // Account for any discarded data - // - *pSkipBytes = pRxData->HeaderLength + pRxData->DataLength - LengthInBytes; - } - - // - // Return the data length and the buffer address - // - *pDataLength = LengthInBytes; - DBG_EXIT_HEX ( pBuffer ); - return pBuffer; -} - - -/** - Get the remote socket address - - This routine returns the address of the remote connection point - associated with the SOCK_RAW socket. - - This routine is called by ::EslSocketGetPeerAddress to detemine - the IPv4 address associated with the network adapter. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [out] pAddress Network address to receive the remote system address - -**/ -VOID -EslIp4RemoteAddressGet ( - IN ESL_PORT * pPort, - OUT struct sockaddr * pAddress - ) -{ - struct sockaddr_in * pRemoteAddress; - ESL_IP4_CONTEXT * pIp4; - - DBG_ENTER ( ); - - // - // Return the remote address - // - pIp4 = &pPort->Context.Ip4; - pRemoteAddress = (struct sockaddr_in *)pAddress; - pRemoteAddress->sin_family = AF_INET; - CopyMem ( &pRemoteAddress->sin_addr, - &pIp4->DestinationAddress.Addr[0], - sizeof ( pRemoteAddress->sin_addr )); - - DBG_EXIT ( ); -} - - -/** - Set the remote address - - This routine sets the remote address in the port. - - This routine is called by ::EslSocketConnect to specify the - remote network address. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [in] pSockAddr Network address of the remote system. - - @param [in] SockAddrLength Length in bytes of the network address. - - @retval EFI_SUCCESS The operation was successful - - **/ -EFI_STATUS -EslIp4RemoteAddressSet ( - IN ESL_PORT * pPort, - IN CONST struct sockaddr * pSockAddr, - IN socklen_t SockAddrLength - ) -{ - ESL_IP4_CONTEXT * pIp4; - CONST struct sockaddr_in * pRemoteAddress; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Set the remote address - // - pIp4 = &pPort->Context.Ip4; - pRemoteAddress = (struct sockaddr_in *)pSockAddr; - pIp4->DestinationAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr ); - pIp4->DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 ); - pIp4->DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 ); - pIp4->DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 ); - pPort->pSocket->bAddressSet = TRUE; - Status = EFI_SUCCESS; - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the receive completion - - This routine keeps the IPv4 driver's buffer and queues it in - in FIFO order to the data queue. The IP4 driver's buffer will - be returned by either ::EslIp4Receive or ::EslSocketPortCloseTxDone. - See the \ref ReceiveEngine section. - - This routine is called by the IPv4 driver when data is - received. - - @param [in] Event The receive completion event - - @param [in] pIo The address of an ::ESL_IO_MGMT structure - -**/ -VOID -EslIp4RxComplete ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ) -{ - size_t LengthInBytes; - ESL_PACKET * pPacket; - EFI_IP4_RECEIVE_DATA * pRxData; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Get the operation status. - // - Status = pIo->Token.Ip4Rx.Status; - - // - // Get the packet length - // - pRxData = pIo->Token.Ip4Rx.Packet.RxData; - LengthInBytes = pRxData->HeaderLength + pRxData->DataLength; - - //{{ - // +--------------------+ +----------------------+ - // | ESL_IO_MGMT | | Data Buffer | - // | | | (Driver owned) | - // | +---------------+ +----------------------+ - // | | Token | ^ - // | | Rx Event | | - // | | | +----------------------+ - // | | RxData --> | EFI_IP4_RECEIVE_DATA | - // +----+---------------+ | (Driver owned) | - // +----------------------+ - // +--------------------+ ^ - // | ESL_PACKET | . - // | | . - // | +---------------+ . - // | | pRxData --> NULL ....... - // +----+---------------+ - // - // - // Save the data in the packet - //}} - pPacket = pIo->pPacket; - pPacket->Op.Ip4Rx.pRxData = pRxData; - - // - // Complete this request - // - EslSocketRxComplete ( pIo, Status, LengthInBytes, FALSE ); - DBG_EXIT ( ); -} - - -/** - Determine if the socket is configured. - - This routine uses the flag ESL_SOCKET::bConfigured to determine - if the network layer's configuration routine has been called. - This routine calls the ::EslSocketBind and configuration routines - if they were not already called. After the port is configured, - the \ref ReceiveEngine is started. - - This routine is called by EslSocketIsConfigured to verify - that the socket is configured. - - @param [in] pSocket Address of an ::ESL_SOCKET structure - - @retval EFI_SUCCESS - The port is connected - @retval EFI_NOT_STARTED - The port is not connected - - **/ - EFI_STATUS - EslIp4SocketIsConfigured ( - IN ESL_SOCKET * pSocket - ) -{ - UINTN Index; - ESL_PORT * pPort; - ESL_PORT * pNextPort; - ESL_IP4_CONTEXT * pIp4; - EFI_IP4_PROTOCOL * pIp4Protocol; - EFI_STATUS Status; - struct sockaddr_in LocalAddress; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Configure the port if necessary - // - if ( !pSocket->bConfigured ) { - // - // Fill in the port list if necessary - // - pSocket->errno = ENETDOWN; - if ( NULL == pSocket->pPortList ) { - LocalAddress.sin_len = sizeof ( LocalAddress ); - LocalAddress.sin_family = AF_INET; - LocalAddress.sin_addr.s_addr = 0; - LocalAddress.sin_port = 0; - Status = EslSocketBind ( &pSocket->SocketProtocol, - (struct sockaddr *)&LocalAddress, - LocalAddress.sin_len, - &pSocket->errno ); - } - - // - // Walk the port list - // - pPort = pSocket->pPortList; - while ( NULL != pPort ) { - // - // Update the raw setting - // - pIp4 = &pPort->Context.Ip4; - if ( pSocket->bIncludeHeader ) { - // - // IP header will be included with the data on transmit - // - pIp4->ModeData.ConfigData.RawData = TRUE; - } - - // - // Attempt to configure the port - // - pNextPort = pPort->pLinkSocket; - pIp4Protocol = pPort->pProtocol.IPv4; - DEBUG (( DEBUG_TX, - "0x%08x: pPort Configuring for %d.%d.%d.%d --> %d.%d.%d.%d\r\n", - pPort, - pIp4->ModeData.ConfigData.StationAddress.Addr[0], - pIp4->ModeData.ConfigData.StationAddress.Addr[1], - pIp4->ModeData.ConfigData.StationAddress.Addr[2], - pIp4->ModeData.ConfigData.StationAddress.Addr[3], - pIp4->DestinationAddress.Addr[0], - pIp4->DestinationAddress.Addr[1], - pIp4->DestinationAddress.Addr[2], - pIp4->DestinationAddress.Addr[3])); - Status = pIp4Protocol->Configure ( pIp4Protocol, - &pIp4->ModeData.ConfigData ); - if ( !EFI_ERROR ( Status )) { - // - // Update the configuration data - // - Status = pIp4Protocol->GetModeData ( pIp4Protocol, - &pIp4->ModeData, - NULL, - NULL ); - } - if ( EFI_ERROR ( Status )) { - if ( !pSocket->bConfigured ) { - DEBUG (( DEBUG_LISTEN, - "ERROR - Failed to configure the Ip4 port, Status: %r\r\n", - Status )); - switch ( Status ) { - case EFI_ACCESS_DENIED: - pSocket->errno = EACCES; - break; - - default: - case EFI_DEVICE_ERROR: - pSocket->errno = EIO; - break; - - case EFI_INVALID_PARAMETER: - pSocket->errno = EADDRNOTAVAIL; - break; - - case EFI_NO_MAPPING: - pSocket->errno = EAFNOSUPPORT; - break; - - case EFI_OUT_OF_RESOURCES: - pSocket->errno = ENOBUFS; - break; - - case EFI_UNSUPPORTED: - pSocket->errno = EOPNOTSUPP; - break; - } - } - } - else { - DEBUG (( DEBUG_TX, - "0x%08x: pPort Configured for %d.%d.%d.%d --> %d.%d.%d.%d\r\n", - pPort, - pIp4->ModeData.ConfigData.StationAddress.Addr[0], - pIp4->ModeData.ConfigData.StationAddress.Addr[1], - pIp4->ModeData.ConfigData.StationAddress.Addr[2], - pIp4->ModeData.ConfigData.StationAddress.Addr[3], - pIp4->DestinationAddress.Addr[0], - pIp4->DestinationAddress.Addr[1], - pIp4->DestinationAddress.Addr[2], - pIp4->DestinationAddress.Addr[3])); - DEBUG (( DEBUG_TX, - "Subnet Mask: %d.%d.%d.%d\r\n", - pIp4->ModeData.ConfigData.SubnetMask.Addr[0], - pIp4->ModeData.ConfigData.SubnetMask.Addr[1], - pIp4->ModeData.ConfigData.SubnetMask.Addr[2], - pIp4->ModeData.ConfigData.SubnetMask.Addr[3])); - DEBUG (( DEBUG_TX, - "Route Count: %d\r\n", - pIp4->ModeData.RouteCount )); - for ( Index = 0; pIp4->ModeData.RouteCount > Index; Index++ ) { - if ( 0 == Index ) { - DEBUG (( DEBUG_TX, "Route Table:\r\n" )); - } - DEBUG (( DEBUG_TX, - "%5d: %d.%d.%d.%d, %d.%d.%d.%d ==> %d.%d.%d.%d\r\n", - Index, - pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[0], - pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[1], - pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[2], - pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[3], - pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[0], - pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[1], - pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[2], - pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[3], - pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[0], - pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[1], - pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[2], - pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[3])); - } - pPort->bConfigured = TRUE; - pSocket->bConfigured = TRUE; - - // - // Start the first read on the port - // - EslSocketRxStart ( pPort ); - - // - // The socket is connected - // - pSocket->State = SOCKET_STATE_CONNECTED; - pSocket->errno = 0; - } - - // - // Set the next port - // - pPort = pNextPort; - } - } - - // - // Determine the socket configuration status - // - Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED; - - // - // Return the port connected state. - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Buffer data for transmission over a network connection. - - This routine buffers data for the transmit engine in the normal - data queue. When the \ref TransmitEngine has resources, this - routine will start the transmission of the next buffer on the - network connection. - - This routine is called by ::EslSocketTransmit to buffer - data for transmission. The data is copied into a local buffer - freeing the application buffer for reuse upon return. When - necessary, this routine starts the transmit engine that - performs the data transmission on the network connection. The - transmit engine transmits the data a packet at a time over the - network connection. - - Transmission errors are returned during the next transmission or - during the close operation. Only buffering errors are returned - during the current transmission attempt. - - @param [in] pSocket Address of an ::ESL_SOCKET structure - - @param [in] Flags Message control flags - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @param [in] pAddress Network address of the remote system address - - @param [in] AddressLength Length of the remote network address structure - - @retval EFI_SUCCESS - Socket data successfully buffered - -**/ -EFI_STATUS -EslIp4TxBuffer ( - IN ESL_SOCKET * pSocket, - IN int Flags, - IN size_t BufferLength, - IN CONST UINT8 * pBuffer, - OUT size_t * pDataLength, - IN const struct sockaddr * pAddress, - IN socklen_t AddressLength - ) -{ - ESL_PACKET * pPacket; - ESL_PACKET * pPreviousPacket; - ESL_PORT * pPort; - const struct sockaddr_in * pRemoteAddress; - ESL_IP4_CONTEXT * pIp4; - size_t * pTxBytes; - ESL_IP4_TX_DATA * pTxData; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume failure - // - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTCONN; - *pDataLength = 0; - - // - // Verify that the socket is connected - // - if ( SOCKET_STATE_CONNECTED == pSocket->State ) { - // - // Verify that there is enough room to buffer another - // transmit operation - // - pTxBytes = &pSocket->TxBytes; - if ( pSocket->MaxTxBuf > *pTxBytes ) { - // - // Locate the port - // - pPort = pSocket->pPortList; - while ( NULL != pPort ) { - // - // Determine the queue head - // - pIp4 = &pPort->Context.Ip4; - - // - // Attempt to allocate the packet - // - Status = EslSocketPacketAllocate ( &pPacket, - sizeof ( pPacket->Op.Ip4Tx ) - - sizeof ( pPacket->Op.Ip4Tx.Buffer ) - + BufferLength, - 0, - DEBUG_TX ); - if ( !EFI_ERROR ( Status )) { - // - // Initialize the transmit operation - // - pTxData = &pPacket->Op.Ip4Tx; - pTxData->TxData.DestinationAddress.Addr[0] = pIp4->DestinationAddress.Addr[0]; - pTxData->TxData.DestinationAddress.Addr[1] = pIp4->DestinationAddress.Addr[1]; - pTxData->TxData.DestinationAddress.Addr[2] = pIp4->DestinationAddress.Addr[2]; - pTxData->TxData.DestinationAddress.Addr[3] = pIp4->DestinationAddress.Addr[3]; - pTxData->TxData.OverrideData = NULL; - pTxData->TxData.OptionsLength = 0; - pTxData->TxData.OptionsBuffer = NULL; - pTxData->TxData.TotalDataLength = (UINT32) BufferLength; - pTxData->TxData.FragmentCount = 1; - pTxData->TxData.FragmentTable[0].FragmentLength = (UINT32) BufferLength; - pTxData->TxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Ip4Tx.Buffer[0]; - - // - // Set the remote system address if necessary - // - if ( NULL != pAddress ) { - pRemoteAddress = (const struct sockaddr_in *)pAddress; - pTxData->Override.SourceAddress.Addr[0] = pIp4->ModeData.ConfigData.StationAddress.Addr[0]; - pTxData->Override.SourceAddress.Addr[1] = pIp4->ModeData.ConfigData.StationAddress.Addr[1]; - pTxData->Override.SourceAddress.Addr[2] = pIp4->ModeData.ConfigData.StationAddress.Addr[2]; - pTxData->Override.SourceAddress.Addr[3] = pIp4->ModeData.ConfigData.StationAddress.Addr[3]; - pTxData->TxData.DestinationAddress.Addr[0] = (UINT8)pRemoteAddress->sin_addr.s_addr; - pTxData->TxData.DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 ); - pTxData->TxData.DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 ); - pTxData->TxData.DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 ); - pTxData->Override.GatewayAddress.Addr[0] = 0; - pTxData->Override.GatewayAddress.Addr[1] = 0; - pTxData->Override.GatewayAddress.Addr[2] = 0; - pTxData->Override.GatewayAddress.Addr[3] = 0; - pTxData->Override.Protocol = (UINT8)pSocket->Protocol; - pTxData->Override.TypeOfService = 0; - pTxData->Override.TimeToLive = 255; - pTxData->Override.DoNotFragment = FALSE; - - // - // Use the remote system address when sending this packet - // - pTxData->TxData.OverrideData = &pTxData->Override; - } - - // - // Copy the data into the buffer - // - CopyMem ( &pPacket->Op.Ip4Tx.Buffer[0], - pBuffer, - BufferLength ); - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Display the request - // - DEBUG (( DEBUG_TX, - "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n", - BufferLength, - pBuffer, - pIp4->ModeData.ConfigData.StationAddress.Addr[0], - pIp4->ModeData.ConfigData.StationAddress.Addr[1], - pIp4->ModeData.ConfigData.StationAddress.Addr[2], - pIp4->ModeData.ConfigData.StationAddress.Addr[3], - pTxData->TxData.DestinationAddress.Addr[0], - pTxData->TxData.DestinationAddress.Addr[1], - pTxData->TxData.DestinationAddress.Addr[2], - pTxData->TxData.DestinationAddress.Addr[3])); - - // - // Queue the data for transmission - // - pPacket->pNext = NULL; - pPreviousPacket = pSocket->pTxPacketListTail; - if ( NULL == pPreviousPacket ) { - pSocket->pTxPacketListHead = pPacket; - } - else { - pPreviousPacket->pNext = pPacket; - } - pSocket->pTxPacketListTail = pPacket; - DEBUG (( DEBUG_TX, - "0x%08x: Packet on transmit list\r\n", - pPacket )); - - // - // Account for the buffered data - // - *pTxBytes += BufferLength; - *pDataLength = BufferLength; - - // - // Start the transmit engine if it is idle - // - if ( NULL != pPort->pTxFree ) { - EslSocketTxStart ( pPort, - &pSocket->pTxPacketListHead, - &pSocket->pTxPacketListTail, - &pPort->pTxActive, - &pPort->pTxFree ); - - // - // Ignore any transmit error - // - if ( EFI_ERROR ( pSocket->TxError )) { - DEBUG (( DEBUG_TX, - "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n", - pPort, - pPacket, - pSocket->TxError )); - } - pSocket->TxError = EFI_SUCCESS; - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - else { - // - // Packet allocation failed - // - pSocket->errno = ENOMEM; - break; - } - - // - // Set the next port - // - pPort = pPort->pLinkSocket; - } - } - else { - // - // Not enough buffer space available - // - pSocket->errno = EAGAIN; - Status = EFI_NOT_READY; - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the transmit completion - - This routine use ::EslSocketTxComplete to perform the transmit - completion processing for data packets. - - This routine is called by the IPv4 network layer when a data - transmit request completes. - - @param [in] Event The normal transmit completion event - - @param [in] pIo The address of an ::ESL_IO_MGMT structure - -**/ -VOID -EslIp4TxComplete ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ) -{ - UINT32 LengthInBytes; - ESL_PORT * pPort; - ESL_PACKET * pPacket; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the active transmit packet - // - pPacket = pIo->pPacket; - pPort = pIo->pPort; - pSocket = pPort->pSocket; - - // - // Get the transmit length and status - // - LengthInBytes = pPacket->Op.Ip4Tx.TxData.TotalDataLength; - pSocket->TxBytes -= LengthInBytes; - Status = pIo->Token.Ip4Tx.Status; - - // - // Ignore the transmit error - // - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_TX, - "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n", - pPort, - pPacket, - Status )); - Status = EFI_SUCCESS; - } - - // - // Complete the transmit operation - // - EslSocketTxComplete ( pIo, - LengthInBytes, - Status, - "Raw ", - &pSocket->pTxPacketListHead, - &pSocket->pTxPacketListTail, - &pPort->pTxActive, - &pPort->pTxFree ); - DBG_EXIT ( ); -} - - -/** - Verify the adapter's IP address - - This support routine is called by EslSocketBindTest. - - @param [in] pPort Address of an ::ESL_PORT structure. - @param [in] pConfigData Address of the configuration data - - @retval EFI_SUCCESS - The IP address is valid - @retval EFI_NOT_STARTED - The IP address is invalid - - **/ -EFI_STATUS -EslIp4VerifyLocalIpAddress ( - IN ESL_PORT * pPort, - IN EFI_IP4_CONFIG_DATA * pConfigData - ) -{ - UINTN DataSize; - EFI_IP4_CONFIG2_INTERFACE_INFO * pIfInfo; - EFI_IP4_CONFIG2_PROTOCOL * pIpConfig2Protocol; - ESL_SERVICE * pService; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Use break instead of goto - // - pIfInfo = NULL; - for ( ; ; ) { - // - // Determine if the IP address is specified - // - DEBUG (( DEBUG_BIND, - "UseDefaultAddress: %s\r\n", - pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" )); - DEBUG (( DEBUG_BIND, - "Requested IP address: %d.%d.%d.%d\r\n", - pConfigData->StationAddress.Addr [ 0 ], - pConfigData->StationAddress.Addr [ 1 ], - pConfigData->StationAddress.Addr [ 2 ], - pConfigData->StationAddress.Addr [ 3 ])); - if ( pConfigData->UseDefaultAddress - || (( 0 == pConfigData->StationAddress.Addr [ 0 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 1 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 2 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 3 ]))) - { - Status = EFI_SUCCESS; - break; - } - - // - // Open the configuration protocol - // - pService = pPort->pService; - Status = gBS->OpenProtocol ( - pService->Controller, - &gEfiIp4Config2ProtocolGuid, - (VOID **)&pIpConfig2Protocol, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR, - "ERROR - IP Configuration Protocol not available, Status: %r\r\n", - Status )); - break; - } - - // - // Get the interface information size. - // - DataSize = 0; - Status = pIpConfig2Protocol->GetData ( - pIpConfig2Protocol, - Ip4Config2DataTypeInterfaceInfo, - &DataSize, - NULL - ); - if ( EFI_BUFFER_TOO_SMALL != Status ) { - DEBUG (( DEBUG_ERROR, - "ERROR - Failed to get the interface information size, Status: %r\r\n", - Status )); - break; - } - - // - // Allocate the interface information buffer - // - pIfInfo = AllocatePool ( DataSize ); - if ( NULL == pIfInfo ) { - DEBUG (( DEBUG_ERROR, - "ERROR - Not enough memory to allocate the interface information buffer!\r\n" )); - Status = EFI_OUT_OF_RESOURCES; - break; - } - - // - // Get the interface info. - // - Status = pIpConfig2Protocol->GetData ( - pIpConfig2Protocol, - Ip4Config2DataTypeInterfaceInfo, - &DataSize, - pIfInfo - ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR, - "ERROR - Failed to return the interface info, Status: %r\r\n", - Status )); - break; - } - - // - // Display the current configuration - // - DEBUG (( DEBUG_BIND, - "Actual adapter IP address: %d.%d.%d.%d\r\n", - pIfInfo->StationAddress.Addr [ 0 ], - pIfInfo->StationAddress.Addr [ 1 ], - pIfInfo->StationAddress.Addr [ 2 ], - pIfInfo->StationAddress.Addr [ 3 ])); - - // - // Assume the port is not configured - // - Status = EFI_SUCCESS; - if (( pConfigData->StationAddress.Addr [ 0 ] == pIfInfo->StationAddress.Addr [ 0 ]) - && ( pConfigData->StationAddress.Addr [ 1 ] == pIfInfo->StationAddress.Addr [ 1 ]) - && ( pConfigData->StationAddress.Addr [ 2 ] == pIfInfo->StationAddress.Addr [ 2 ]) - && ( pConfigData->StationAddress.Addr [ 3 ] == pIfInfo->StationAddress.Addr [ 3 ])) { - break; - } - - // - // The IP address did not match - // - Status = EFI_NOT_STARTED; - break; - } - - // - // Free the buffer if necessary - // - if ( NULL != pIfInfo ) { - FreePool ( pIfInfo ); - } - - // - // Return the IP address status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Interface between the socket layer and the network specific - code that supports SOCK_RAW sockets over IPv4. -**/ -CONST ESL_PROTOCOL_API cEslIp4Api = { - "IPv4", - IPPROTO_IP, - OFFSET_OF ( ESL_PORT, Context.Ip4.ModeData.ConfigData ), - OFFSET_OF ( ESL_LAYER, pIp4List ), - OFFSET_OF ( struct sockaddr_in, sin_zero ), - sizeof ( struct sockaddr_in ), - AF_INET, - sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ), - sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ), - OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Rx.Packet.RxData ), - FALSE, - EADDRNOTAVAIL, - NULL, // Accept - NULL, // ConnectPoll - NULL, // ConnectStart - EslIp4SocketIsConfigured, - EslIp4LocalAddressGet, - EslIp4LocalAddressSet, - NULL, // Listen - EslIp4OptionGet, - EslIp4OptionSet, - EslIp4PacketFree, - EslIp4PortAllocate, - NULL, // PortClose - NULL, // PortCloseOp - TRUE, - EslIp4Receive, - EslIp4RemoteAddressGet, - EslIp4RemoteAddressSet, - EslIp4RxComplete, - NULL, // RxStart - EslIp4TxBuffer, - EslIp4TxComplete, - NULL, // TxOobComplete - (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslIp4VerifyLocalIpAddress -}; diff --git a/StdLib/EfiSocketLib/ReleaseNotes.txt b/StdLib/EfiSocketLib/ReleaseNotes.txt deleted file mode 100644 index c978e42405..0000000000 --- a/StdLib/EfiSocketLib/ReleaseNotes.txt +++ /dev/null @@ -1,34 +0,0 @@ -The following issues exist with the EFI Socket Library: - -* Don't run socket applications or the socket driver for a long time - The IPv4Config - and DHCP protocols are not properly running the renew and lease expiration timers. - When the DHCP lease expires it is possible for a duplicate IP address to exist on - the network. HSD 206136 - -* Network adapters must be initialized prior to running the socket application - Static - and dynamic IP address need to be properly assigned to the network adapters on the - system. Note that sockets does not assign the IP addresses since it does not - understand how the system is connected to the network! - -* The default device must contain the Efi\etc directory populated with files containing - the proper network configuration - A template set of files is in StdLib\Efi\etc. Note - that the resolv.conf file contains the set of DNS servers. - -* Since DHCP is not running when the sockets application is running, the last negotiated - packet is no longer available. As a result, any of the options that DHCP did negotiate - are no longer available for sockets such as the list of DNS servers. - -* DHCP does not request the domain name and domain name server (DNS) addresses. This - requires that sockets use configuration files in Efi\etc! - -* TCPv4 transfer rate is slow (< 10 Mbits/sec) - This is an unidentified issue. - -* Tcp4Dxe transmits more urgent data than is sent through sockets when normal data is - queued for transmission before the urgent data. HSD 206365 - -* Raw socket applications are not able to pass the IP header as part of their - payload by using the IP option IP_HDRINCL. This is because the UEFI IPv4 driver - (Ip4Dxe) does not support RawData. HSD 206136 - -* Only version 4 of the UEFI network stack is supported - diff --git a/StdLib/EfiSocketLib/Service.c b/StdLib/EfiSocketLib/Service.c deleted file mode 100644 index 414cace00b..0000000000 --- a/StdLib/EfiSocketLib/Service.c +++ /dev/null @@ -1,479 +0,0 @@ -/** @file - Connect to and disconnect from the various network layers - - Copyright (c) 2011, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "Socket.h" - - -/** - Connect to the network service bindings - - Walk the network service protocols on the controller handle and - locate any that are not in use. Create ::ESL_SERVICE structures to - manage the network layer interfaces for the socket driver. Tag - each of the network interfaces that are being used. Finally, this - routine calls ESL_SOCKET_BINDING::pfnInitialize to prepare the network - interface for use by the socket layer. - - @param [in] BindingHandle Handle for protocol binding. - @param [in] Controller Handle of device to work with. - - @retval EFI_SUCCESS This driver is added to Controller. - @retval EFI_OUT_OF_RESOURCES No more memory available. - @retval EFI_UNSUPPORTED This driver does not support this device. - -**/ -EFI_STATUS -EFIAPI -EslServiceConnect ( - IN EFI_HANDLE BindingHandle, - IN EFI_HANDLE Controller - ) -{ - BOOLEAN bInUse; - EFI_STATUS ExitStatus; - UINTN LengthInBytes; - UINT8 * pBuffer; - CONST ESL_SOCKET_BINDING * pEnd; - VOID * pJunk; - ESL_SERVICE ** ppServiceListHead; - ESL_SERVICE * pService; - CONST ESL_SOCKET_BINDING * pSocketBinding; - EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume the list is empty - // - ExitStatus = EFI_UNSUPPORTED; - bInUse = FALSE; - - // - // Walk the list of network connection points - // - pSocketBinding = &cEslSocketBinding[0]; - pEnd = &pSocketBinding[ cEslSocketBindingEntries ]; - while ( pEnd > pSocketBinding ) { - // - // Determine if the controller supports the network protocol - // - Status = gBS->OpenProtocol ( - Controller, - pSocketBinding->pNetworkBinding, - (VOID**)&pServiceBinding, - BindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if ( !EFI_ERROR ( Status )) { - // - // Determine if the socket layer is already connected - // - Status = gBS->OpenProtocol ( - Controller, - (EFI_GUID *)pSocketBinding->pTagGuid, - &pJunk, - BindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if ( EFI_UNSUPPORTED == Status ) { - // - // Allocate a service structure since the tag is not present - // - LengthInBytes = sizeof ( *pService ); - Status = gBS->AllocatePool ( - EfiRuntimeServicesData, - LengthInBytes, - (VOID **) &pService - ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_POOL | DEBUG_INIT, - "0x%08x: Allocate pService, %d bytes\r\n", - pService, - LengthInBytes )); - - // - // Set the structure signature and service binding - // - ZeroMem ( pService, LengthInBytes ); - pService->Signature = SERVICE_SIGNATURE; - pService->pSocketBinding = pSocketBinding; - pService->Controller = Controller; - pService->pServiceBinding = pServiceBinding; - - // - // Mark the controller in use - // - if ( !bInUse ) { - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - &gEfiCallerIdGuid, - NULL, - NULL - ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, - "Installed: gEfiCallerIdGuid on 0x%08x\r\n", - Controller )); - bInUse = TRUE; - } - else { - if ( EFI_INVALID_PARAMETER == Status ) { - Status = EFI_SUCCESS; - } - } - } - if ( !EFI_ERROR ( Status )) { - // - // Mark the network service protocol in use - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - pSocketBinding->pTagGuid, - pService, - NULL - ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, - "Installed: %s TagGuid on 0x%08x\r\n", - pSocketBinding->pName, - Controller )); - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Connect the service to the list - // - pBuffer = (UINT8 *)&mEslLayer; - pBuffer = &pBuffer[ pSocketBinding->ServiceListOffset ]; - ppServiceListHead = (ESL_SERVICE **)pBuffer; - pService->pNext = *ppServiceListHead; - *ppServiceListHead = pService; - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - - // - // At least one service was made available - // - ExitStatus = EFI_SUCCESS; - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT, - "ERROR - Failed to install %s TagGuid on 0x%08x, Status: %r\r\n", - pSocketBinding->pName, - Controller, - Status )); - } - - if ( EFI_ERROR ( Status )) { - // - // The controller is no longer in use - // - if ( bInUse ) { - gBS->UninstallMultipleProtocolInterfaces ( - Controller, - &gEfiCallerIdGuid, - NULL, - NULL ); - DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, - "Removed: gEfiCallerIdGuid from 0x%08x\r\n", - Controller )); - } - } - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_INIT, - "ERROR - Failed to install gEfiCallerIdGuid on 0x%08x, Status: %r\r\n", - Controller, - Status )); - } - - // - // Release the service if necessary - // - if ( EFI_ERROR ( Status )) { - gBS->FreePool ( pService ); - DEBUG (( DEBUG_POOL | DEBUG_INIT, - "0x%08x: Free pService, %d bytes\r\n", - pService, - sizeof ( *pService ))); - pService = NULL; - } - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_INIT, - "ERROR - Failed service allocation, Status: %r\r\n", - Status )); - ExitStatus = EFI_OUT_OF_RESOURCES; - break; - } - } - } - - // - // Set the next network protocol - // - pSocketBinding += 1; - } - - // - // Display the driver start status - // - DBG_EXIT_STATUS ( ExitStatus ); - return ExitStatus; -} - - -/** - Shutdown the connections to the network layer by locating the - tags on the network interfaces established by ::EslServiceConnect. - This routine shutdowns any activity on the network interface and - then frees the ::ESL_SERVICE structures. - - @param [in] BindingHandle Handle for protocol binding. - @param [in] Controller Handle of device to stop driver on. - - @retval EFI_SUCCESS This driver is removed Controller. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. - @retval other This driver was not removed from this device. - -**/ -EFI_STATUS -EFIAPI -EslServiceDisconnect ( - IN EFI_HANDLE BindingHandle, - IN EFI_HANDLE Controller - ) -{ - UINT8 * pBuffer; - CONST ESL_SOCKET_BINDING * pEnd; - ESL_PORT * pPort; - ESL_SERVICE * pPreviousService; - ESL_SERVICE * pService; - ESL_SERVICE ** ppServiceListHead; - CONST ESL_SOCKET_BINDING * pSocketBinding; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Walk the list of network connection points in reverse order - // - pEnd = &cEslSocketBinding[0]; - pSocketBinding = &pEnd[ cEslSocketBindingEntries ]; - while ( pEnd < pSocketBinding ) { - // - // Set the next network protocol - // - pSocketBinding -= 1; - - // - // Determine if the driver connected - // - Status = gBS->OpenProtocol ( - Controller, - (EFI_GUID *)pSocketBinding->pTagGuid, - (VOID **)&pService, - BindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if ( !EFI_ERROR ( Status )) { - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Walk the list of ports - // - pPort = pService->pPortList; - while ( NULL != pPort ) { - // - // Remove the port from the port list - // - pPort->pService = NULL; - pService->pPortList = pPort->pLinkService; - - // - // Close the port - // - EslSocketPortCloseStart ( pPort, - TRUE, - DEBUG_POOL | DEBUG_INIT ); - - // - // Set the next port - // - pPort = pService->pPortList; - } - - // - // Remove the service from the service list - // - pBuffer = (UINT8 *)&mEslLayer; - pBuffer = &pBuffer[ pService->pSocketBinding->ServiceListOffset ]; - ppServiceListHead = (ESL_SERVICE **)pBuffer; - pPreviousService = *ppServiceListHead; - if ( pService == pPreviousService ) { - // - // Remove the service from the beginning of the list - // - *ppServiceListHead = pService->pNext; - } - else { - // - // Remove the service from the middle of the list - // - while ( NULL != pPreviousService ) { - if ( pService == pPreviousService->pNext ) { - pPreviousService->pNext = pService->pNext; - break; - } - pPreviousService = pPreviousService->pNext; - } - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - - // - // Break the driver connection - // - Status = gBS->UninstallMultipleProtocolInterfaces ( - Controller, - pSocketBinding->pTagGuid, - pService, - NULL ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_POOL | DEBUG_INIT, - "Removed: %s TagGuid from 0x%08x\r\n", - pSocketBinding->pName, - Controller )); - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT, - "ERROR - Failed to removed %s TagGuid from 0x%08x, Status: %r\r\n", - pSocketBinding->pName, - Controller, - Status )); - } - - // - // Free the service structure - // - Status = gBS->FreePool ( pService ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_POOL | DEBUG_INIT, - "0x%08x: Free pService, %d bytes\r\n", - pService, - sizeof ( *pService ))); - } - else { - DEBUG (( DEBUG_POOL | DEBUG_INIT, - "ERROR - Failed to free pService 0x%08x, Status: %r\r\n", - pService, - Status )); - } - pService = NULL; - } - } - - // - // The controller is no longer in use - // - gBS->UninstallMultipleProtocolInterfaces ( - Controller, - &gEfiCallerIdGuid, - NULL, - NULL ); - DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, - "Removed: gEfiCallerIdGuid from 0x%08x\r\n", - Controller )); - - // - // The driver is disconnected from the network controller - // - Status = EFI_SUCCESS; - - // - // Display the driver start status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - - -/** -Initialize the service layer - -@param [in] ImageHandle Handle for the image. - -**/ -VOID -EFIAPI -EslServiceLoad ( - IN EFI_HANDLE ImageHandle - ) -{ - ESL_LAYER * pLayer; - - // - // Save the image handle - // - pLayer = &mEslLayer; - ZeroMem ( pLayer, sizeof ( *pLayer )); - pLayer->Signature = LAYER_SIGNATURE; - pLayer->ImageHandle = ImageHandle; - - // - // Connect the service binding protocol to the image handle - // - pLayer->pServiceBinding = &mEfiServiceBinding; -} - - -/** - Shutdown the service layer - -**/ -VOID -EFIAPI -EslServiceUnload ( - VOID - ) -{ - ESL_LAYER * pLayer; - - // - // Undo the work by ServiceLoad - // - pLayer = &mEslLayer; - pLayer->ImageHandle = NULL; - pLayer->pServiceBinding = NULL; -} diff --git a/StdLib/EfiSocketLib/Socket.c b/StdLib/EfiSocketLib/Socket.c deleted file mode 100644 index d782b435e6..0000000000 --- a/StdLib/EfiSocketLib/Socket.c +++ /dev/null @@ -1,5795 +0,0 @@ -/** @file - Implement the socket support for the socket layer. - - Socket States: - * Bound - pSocket->PortList is not NULL - * Listen - AcceptWait event is not NULL - - Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
- This program and the accompanying materials are licensed and made available under - the terms and conditions of the BSD License that accompanies this distribution. - The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - - - \section DataStructures Data Structures - -
-
-                +---------------+   +-------------+   +-------------+
-  Service Lists | ::ESL_SERVICE |-->| ESL_SERVICE |-->| ESL_SERVICE |--> NULL (pNext)
-                +---------------+   +-------------+   +-------------+
-                  ^                       | (pPortList)    |
-    pUdp4List ^   | pTcp4List             |                |
-              |   |                       |                |
-          ^   |   |                       |                |
- pIp4List |   |   |                       |                |
-        +---------------+                 |                |
-        | ::ESL_LAYER   | ::mEslLayer     |                |
-        +---------------+                 |                |
-                  | (pSocketList)         |                |
-    Socket List   V                       V                V
-                +---------------+   +-------------+   +-------------+
-                | ::ESL_SOCKET  |-->| ::ESL_PORT  |-->|   ESL_PORT  |--> NULL (pLinkSocket)
-                +---------------+   +-------------+   +-------------+
-                  |                       |                |
-                  |                       |                V
-                  V                       V               NULL
-                +-------------+   +-------------+
-                | ESL_SOCKET  |-->|   ESL_PORT  |--> NULL
-                +-------------+   +-------------+
-                  |    | | | |            |
-                  V    | | | |            V
-                 NULL  | | | |           NULL
-               (pNext) | | | |     (pLinkService)
-                       | | | |                                     pRxPacketListHead
-                       | | | `-----------------------------------------------.
-                       | | |                     pRxOobPacketListHead        |
-                       | | `--------------------------------.                |
-                       | |      pTxPacketListHead           |                |
-                       | `---------------.                  |                |
-  pTxOobPacketListHead |                 |                  |                |
-                       V                 V                  V                V
-                  +--------------+    +------------+    +------------+    +------------+
-                  | ::ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |
-                  +--------------+    +------------+    +------------+    +------------+
-                         |                 |                |                |
-                         V                 V                V                V
-                  +------------+    +------------+    +------------+    +------------+
-                  | ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |    | ESL_PACKET |
-                  +------------+    +------------+    +------------+    +------------+
-                         |                 |                |                |
-                         V                 V                V                V
-                        NULL              NULL             NULL             NULL
-                       (pNext)
-
-  
- - ::mEslLayer is the one and only ::ESL_LAYER structure. It connects directly or - indirectly to the other data structures. The ESL_LAYER structure has a unique - service list for each of the network protocol interfaces. - - ::ESL_SERVICE manages the network interfaces for a given transport type (IP4, TCP4, UDP4, etc.) - - ::ESL_SOCKET manages the activity for a single socket instance. As such, it contains - the ::EFI_SOCKET_PROTOCOL structure which the BSD socket library uses as the object - reference and the API into the EFI socket library. - - ::ESL_PORT manages the connection with a single instance of the lower layer network. - This structure is the socket equivalent of an IP connection or a TCP or UDP port. - - ::ESL_PACKET buffers data for transmit and receive. There are four queues connected - to the ::ESL_SOCKET that manage the data: - - The selection of the transmit queue is controlled by the MSG_OOB flag on the transmit - request as well as the socket option SO_OOBINLINE. The receive queue is selected by - the URGENT data flag for TCP and the setting of the socket option SO_OOBINLINE. - - Data structure synchronization is done by raising TPL to TPL_SOCKET. Modifying - critical elements within the data structures must be done at this TPL. TPL is then - restored to the previous level. Note that the code verifies that all callbacks are - entering at TPL_SOCKETS for proper data structure synchronization. - - \section PortCloseStateMachine Port Close State Machine - - The port close state machine walks the port through the necessary - states to stop activity on the port and get it into a state where - the resources may be released. The state machine consists of the - following arcs and states: - -
-
-      +--------------------------+
-      |          Open            |
-      +--------------------------+
-                   |
-                   |  ::EslSocketPortCloseStart
-                   V
-      +--------------------------+
-      | PORT_STATE_CLOSE_STARTED |
-      +--------------------------+
-                   |
-                   |  ::EslSocketPortCloseTxDone
-                   V
-      +--------------------------+
-      | PORT_STATE_CLOSE_TX_DONE |
-      +--------------------------+
-                   |
-                   |  ::EslSocketPortCloseComplete
-                   V
-      +--------------------------+
-      |  PORT_STATE_CLOSE_DONE   |
-      +--------------------------+
-                   |
-                   |  ::EslSocketPortCloseRxDone
-                   V
-      +--------------------------+
-      | PORT_STATE_CLOSE_RX_DONE |
-      +--------------------------+
-                   |
-                   |  ::EslSocketPortClose
-                   V
-      +--------------------------+
-      |          Closed          |
-      +--------------------------+
-
-  
- - - - - \section ReceiveEngine Receive Engine - - The receive path accepts data from the network and queues (buffers) it for the - application. Flow control is applied once a maximum amount of buffering is reached - and is released when the buffer usage drops below that limit. Eventually the - application requests data from the socket which removes entries from the queue and - returns the data. - - The receive engine is the state machine which reads data from the network and - fills the queue with received packets. The receive engine uses two data structures - to manage the network receive opeations and the buffers. - - At a high level, the ::ESL_IO_MGMT structures are managing the tokens and - events for the interface to the UEFI network stack. The ::ESL_PACKET - structures are managing the receive data buffers. The receive engine - connects these two structures in the network specific receive completion - routines. - -
-
-      +------------------+
-      |     ::ESL_PORT     |
-      |                  |
-      +------------------+
-      |    ::ESL_IO_MGMT   |
-      +------------------+
-      |    ESL_IO_MGMT   |
-      +------------------+
-      .                  .
-      .    ESL_IO_MGMT   .
-      .                  .
-      +------------------+
-
-
- - The ::ESL_IO_MGMT structures are allocated as part of the ::ESL_PORT structure in - ::EslSocketPortAllocate. The ESL_IO_MGMT structures are separated and placed on - the free list by calling ::EslSocketIoInit. The ESL_IO_MGMT structure contains - the network layer specific receive completion token and event. The receive engine - is eventually shutdown by ::EslSocketPortCloseTxDone and the resources in these - structures are released in ::EslSocketPortClose by a call to ::EslSocketIoFree. - -
-
-         pPort->pRxActive
-                |
-                V
-          +-------------+   +-------------+   +-------------+
-  Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL
-          +-------------+   +-------------+   +-------------+
-
-          +-------------+   +-------------+   +-------------+
-  Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL
-          +-------------+   +-------------+   +-------------+
-                ^
-                |
-          pPort->pRxFree
-
- - The receive engine is started by calling ::EslSocketRxStart. Flow control pauses - the receive engine by stopping the calls to EslSocketRxStart when the amount of - receive data waiting for the application meets or exceeds MAX_RX_DATA. After - the application reads enough data that the amount of buffering drops below this - limit, the calls to EslSockeRxStart continue which releases the flow control. - - Receive flow control is applied when the port is created, since no receive - operation are pending to the low layer network driver. The flow control gets - released when the low layer network port is configured or the first receive - operation is posted. Flow control remains in the released state until the - maximum buffer space is consumed. During this time, ::EslSocketRxComplete - calls ::EslSocketRxStart. Flow control is applied in EslSocketRxComplete - by skipping the call to EslSocketRxStart. Flow control is eventually - released in ::EslSocketReceive when the buffer space drops below the - maximum amount causing EslSocketReceive to call EslSocketRxStart. - -
-
-                    +------------+   +------------+
-    High     .----->| ESL_PACKET |-->| ESL_PACKET |--> NULL (pNext)
-  Priority   |      +------------+   +------------+
-             |
-             | pRxOobPacketListHead
-       +------------+
-       | ::ESL_SOCKET |
-       +------------+
-             | pRxPacketListHead
-    Low      |
-  Priority   |      +------------+   +------------+   +------------+
-             `----->| ::ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL
-                    +------------+   +------------+   +------------+
-
-
- - ::EslSocketRxStart connects an ::ESL_PACKET structure to the ::ESL_IO_MGMT structure - and then calls the network layer to start the receive operation. Upon - receive completion, ::EslSocketRxComplete breaks the connection between these - structrues and places the ESL_IO_MGMT structure onto the ESL_PORT::pRxFree list to - make token and event available for another receive operation. EslSocketRxComplete - then queues the ESL_PACKET structure (data packet) to either the - ESL_SOCKET::pRxOobPacketListTail or ESL_SOCKET::pRxPacketListTail depending on - whether urgent or normal data was received. Finally ::EslSocketRxComplete attempts - to start another receive operation. - -
-
-  Setup for IP4 and UDP4
-
-      +--------------------+
-      | ESL_IO_MGMT        |
-      |                    |
-      |    +---------------+
-      |    | Token         |
-      |    |        RxData --> NULL
-      +----+---------------+
-         |
-         V
-      +--------------------+
-      | ESL_PACKET         |
-      |                    |
-      |    +---------------+
-      |    |       pRxData --> NULL
-      +----+---------------+
-
-  Completion for IP4 and UDP4
-
-      +--------------------+   +----------------------+
-      | ESL_IO_MGMT        |   |      Data Buffer     |
-      |                    |   |     (Driver owned)   |
-      |    +---------------+   +----------------------+
-      |    | Token         |               ^
-      |    |      Rx Event |               |
-      |    |               |   +----------------------+
-      |    |        RxData --> | EFI_IP4_RECEIVE_DATA |
-      +----+---------------+   |    (Driver owned)    |
-         |                     +----------------------+
-         V                                 ^
-      +--------------------+               .
-      | ESL_PACKET         |               .
-      |                    |               .
-      |    +---------------+               .
-      |    |       pRxData --> NULL  .......
-      +----+---------------+
-
-
-  Setup and completion for TCP4
-
-      +--------------------+   +--------------------------+
-      | ESL_IO_MGMT        |-->| ESL_PACKET               |
-      |                    |   |                          |
-      |    +---------------+   +----------------------+   |
-      |    | Token         |   | EFI_IP4_RECEIVE_DATA |   |
-      |    |        RxData --> |                      |   |
-      |    |               |   +----------------------+---+
-      |    |        Event  |   |       Data Buffer        |
-      +----+---------------+   |                          |
-                               |                          |
-                               +--------------------------+
-
-
- - To minimize the number of buffer copies, the data is not copied until the - application makes a receive call. At this point socket performs a single copy - in the receive path to move the data from the buffer filled by the network layer - into the application's buffer. - - The IP4 and UDP4 drivers go one step further to reduce buffer copies. They - allow the socket layer to hold on to the actual receive buffer until the - application has performed a receive operation or closes the socket. Both - of theses operations return the buffer to the lower layer network driver - by calling ESL_PROTOCOL_API::pfnPacketFree. - - When a socket application wants to receive data it indirectly calls - ::EslSocketReceive to remove data from one of the receive data queues. This routine - removes the next available packet from ESL_SOCKET::pRxOobPacketListHead or - ESL_SOCKET::pRxPacketListHead and copies the data from the packet - into the application's buffer. For SOCK_STREAM sockets, if the packet - contains more data then the ESL_PACKET structures remains at the head of the - receive queue for the next application receive - operation. For SOCK_DGRAM, SOCK_RAW and SOCK_SEQ_PACKET sockets, the ::ESL_PACKET - structure is removed from the head of the receive queue and any remaining data is - discarded as the packet is placed on the free queue. - - During socket layer shutdown, ::EslSocketShutdown calls ::EslSocketRxCancel to - cancel any pending receive operations. EslSocketRxCancel calls the network specific - cancel routine using ESL_PORT::pfnRxCancel. - - - \section TransmitEngine Transmit Engine - - Application calls to ::EslSocketTransmit cause data to be copied into a buffer. - The buffer exists as an extension to an ESL_PACKET structure and the structure - is placed at the end of the transmit queue. - -
-
-     *ppQueueHead: pSocket->pRxPacketListHead or pSocket->pRxOobPacketListHead
-          |
-          V
-        +------------+   +------------+   +------------+
-  Data  | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL
-        +------------+   +------------+   +------------+
-                                                     ^
-                                                     |
-     *ppQueueTail: pSocket->pRxPacketListTail or pSocket->pRxOobPacketListTail
-
-
- - There are actually two transmit queues the normal or low priority queue which is - the default and the urgent or high priority queue which is addressed by specifying - the MSG_OOB flag during the transmit request. Associated with each queue is a - transmit engine which is responsible for sending the data in that queue. - - The transmit engine is the state machine which removes entries from the head - of the transmit queue and causes the data to be sent over the network. - -
-
-      +--------------------+   +--------------------+
-      | ESL_IO_MGMT        |   | ESL_PACKET         |
-      |                    |   |                    |
-      |    +---------------+   +----------------+   |
-      |    | Token         |   | Buffer Length  |   |
-      |    |        TxData --> | Buffer Address |   |
-      |    |               |   +----------------+---+
-      |    |        Event  |   | Data Buffer        |
-      +----+---------------+   |                    |
-                               +--------------------+
-
- - At a high level, the transmit engine uses a couple of data structures - to manage the data flow. The ::ESL_IO_MGMT structures manage the tokens and - events for the interface to the UEFI network stack. The ::ESL_PACKET - structures manage the data buffers that get sent. The transmit - engine connects these two structures prior to transmission and disconnects - them upon completion. - -
-
-         pPort->pTxActive or pTxOobActive
-                |
-                V
-          +-------------+   +-------------+   +-------------+
-  Active  | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL
-          +-------------+   +-------------+   +-------------+
-
-          +-------------+   +-------------+   +-------------+
-  Free    | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL
-          +-------------+   +-------------+   +-------------+
-                ^
-                |
-          pPort->pTxFree or pTxOobFree
-
-
- - The transmit engine manages multiple transmit operations using the - active and free lists shown above. ::EslSocketPortAllocate allocates the - ::ESL_IO_MGMT structures as an extension to the ::ESL_PORT structure. - This routine places the ESL_IO_MGMT structures on the free list by calling - ::EslSocketIoInit. During their lifetime, the ESL_IO_MGMT structures - will move from the free list to the active list and back again. The - active list contains the packets that are actively being processed by - the UEFI network stack. Eventually the ESL_IO_MGMT structures will be - removed from the free list and be deallocated by the EslSocketPortClose - routine. - - The network specific code calls the ::EslSocketTxStart routine - to hand a packet to the network stack. EslSocketTxStart connects - the transmit packet (::ESL_PACKET) to an ::ESL_IO_MGMT structure - and then queues the result to one of the active lists: - ESL_PORT::pTxActive or ESL_PORT::pTxOobActive. The routine then - hands the packet to the network stack. - - Upon completion, the network specific TxComplete routine calls - ::EslSocketTxComplete to disconnect the transmit packet from the - ESL_IO_MGMT structure and frees the ::ESL_PACKET structure by calling - ::EslSocketPacketFree. The routine places the ::ESL_IO_MGMT structure - into the free list either ESL_PORT::pTxFree or ESL_PORT::pTxOobFree. - EslSocketTxComplete then starts the next transmit operation while - the socket is active or calls the ::EslSocketPortCloseTxDone routine - when the socket is shutting down. - -**/ - -#include "Socket.h" - - -/** Socket driver connection points - - List the network stack connection points for the socket driver. -**/ -CONST ESL_SOCKET_BINDING cEslSocketBinding[] = { - { L"Ip4", - &gEfiIp4ServiceBindingProtocolGuid, - &gEfiIp4ProtocolGuid, - &mEslIp4ServiceGuid, - OFFSET_OF ( ESL_LAYER, pIp4List ), - 4, // RX buffers - 4, // TX buffers - 0 }, // TX Oob buffers - { L"Tcp4", - &gEfiTcp4ServiceBindingProtocolGuid, - &gEfiTcp4ProtocolGuid, - &mEslTcp4ServiceGuid, - OFFSET_OF ( ESL_LAYER, pTcp4List ), - 4, // RX buffers - 4, // TX buffers - 4 }, // TX Oob buffers - { L"Tcp6", - &gEfiTcp6ServiceBindingProtocolGuid, - &gEfiTcp6ProtocolGuid, - &mEslTcp6ServiceGuid, - OFFSET_OF ( ESL_LAYER, pTcp6List ), - 4, // RX buffers - 4, // TX buffers - 4 }, // TX Oob buffers - { L"Udp4", - &gEfiUdp4ServiceBindingProtocolGuid, - &gEfiUdp4ProtocolGuid, - &mEslUdp4ServiceGuid, - OFFSET_OF ( ESL_LAYER, pUdp4List ), - 4, // RX buffers - 4, // TX buffers - 0 }, // TX Oob buffers - { L"Udp6", - &gEfiUdp6ServiceBindingProtocolGuid, - &gEfiUdp6ProtocolGuid, - &mEslUdp6ServiceGuid, - OFFSET_OF ( ESL_LAYER, pUdp6List ), - 4, // RX buffers - 4, // TX buffers - 0 } // TX Oob buffers -}; - -CONST UINTN cEslSocketBindingEntries = DIM ( cEslSocketBinding ); - -/// APIs to support the various socket types for the v4 network stack. -CONST ESL_PROTOCOL_API * cEslAfInetApi[] = { - NULL, // 0 - &cEslTcp4Api, // SOCK_STREAM - &cEslUdp4Api, // SOCK_DGRAM - &cEslIp4Api, // SOCK_RAW - NULL, // SOCK_RDM - &cEslTcp4Api // SOCK_SEQPACKET -}; - -/// Number of entries in the v4 API array ::cEslAfInetApi. -CONST int cEslAfInetApiSize = DIM ( cEslAfInetApi ); - - -/// APIs to support the various socket types for the v6 network stack. -CONST ESL_PROTOCOL_API * cEslAfInet6Api[] = { - NULL, // 0 - &cEslTcp6Api, // SOCK_STREAM - &cEslUdp6Api, // SOCK_DGRAM - NULL, // SOCK_RAW - NULL, // SOCK_RDM - &cEslTcp6Api // SOCK_SEQPACKET -}; - -/// Number of entries in the v6 API array ::cEslAfInet6Api. -CONST int cEslAfInet6ApiSize = DIM ( cEslAfInet6Api ); - - -/// Global management structure for the socket layer. -ESL_LAYER mEslLayer; - - -/** Initialize an endpoint for network communication. - - This routine initializes the communication endpoint. - - The ::socket routine calls this routine indirectly to create - the communication endpoint. - - @param[in] pSocketProtocol Address of the socket protocol structure. - @param[in] domain Select the family of protocols for the client or server - application. See the ::socket documentation for values. - @param[in] type Specifies how to make the network connection. - See the ::socket documentation for values. - @param[in] protocol Specifies the lower layer protocol to use. - See the ::socket documentation for values. - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS - Socket successfully created - @retval EFI_INVALID_PARAMETER - Invalid domain value, errno = EAFNOSUPPORT - @retval EFI_INVALID_PARAMETER - Invalid type value, errno = EINVAL - @retval EFI_INVALID_PARAMETER - Invalid protocol value, errno = EINVAL - **/ -EFI_STATUS -EslSocket ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN int domain, - IN int type, - IN int protocol, - IN int * pErrno - ) -{ - CONST ESL_PROTOCOL_API * pApi; - CONST ESL_PROTOCOL_API ** ppApiArray; - CONST ESL_PROTOCOL_API ** ppApiArrayEnd; - int ApiArraySize; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - int errno; - - DBG_ENTER ( ); - - // Locate the socket - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - - // Set the default domain if necessary - if ( AF_UNSPEC == domain ) { - domain = AF_INET; - } - - // Assume success - errno = 0; - Status = EFI_SUCCESS; - - // Use break instead of goto - for ( ; ; ) { - // Validate the domain value - if (( AF_INET != domain ) - && ( AF_INET6 != domain ) - && ( AF_LOCAL != domain )) { - DEBUG (( DEBUG_ERROR | DEBUG_SOCKET, - "ERROR - Invalid domain value\r\n" )); - Status = EFI_INVALID_PARAMETER; - errno = EAFNOSUPPORT; - break; - } - - // Determine the protocol APIs - ppApiArray = NULL; - ApiArraySize = 0; - if (( AF_INET == domain ) - || ( AF_LOCAL == domain )) { - ppApiArray = &cEslAfInetApi[0]; - ApiArraySize = cEslAfInetApiSize; - } - else { - ppApiArray = &cEslAfInet6Api[0]; - ApiArraySize = cEslAfInet6ApiSize; - } - - // Set the default type if necessary - if ( 0 == type ) { - type = SOCK_STREAM; - } - - // Validate the type value - if (( type >= ApiArraySize ) - || ( NULL == ppApiArray ) - || ( NULL == ppApiArray[ type ])) { - DEBUG (( DEBUG_ERROR | DEBUG_SOCKET, - "ERROR - Invalid type value\r\n" )); - // The socket type is not supported - Status = EFI_INVALID_PARAMETER; - errno = EPROTOTYPE; - break; - } - - // Set the default protocol if necessary - pApi = ppApiArray[ type ]; - if ( 0 == protocol ) { - protocol = pApi->DefaultProtocol; - } - - // Validate the protocol value - if (( pApi->DefaultProtocol != protocol ) - && ( SOCK_RAW != type )) { - Status = EFI_INVALID_PARAMETER; - - // Assume that the driver supports this protocol - ppApiArray = &cEslAfInetApi[0]; - ppApiArrayEnd = &ppApiArray [ cEslAfInetApiSize ]; - while ( ppApiArrayEnd > ppApiArray ) { - pApi = *ppApiArray; - if ( protocol == pApi->DefaultProtocol ) { - break; - } - ppApiArray += 1; - } - if ( ppApiArrayEnd <= ppApiArray ) { - // Verify against the IPv6 table - ppApiArray = &cEslAfInet6Api[0]; - ppApiArrayEnd = &ppApiArray [ cEslAfInet6ApiSize ]; - while ( ppApiArrayEnd > ppApiArray ) { - pApi = *ppApiArray; - if ( protocol == pApi->DefaultProtocol ) { - break; - } - ppApiArray += 1; - } - } - if ( ppApiArrayEnd <= ppApiArray ) { - DEBUG (( DEBUG_ERROR | DEBUG_SOCKET, - "ERROR - The protocol is not supported!\r\n" )); - errno = EPROTONOSUPPORT; - break; - } - - // The driver does not support this protocol - DEBUG (( DEBUG_ERROR | DEBUG_SOCKET, - "ERROR - The protocol does not support this socket type!\r\n" )); - errno = EPROTONOSUPPORT; - errno = EPROTOTYPE; - break; - } - // Save the socket attributes - pSocket->pApi = pApi; - pSocket->Domain = domain; - pSocket->Type = type; - pSocket->Protocol = protocol; - - // Done - break; - } - // Return the operation status - if ( NULL != pErrno ) { - *pErrno = errno; - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Accept a network connection. - - This routine calls the network specific layer to remove the next - connection from the FIFO. - - The ::accept calls this routine to poll for a network - connection to the socket. When a connection is available - this routine returns the ::EFI_SOCKET_PROTOCOL structure address - associated with the new socket and the remote network address - if requested. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[in] pSockAddr Address of a buffer to receive the remote - network address. - @param[in,out] pSockAddrLength Length in bytes of the address buffer. - On output specifies the length of the - remote network address. - @param[out] ppSocketProtocol Address of a buffer to receive the - ::EFI_SOCKET_PROTOCOL instance - associated with the new socket. - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS New connection successfully created - @retval EFI_NOT_READY No connection is available - **/ -EFI_STATUS -EslSocketAccept ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN struct sockaddr * pSockAddr, - IN OUT socklen_t * pSockAddrLength, - IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol, - IN int * pErrno - ) -{ - ESL_SOCKET * pNewSocket; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Validate the socket - // - pSocket = NULL; - pNewSocket = NULL; - if ( NULL != pSocketProtocol ) { - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - - // - // Verify the API - // - if ( NULL == pSocket->pApi->pfnAccept ) { - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTSUP; - } - else { - // - // Validate the sockaddr - // - if (( NULL != pSockAddr ) - && ( NULL == pSockAddrLength )) { - DEBUG (( DEBUG_ACCEPT, - "ERROR - pSockAddr is NULL!\r\n" )); - Status = EFI_INVALID_PARAMETER; - pSocket->errno = EFAULT; - } - else { - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Verify that the socket is in the listen state - // - if ( SOCKET_STATE_LISTENING != pSocket->State ) { - DEBUG (( DEBUG_ACCEPT, - "ERROR - Socket is not listening!\r\n" )); - if ( NULL == pSocket->pApi->pfnAccept ) { - // - // Socket does not support listen - // - pSocket->errno = EOPNOTSUPP; - Status = EFI_UNSUPPORTED; - } - else { - // - // Socket supports listen, but not in listen state - // - pSocket->errno = EINVAL; - Status = EFI_NOT_STARTED; - } - } - else { - // - // Determine if a socket is available - // - if ( 0 == pSocket->FifoDepth ) { - // - // No connections available - // Determine if any ports are available - // - if ( NULL == pSocket->pPortList ) { - // - // No ports available - // - Status = EFI_DEVICE_ERROR; - pSocket->errno = EINVAL; - - // - // Update the socket state - // - pSocket->State = SOCKET_STATE_NO_PORTS; - } - else { - // - // Ports are available - // No connection requests at this time - // - Status = EFI_NOT_READY; - pSocket->errno = EAGAIN; - } - } - else { - - // - // Attempt to accept the connection and - // get the remote network address - // - pNewSocket = pSocket->pFifoHead; - ASSERT ( NULL != pNewSocket ); - Status = pSocket->pApi->pfnAccept ( pNewSocket, - pSockAddr, - pSockAddrLength ); - if ( !EFI_ERROR ( Status )) { - // - // Remove the new socket from the list - // - pSocket->pFifoHead = pNewSocket->pNextConnection; - if ( NULL == pSocket->pFifoHead ) { - pSocket->pFifoTail = NULL; - } - - // - // Account for this socket - // - pSocket->FifoDepth -= 1; - - // - // Update the new socket's state - // - pNewSocket->State = SOCKET_STATE_CONNECTED; - pNewSocket->bConfigured = TRUE; - DEBUG (( DEBUG_ACCEPT, - "0x%08x: Socket connected\r\n", - pNewSocket )); - } - } - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - } - } - - // - // Return the new socket - // - if (( NULL != ppSocketProtocol ) - && ( NULL != pNewSocket )) { - *ppSocketProtocol = &pNewSocket->SocketProtocol; - } - - // - // Return the operation status - // - if ( NULL != pErrno ) { - if ( NULL != pSocket ) { - *pErrno = pSocket->errno; - } - else { - Status = EFI_INVALID_PARAMETER; - *pErrno = ENOTSOCK; - } - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Allocate and initialize a ESL_SOCKET structure. - - This support function allocates an ::ESL_SOCKET structure - and installs a protocol on ChildHandle. If pChildHandle is a - pointer to NULL, then a new handle is created and returned in - pChildHandle. If pChildHandle is not a pointer to NULL, then - the protocol installs on the existing pChildHandle. - - @param[in,out] pChildHandle Pointer to the handle of the child to create. - If it is NULL, then a new handle is created. - If it is a pointer to an existing UEFI handle, - then the protocol is added to the existing UEFI - handle. - @param[in] DebugFlags Flags for debug messages - @param[in,out] ppSocket The buffer to receive an ::ESL_SOCKET structure address. - - @retval EFI_SUCCESS The protocol was added to ChildHandle. - @retval EFI_INVALID_PARAMETER ChildHandle is NULL. - @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create - the child - @retval other The child handle was not created -**/ -EFI_STATUS -EFIAPI -EslSocketAllocate ( - IN OUT EFI_HANDLE * pChildHandle, - IN UINTN DebugFlags, - IN OUT ESL_SOCKET ** ppSocket - ) -{ - UINTN LengthInBytes; - ESL_LAYER * pLayer; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Create a socket structure - // - LengthInBytes = sizeof ( *pSocket ); - pSocket = (ESL_SOCKET *) AllocateZeroPool ( LengthInBytes ); - if ( NULL != pSocket ) { - DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT, - "0x%08x: Allocate pSocket, %d bytes\r\n", - pSocket, - LengthInBytes )); - - // - // Initialize the socket protocol - // - pSocket->Signature = SOCKET_SIGNATURE; - pSocket->SocketProtocol.pfnAccept = EslSocketAccept; - pSocket->SocketProtocol.pfnBind = EslSocketBind; - pSocket->SocketProtocol.pfnClosePoll = EslSocketClosePoll; - pSocket->SocketProtocol.pfnCloseStart = EslSocketCloseStart; - pSocket->SocketProtocol.pfnConnect = EslSocketConnect; - pSocket->SocketProtocol.pfnGetLocal = EslSocketGetLocalAddress; - pSocket->SocketProtocol.pfnGetPeer = EslSocketGetPeerAddress; - pSocket->SocketProtocol.pfnListen = EslSocketListen; - pSocket->SocketProtocol.pfnOptionGet = EslSocketOptionGet; - pSocket->SocketProtocol.pfnOptionSet = EslSocketOptionSet; - pSocket->SocketProtocol.pfnPoll = EslSocketPoll; - pSocket->SocketProtocol.pfnReceive = EslSocketReceive; - pSocket->SocketProtocol.pfnShutdown = EslSocketShutdown; - pSocket->SocketProtocol.pfnSocket = EslSocket; - pSocket->SocketProtocol.pfnTransmit = EslSocketTransmit; - - pSocket->MaxRxBuf = MAX_RX_DATA; - pSocket->MaxTxBuf = MAX_TX_DATA; - - // - // Install the socket protocol on the specified handle - // - Status = gBS->InstallMultipleProtocolInterfaces ( - pChildHandle, - &gEfiSocketProtocolGuid, - &pSocket->SocketProtocol, - NULL - ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, - "Installed: gEfiSocketProtocolGuid on 0x%08x\r\n", - *pChildHandle )); - pSocket->SocketProtocol.SocketHandle = *pChildHandle; - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Add this socket to the list - // - pLayer = &mEslLayer; - pSocket->pNext = pLayer->pSocketList; - pLayer->pSocketList = pSocket; - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - - // - // Return the socket structure address - // - *ppSocket = pSocket; - } - else { - DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT, - "ERROR - Failed to install gEfiSocketProtocolGuid on 0x%08x, Status: %r\r\n", - *pChildHandle, - Status )); - } - - // - // Release the socket if necessary - // - if ( EFI_ERROR ( Status )) { - gBS->FreePool ( pSocket ); - DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT, - "0x%08x: Free pSocket, %d bytes\r\n", - pSocket, - sizeof ( *pSocket ))); - pSocket = NULL; - } - } - else { - Status = EFI_OUT_OF_RESOURCES; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Bind a name to a socket. - - This routine calls the network specific layer to save the network - address of the local connection point. - - The ::bind routine calls this routine to connect a name - (network address and port) to a socket on the local machine. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[in] pSockAddr Address of a sockaddr structure that contains the - connection point on the local machine. An IPv4 address - of INADDR_ANY specifies that the connection is made to - all of the network stacks on the platform. Specifying a - specific IPv4 address restricts the connection to the - network stack supporting that address. Specifying zero - for the port causes the network layer to assign a port - number from the dynamic range. Specifying a specific - port number causes the network layer to use that port. - @param[in] SockAddrLength Specifies the length in bytes of the sockaddr structure. - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS - Socket successfully created -**/ -EFI_STATUS -EslSocketBind ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN CONST struct sockaddr * pSockAddr, - IN socklen_t SockAddrLength, - OUT int * pErrno - ) -{ - EFI_HANDLE ChildHandle; - UINT8 * pBuffer; - ESL_PORT * pPort; - ESL_SERVICE ** ppServiceListHead; - ESL_SOCKET * pSocket; - ESL_SERVICE * pService; - EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Validate the socket - // - pSocket = NULL; - if ( NULL != pSocketProtocol ) { - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - - // - // Validate the structure pointer - // - pSocket->errno = 0; - if ( NULL == pSockAddr ) { - DEBUG (( DEBUG_BIND, - "ERROR - pSockAddr is NULL!\r\n" )); - Status = EFI_INVALID_PARAMETER; - pSocket->errno = EFAULT; - } - - // - // Validate the local address length - // - else if ( SockAddrLength < pSocket->pApi->MinimumAddressLength ) { - DEBUG (( DEBUG_BIND, - "ERROR - Invalid bind name length: %d\r\n", - SockAddrLength )); - Status = EFI_INVALID_PARAMETER; - pSocket->errno = EINVAL; - } - - // - // Validate the shutdown state - // - else if ( pSocket->bRxDisable || pSocket->bTxDisable ) { - DEBUG (( DEBUG_BIND, - "ERROR - Shutdown has been called on socket 0x%08x\r\n", - pSocket )); - pSocket->errno = EINVAL; - Status = EFI_INVALID_PARAMETER; - } - - // - // Verify the socket state - // - else if ( SOCKET_STATE_NOT_CONFIGURED != pSocket->State ) { - DEBUG (( DEBUG_BIND, - "ERROR - The socket 0x%08x is already configured!\r\n", - pSocket )); - pSocket->errno = EINVAL; - Status = EFI_ALREADY_STARTED; - } - else { - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Assume no ports are available - // - pSocket->errno = EADDRNOTAVAIL; - Status = EFI_INVALID_PARAMETER; - - // - // Walk the list of services - // - pBuffer = (UINT8 *)&mEslLayer; - pBuffer = &pBuffer[ pSocket->pApi->ServiceListOffset ]; - ppServiceListHead = (ESL_SERVICE **)pBuffer; - pService = *ppServiceListHead; - while ( NULL != pService ) { - // - // Create the port - // - pServiceBinding = pService->pServiceBinding; - ChildHandle = NULL; - Status = pServiceBinding->CreateChild ( pServiceBinding, - &ChildHandle ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_BIND | DEBUG_POOL, - "0x%08x: %s port handle created\r\n", - ChildHandle, - pService->pSocketBinding->pName )); - - // - // Open the port - // - Status = EslSocketPortAllocate ( pSocket, - pService, - ChildHandle, - pSockAddr, - TRUE, - DEBUG_BIND, - &pPort ); - } - else { - DEBUG (( DEBUG_BIND | DEBUG_POOL, - "ERROR - Failed to open %s port handle, Status: %r\r\n", - pService->pSocketBinding->pName, - Status )); - } - - // - // Set the next service - // - pService = pService->pNext; - } - - // - // Verify that at least one network connection was found - // - if ( NULL != pSocket->pPortList ) { - Status = EFI_SUCCESS; - } - else { - if ( EADDRNOTAVAIL == pSocket->errno ) { - DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT, - "ERROR - Socket address is not available!\r\n" )); - } - if ( EADDRINUSE == pSocket->errno ) { - DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT, - "ERROR - Socket address is in use!\r\n" )); - } - Status = EFI_INVALID_PARAMETER; - } - - // - // Mark this socket as bound if successful - // - if ( !EFI_ERROR ( Status )) { - pSocket->State = SOCKET_STATE_BOUND; - pSocket->errno = 0; - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - } - - // - // Return the operation status - // - if ( NULL != pErrno ) { - if ( NULL != pSocket ) { - *pErrno = pSocket->errno; - } - else { - Status = EFI_INVALID_PARAMETER; - *pErrno = ENOTSOCK; - } - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Test the bind configuration. - - @param[in] pPort Address of the ::ESL_PORT structure. - @param[in] ErrnoValue errno value if test fails - - @retval EFI_SUCCESS The connection was successfully established. - @retval Others The connection attempt failed. -**/ -EFI_STATUS -EslSocketBindTest ( - IN ESL_PORT * pPort, - IN int ErrnoValue - ) -{ - UINT8 * pBuffer; - VOID * pConfigData; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the configuration data - // - pBuffer = (UINT8 *)pPort; - pBuffer = &pBuffer [ pPort->pSocket->pApi->ConfigDataOffset ]; - pConfigData = (VOID *)pBuffer; - - // - // Validate that the port is connected - // - Status = pPort->pSocket->pApi->pfnVerifyLocalIpAddress ( pPort, pBuffer ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_WARN | DEBUG_BIND, - "WARNING - Port 0x%08x invalid IP address: %r\r\n", - pPort, - Status )); - pPort->pSocket->errno = ErrnoValue; - } - else { - // - // Attempt to use this configuration - // - Status = pPort->pfnConfigure ( pPort->pProtocol.v, pConfigData ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_WARN | DEBUG_BIND, - "WARNING - Port 0x%08x failed configuration, Status: %r\r\n", - pPort, - Status )); - pPort->pSocket->errno = ErrnoValue; - } - else { - // - // Reset the port - // - Status = pPort->pfnConfigure ( pPort->pProtocol.v, NULL ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR | DEBUG_BIND, - "ERROR - Port 0x%08x failed configuration reset, Status: %r\r\n", - pPort, - Status )); - ASSERT ( EFI_SUCCESS == Status ); - } - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Determine if the socket is closed. - - This routine checks the state of the socket to determine if - the network specific layer has completed the close operation. - - The ::close routine polls this routine to determine when the - close operation is complete. The close operation needs to - reverse the operations of the ::EslSocketAllocate routine. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS Socket successfully closed - @retval EFI_NOT_READY Close still in progress - @retval EFI_ALREADY Close operation already in progress - @retval Other Failed to close the socket -**/ -EFI_STATUS -EslSocketClosePoll ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN int * pErrno - ) -{ - int errno; - ESL_LAYER * pLayer; - ESL_SOCKET * pNextSocket; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume success - // - errno = 0; - Status = EFI_SUCCESS; - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Locate the socket - // - pLayer = &mEslLayer; - pNextSocket = pLayer->pSocketList; - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - while ( NULL != pNextSocket ) { - if ( pNextSocket == pSocket ) { - // - // Determine if the socket is in the closing state - // - if ( SOCKET_STATE_CLOSED == pSocket->State ) { - // - // Walk the list of ports - // - if ( NULL == pSocket->pPortList ) { - // - // All the ports are closed - // Close the WaitAccept event if necessary - // - if ( NULL != pSocket->WaitAccept ) { - Status = gBS->CloseEvent ( pSocket->WaitAccept ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_SOCKET | DEBUG_CLOSE | DEBUG_POOL, - "0x%08x: Closed WaitAccept event\r\n", - pSocket->WaitAccept )); - // - // Return the transmit status - // - Status = pSocket->TxError; - if ( EFI_ERROR ( Status )) { - pSocket->errno = EIO; - } - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_SOCKET | DEBUG_CLOSE | DEBUG_POOL, - "ERROR - Failed to close the WaitAccept event, Status: %r\r\n", - Status )); - ASSERT ( EFI_SUCCESS == Status ); - } - } - } - else { - // - // At least one port is still open - // - Status = EFI_NOT_READY; - errno = EAGAIN; - } - } - else { - // - // SocketCloseStart was not called - // - Status = EFI_NOT_STARTED; - errno = EPERM; - } - break; - } - - // - // Set the next socket - // - pNextSocket = pNextSocket->pNext; - } - - // - // Handle the error case where the socket was already closed - // - if ( NULL == pSocket ) { - // - // Socket not found - // - Status = EFI_NOT_FOUND; - errno = ENOTSOCK; - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - - // - // Return the operation status - // - if ( NULL != pErrno ) { - *pErrno = errno; - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Start the close operation on the socket. - - This routine calls the network specific layer to initiate the - close state machine. This routine then calls the network - specific layer to determine if the close state machine has gone - to completion. The result from this poll is returned to the - caller. - - The ::close routine calls this routine to start the close - operation which reverses the operations of the - ::EslSocketAllocate routine. The close routine then polls - the ::EslSocketClosePoll routine to determine when the - socket is closed. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[in] bCloseNow Boolean to control close behavior - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS Socket successfully closed - @retval EFI_NOT_READY Close still in progress - @retval EFI_ALREADY Close operation already in progress - @retval Other Failed to close the socket -**/ -EFI_STATUS -EslSocketCloseStart ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN BOOLEAN bCloseNow, - IN int * pErrno - ) -{ - int errno; - ESL_PORT * pNextPort; - ESL_PORT * pPort; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - errno = 0; - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Determine if the socket is already closed - // - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - if ( SOCKET_STATE_CLOSED > pSocket->State ) { - // - // Update the socket state - // - pSocket->State = SOCKET_STATE_CLOSED; - - // - // Walk the list of ports - // - pPort = pSocket->pPortList; - while ( NULL != pPort ) { - // - // Start closing the ports - // - pNextPort = pPort->pLinkSocket; - Status = EslSocketPortCloseStart ( pPort, - bCloseNow, - DEBUG_CLOSE | DEBUG_LISTEN | DEBUG_CONNECTION ); - if (( EFI_SUCCESS != Status ) - && ( EFI_NOT_READY != Status )) { - errno = EIO; - break; - } - - // - // Set the next port - // - pPort = pNextPort; - } - - // - // Attempt to finish closing the socket - // - if ( NULL == pPort ) { - Status = EslSocketClosePoll ( pSocketProtocol, &errno ); - } - } - else { - Status = EFI_NOT_READY; - errno = EAGAIN; - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - - // - // Return the operation status - // - if ( NULL != pErrno ) { - *pErrno = errno; - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Connect to a remote system via the network. - - This routine calls the network specific layer to establish - the remote system address and establish the connection to - the remote system. - - The ::connect routine calls this routine to establish a - connection with the specified remote system. This routine - is designed to be polled by the connect routine for completion - of the network connection. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[in] pSockAddr Network address of the remote system. - @param[in] SockAddrLength Length in bytes of the network address. - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS The connection was successfully established. - @retval EFI_NOT_READY The connection is in progress, call this routine again. - @retval Others The connection attempt failed. - **/ -EFI_STATUS -EslSocketConnect ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN const struct sockaddr * pSockAddr, - IN socklen_t SockAddrLength, - IN int * pErrno - ) -{ - struct sockaddr_in6 LocalAddress; - ESL_PORT * pPort; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DEBUG (( DEBUG_CONNECT, "Entering SocketConnect\r\n" )); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Validate the socket - // - pSocket = NULL; - if ( NULL != pSocketProtocol ) { - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - - // - // Validate the name length - // - if ( SockAddrLength < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data ))) { - DEBUG (( DEBUG_CONNECT, - "ERROR - Invalid bind name length: %d\r\n", - SockAddrLength )); - Status = EFI_INVALID_PARAMETER; - pSocket->errno = EINVAL; - } - else { - // - // Assume success - // - pSocket->errno = 0; - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Validate the socket state - // - switch ( pSocket->State ) { - default: - // - // Wrong socket state - // - pSocket->errno = EIO; - Status = EFI_DEVICE_ERROR; - break; - - case SOCKET_STATE_NOT_CONFIGURED: - case SOCKET_STATE_BOUND: - // - // Validate the address length - // - if ( SockAddrLength >= pSocket->pApi->MinimumAddressLength ) { - // - // Verify the API - // - if ( NULL == pSocket->pApi->pfnRemoteAddrSet ) { - // - // Already connected - // - pSocket->errno = ENOTSUP; - Status = EFI_UNSUPPORTED; - } - else { - // - // Determine if BIND was already called - // - if ( NULL == pSocket->pPortList ) { - // - // Allow any local port - // - ZeroMem ( &LocalAddress, sizeof ( LocalAddress )); - LocalAddress.sin6_len = (uint8_t)pSocket->pApi->MinimumAddressLength; - LocalAddress.sin6_family = pSocket->pApi->AddressFamily; - Status = EslSocketBind ( &pSocket->SocketProtocol, - (struct sockaddr *)&LocalAddress, - LocalAddress.sin6_len, - &pSocket->errno ); - } - if ( NULL != pSocket->pPortList ) { - // - // Walk the list of ports - // - pPort = pSocket->pPortList; - while ( NULL != pPort ) { - // - // Set the remote address - // - Status = pSocket->pApi->pfnRemoteAddrSet ( pPort, - pSockAddr, - SockAddrLength ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Set the next port - // - pPort = pPort->pLinkSocket; - } - - // - // Verify the API - // - if (( !EFI_ERROR ( Status )) - && ( NULL != pSocket->pApi->pfnConnectStart )) { - // - // Initiate the connection with the remote system - // - Status = pSocket->pApi->pfnConnectStart ( pSocket ); - - // - // Set the next state if connecting - // - if ( EFI_NOT_READY == Status ) { - pSocket->State = SOCKET_STATE_CONNECTING; - } - } - } - } - } - else { - DEBUG (( DEBUG_CONNECT, - "ERROR - Invalid address length: %d\r\n", - SockAddrLength )); - Status = EFI_INVALID_PARAMETER; - pSocket->errno = EINVAL; - } - break; - - case SOCKET_STATE_CONNECTING: - // - // Poll the network adapter - // - EslSocketRxPoll ( pSocket ); - - // - // Poll for connection completion - // - if ( NULL == pSocket->pApi->pfnConnectPoll ) { - // - // Already connected - // - pSocket->errno = EISCONN; - Status = EFI_ALREADY_STARTED; - } - else { - Status = pSocket->pApi->pfnConnectPoll ( pSocket ); - - // - // Set the next state if connected - // - if ( EFI_NOT_READY != Status ) { - if ( EFI_ERROR ( Status )) { - pSocket->State = SOCKET_STATE_BOUND; - } - } - } - break; - - case SOCKET_STATE_CONNECTED: - // - // Connected - // - Status = EFI_SUCCESS; - break; - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - } - - // - // Return the operation status - // - if ( NULL != pErrno ) { - if ( NULL != pSocket ) { - *pErrno = pSocket->errno; - } - else { - // - // Bad socket protocol - // - DEBUG (( DEBUG_ERROR | DEBUG_CONNECT, - "ERROR - pSocketProtocol invalid!\r\n" )); - Status = EFI_INVALID_PARAMETER; - *pErrno = ENOTSOCK; - } - } - - // - // Return the operation status - // - DEBUG (( DEBUG_CONNECT, "Exiting SocketConnect, Status: %r\r\n", Status )); - return Status; -} - - -/** Copy a fragmented buffer into a destination buffer. - - This support routine copies a fragmented buffer to the caller specified buffer. - - This routine is called by ::EslIp4Receive and ::EslUdp4Receive. - - @param[in] FragmentCount Number of fragments in the table - @param[in] pFragmentTable Address of an EFI_IP4_FRAGMENT_DATA structure - @param[in] BufferLength Length of the the buffer - @param[in] pBuffer Address of a buffer to receive the data. - @param[in] pDataLength Number of received data bytes in the buffer. - - @return Returns the address of the next free byte in the buffer. -**/ -UINT8 * -EslSocketCopyFragmentedBuffer ( - IN UINT32 FragmentCount, - IN EFI_IP4_FRAGMENT_DATA * pFragmentTable, - IN size_t BufferLength, - IN UINT8 * pBuffer, - OUT size_t * pDataLength - ) -{ - size_t BytesToCopy; - UINT32 Fragment; - UINT8 * pBufferEnd; - UINT8 * pData; - - DBG_ENTER ( ); - - // - // Validate the IP and UDP structures are identical - // - ASSERT ( OFFSET_OF ( EFI_IP4_FRAGMENT_DATA, FragmentLength ) - == OFFSET_OF ( EFI_UDP4_FRAGMENT_DATA, FragmentLength )); - ASSERT ( OFFSET_OF ( EFI_IP4_FRAGMENT_DATA, FragmentBuffer ) - == OFFSET_OF ( EFI_UDP4_FRAGMENT_DATA, FragmentBuffer )); - - // - // Copy the received data - // - Fragment = 0; - pBufferEnd = &pBuffer [ BufferLength ]; - while (( pBufferEnd > pBuffer ) && ( FragmentCount > Fragment )) { - // - // Determine the amount of received data - // - pData = pFragmentTable[Fragment].FragmentBuffer; - BytesToCopy = pFragmentTable[Fragment].FragmentLength; - if (((size_t)( pBufferEnd - pBuffer )) < BytesToCopy ) { - BytesToCopy = pBufferEnd - pBuffer; - } - - // - // Move the data into the buffer - // - DEBUG (( DEBUG_RX, - "0x%08x --> 0x%08x: Copy data 0x%08x bytes\r\n", - pData, - pBuffer, - BytesToCopy )); - CopyMem ( pBuffer, pData, BytesToCopy ); - pBuffer += BytesToCopy; - Fragment += 1; - } - - // - // Return the data length and the buffer address - // - *pDataLength = BufferLength - ( pBufferEnd - pBuffer ); - DBG_EXIT_HEX ( pBuffer ); - return pBuffer; -} - - -/** Free the socket. - - This routine frees the socket structure and handle resources. - - The ::close routine calls EslServiceFreeProtocol which then calls - this routine to free the socket context structure and close the - handle. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS The socket resources were returned successfully. -**/ -EFI_STATUS -EslSocketFree ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN int * pErrno - ) -{ - EFI_HANDLE ChildHandle; - int errno; - ESL_LAYER * pLayer; - ESL_SOCKET * pSocket; - ESL_SOCKET * pSocketPrevious; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume failure - // - errno = EIO; - pSocket = NULL; - Status = EFI_INVALID_PARAMETER; - - // - // Validate the socket - // - pLayer = &mEslLayer; - if ( NULL != pSocketProtocol ) { - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Walk the socket list - // - pSocketPrevious = pLayer->pSocketList; - if ( NULL != pSocketPrevious ) { - if ( pSocket == pSocketPrevious ) { - // - // Remove the socket from the head of the list - // - pLayer->pSocketList = pSocket->pNext; - } - else { - // - // Find the socket in the middle of the list - // - while (( NULL != pSocketPrevious ) - && ( pSocket != pSocketPrevious->pNext )) { - // - // Set the next socket - // - pSocketPrevious = pSocketPrevious->pNext; - } - if ( NULL != pSocketPrevious ) { - // - // Remove the socket from the middle of the list - // - pSocketPrevious = pSocket->pNext; - } - } - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_POOL, - "ERROR - Socket list is empty!\r\n" )); - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - - // - // Determine if the socket was found - // - if ( NULL != pSocketPrevious ) { - pSocket->pNext = NULL; - - // - // Remove the socket protocol - // - ChildHandle = pSocket->SocketProtocol.SocketHandle; - Status = gBS->UninstallMultipleProtocolInterfaces ( - ChildHandle, - &gEfiSocketProtocolGuid, - &pSocket->SocketProtocol, - NULL ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_POOL | DEBUG_INFO, - "Removed: gEfiSocketProtocolGuid from 0x%08x\r\n", - ChildHandle )); - - // - // Free the socket structure - // - Status = gBS->FreePool ( pSocket ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_POOL, - "0x%08x: Free pSocket, %d bytes\r\n", - pSocket, - sizeof ( *pSocket ))); - errno = 0; - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_POOL, - "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n", - pSocket, - Status )); - } - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO, - "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n", - ChildHandle, - Status )); - } - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_INFO, - "ERROR - The socket was not in the socket list!\r\n" )); - Status = EFI_NOT_FOUND; - } - } - else { - DEBUG (( DEBUG_ERROR, - "ERROR - Invalid parameter pSocketProtocol is NULL\r\n" )); - } - - // - // Return the errno value if possible - // - if ( NULL != pErrno ) { - *pErrno = errno; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Get the local address. - - This routine calls the network specific layer to get the network - address of the local host connection point. - - The ::getsockname routine calls this routine to obtain the network - address associated with the local host connection point. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[out] pAddress Network address to receive the local system address - @param[in,out] pAddressLength Length of the local network address structure - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS - Local address successfully returned - **/ -EFI_STATUS -EslSocketGetLocalAddress ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - OUT struct sockaddr * pAddress, - IN OUT socklen_t * pAddressLength, - IN int * pErrno - ) -{ - socklen_t LengthInBytes; - ESL_PORT * pPort; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Validate the socket - // - pSocket = NULL; - if ( NULL != pSocketProtocol ) { - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - - // - // Verify the socket state - // - EslSocketIsConfigured ( pSocket ); - if ( pSocket->bAddressSet ) { - // - // Verify the address buffer and length address - // - if (( NULL != pAddress ) && ( NULL != pAddressLength )) { - // - // Verify the API - // - if ( NULL == pSocket->pApi->pfnLocalAddrGet ) { - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTSUP; - } - else { - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Verify that there is just a single connection - // - pPort = pSocket->pPortList; - if ( NULL != pPort ) { - // - // Verify the address length - // - LengthInBytes = pSocket->pApi->AddressLength; - if (( LengthInBytes <= *pAddressLength ) - && ( 255 >= LengthInBytes )) { - // - // Return the local address and address length - // - ZeroMem ( pAddress, LengthInBytes ); - pAddress->sa_len = (uint8_t)LengthInBytes; - *pAddressLength = pAddress->sa_len; - pSocket->pApi->pfnLocalAddrGet ( pPort, pAddress ); - pSocket->errno = 0; - Status = EFI_SUCCESS; - } - else { - pSocket->errno = EINVAL; - Status = EFI_INVALID_PARAMETER; - } - } - else { - pSocket->errno = ENOTCONN; - Status = EFI_NOT_STARTED; - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - } - else { - pSocket->errno = EINVAL; - Status = EFI_INVALID_PARAMETER; - } - } - else { - // - // Address not set - // - Status = EFI_NOT_STARTED; - pSocket->errno = EADDRNOTAVAIL; - } - } - - // - // Return the operation status - // - if ( NULL != pErrno ) { - if ( NULL != pSocket ) { - *pErrno = pSocket->errno; - } - else { - Status = EFI_INVALID_PARAMETER; - *pErrno = ENOTSOCK; - } - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Get the peer address. - - This routine calls the network specific layer to get the remote - system connection point. - - The ::getpeername routine calls this routine to obtain the network - address of the remote connection point. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[out] pAddress Network address to receive the remote system address - @param[in,out] pAddressLength Length of the remote network address structure - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS - Remote address successfully returned - **/ -EFI_STATUS -EslSocketGetPeerAddress ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - OUT struct sockaddr * pAddress, - IN OUT socklen_t * pAddressLength, - IN int * pErrno - ) -{ - socklen_t LengthInBytes; - ESL_PORT * pPort; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Validate the socket - // - pSocket = NULL; - if ( NULL != pSocketProtocol ) { - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - - // - // Verify the socket state - // - Status = EslSocketIsConfigured ( pSocket ); - if ( !EFI_ERROR ( Status )) { - // - // Verify the API - // - if ( NULL == pSocket->pApi->pfnRemoteAddrGet ) { - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTSUP; - } - else { - // - // Verify the address buffer and length address - // - if (( NULL != pAddress ) && ( NULL != pAddressLength )) { - // - // Verify the socket state - // - if ( SOCKET_STATE_CONNECTED == pSocket->State ) { - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Verify that there is just a single connection - // - pPort = pSocket->pPortList; - if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) { - // - // Verify the address length - // - LengthInBytes = pSocket->pApi->AddressLength; - if ( LengthInBytes <= *pAddressLength ) { - // - // Return the local address - // - ZeroMem ( pAddress, LengthInBytes ); - pAddress->sa_len = (uint8_t)LengthInBytes; - *pAddressLength = pAddress->sa_len; - pSocket->pApi->pfnRemoteAddrGet ( pPort, pAddress ); - pSocket->errno = 0; - Status = EFI_SUCCESS; - } - else { - pSocket->errno = EINVAL; - Status = EFI_INVALID_PARAMETER; - } - } - else { - pSocket->errno = ENOTCONN; - Status = EFI_NOT_STARTED; - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - else { - pSocket->errno = ENOTCONN; - Status = EFI_NOT_STARTED; - } - } - else { - pSocket->errno = EINVAL; - Status = EFI_INVALID_PARAMETER; - } - } - } - } - - // - // Return the operation status - // - if ( NULL != pErrno ) { - if ( NULL != pSocket ) { - *pErrno = pSocket->errno; - } - else { - Status = EFI_INVALID_PARAMETER; - *pErrno = ENOTSOCK; - } - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Free the ESL_IO_MGMT event and structure. - - This support routine walks the free list to close the event in - the ESL_IO_MGMT structure and remove the structure from the free - list. - - See the \ref TransmitEngine section. - - @param[in] pPort Address of an ::ESL_PORT structure - @param[in] ppFreeQueue Address of the free queue head - @param[in] DebugFlags Flags for debug messages - @param[in] pEventName Zero terminated string containing the event name - - @retval EFI_SUCCESS - The structures were properly initialized -**/ -EFI_STATUS -EslSocketIoFree ( - IN ESL_PORT * pPort, - IN ESL_IO_MGMT ** ppFreeQueue, - IN UINTN DebugFlags, - IN CHAR8 * pEventName - ) -{ - UINT8 * pBuffer; - EFI_EVENT * pEvent; - ESL_IO_MGMT * pIo; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Walk the list of IO structures - // - pSocket = pPort->pSocket; - while ( *ppFreeQueue ) { - // - // Free the event for this structure - // - pIo = *ppFreeQueue; - pBuffer = (UINT8 *)pIo; - pBuffer = &pBuffer[ pSocket->TxTokenEventOffset ]; - pEvent = (EFI_EVENT *)pBuffer; - Status = gBS->CloseEvent ( *pEvent ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to close the %a event, Status: %r\r\n", - pEventName, - Status )); - pSocket->errno = ENOMEM; - break; - } - DEBUG (( DebugFlags, - "0x%08x: Closed %a event 0x%08x\r\n", - pIo, - pEventName, - *pEvent )); - - // - // Remove this structure from the queue - // - *ppFreeQueue = pIo->pNext; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Initialize the ESL_IO_MGMT structures. - - This support routine initializes the ESL_IO_MGMT structure and - places them on to a free list. - - This routine is called by ::EslSocketPortAllocate routines to prepare - the transmit engines. See the \ref TransmitEngine section. - - @param[in] pPort Address of an ::ESL_PORT structure - @param[in, out] ppIo Address containing the first structure address. Upon - return this buffer contains the next structure address. - @param[in] TokenCount Number of structures to initialize - @param[in] ppFreeQueue Address of the free queue head - @param[in] DebugFlags Flags for debug messages - @param[in] pEventName Zero terminated string containing the event name - @param[in] pfnCompletion Completion routine address - - @retval EFI_SUCCESS - The structures were properly initialized -**/ -EFI_STATUS -EslSocketIoInit ( - IN ESL_PORT * pPort, - IN ESL_IO_MGMT ** ppIo, - IN UINTN TokenCount, - IN ESL_IO_MGMT ** ppFreeQueue, - IN UINTN DebugFlags, - IN CHAR8 * pEventName, - IN PFN_API_IO_COMPLETE pfnCompletion - ) -{ - ESL_IO_MGMT * pEnd; - EFI_EVENT * pEvent; - ESL_IO_MGMT * pIo; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Walk the list of IO structures - // - pSocket = pPort->pSocket; - pIo = *ppIo; - pEnd = &pIo [ TokenCount ]; - while ( pEnd > pIo ) { - // - // Initialize the IO structure - // - pIo->pPort = pPort; - pIo->pPacket = NULL; - - // - // Allocate the event for this structure - // - pEvent = (EFI_EVENT *)&(((UINT8 *)pIo)[ pSocket->TxTokenEventOffset ]); - Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_SOCKETS, - (EFI_EVENT_NOTIFY)pfnCompletion, - pIo, - pEvent ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to create the %a event, Status: %r\r\n", - pEventName, - Status )); - pSocket->errno = ENOMEM; - break; - } - DEBUG (( DebugFlags, - "0x%08x: Created %a event 0x%08x\r\n", - pIo, - pEventName, - *pEvent )); - - // - // Add this structure to the queue - // - pIo->pNext = *ppFreeQueue; - *ppFreeQueue = pIo; - - // - // Set the next structure - // - pIo += 1; - } - - // - // Save the next structure - // - *ppIo = pIo; - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Determine if the socket is configured. - - This support routine is called to determine if the socket if the - configuration call was made to the network layer. The following - routines call this routine to verify that they may be successful - in their operations: - - - @param[in] pSocket Address of an ::ESL_SOCKET structure - - @retval EFI_SUCCESS - The socket is configured -**/ -EFI_STATUS -EslSocketIsConfigured ( - IN ESL_SOCKET * pSocket - ) -{ - EFI_STATUS Status; - EFI_TPL TplPrevious; - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Verify the socket state - // - if ( !pSocket->bConfigured ) { - DBG_ENTER ( ); - - // - // Verify the API - // - if ( NULL == pSocket->pApi->pfnIsConfigured ) { - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTSUP; - } - else { - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Determine if the socket is configured - // - Status = pSocket->pApi->pfnIsConfigured ( pSocket ); - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - - // - // Set errno if a failure occurs - // - if ( EFI_ERROR ( Status )) { - pSocket->errno = EADDRNOTAVAIL; - } - } - - DBG_EXIT_STATUS ( Status ); - } - - // - // Return the configuration status - // - return Status; -} - - -/** Establish the known port to listen for network connections. - - This routine calls into the network protocol layer to establish - a handler that is called upon connection completion. The handler - is responsible for inserting the connection into the FIFO. - - The ::listen routine indirectly calls this routine to place the - socket into a state that enables connection attempts. Connections - are placed in a FIFO that is serviced by the application. The - application calls the ::accept (::EslSocketAccept) routine to - remove the next connection from the FIFO and get the associated - socket and address. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[in] Backlog Backlog specifies the maximum FIFO depth for - the connections waiting for the application - to call accept. Connection attempts received - while the queue is full are refused. - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS - Socket successfully created - @retval Other - Failed to enable the socket for listen -**/ -EFI_STATUS -EslSocketListen ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN INT32 Backlog, - OUT int * pErrno - ) -{ - ESL_SOCKET * pSocket; - EFI_STATUS Status; - EFI_STATUS TempStatus; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Validate the socket - // - pSocket = NULL; - if ( NULL != pSocketProtocol ) { - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - - // - // Verify the API - // - if ( NULL == pSocket->pApi->pfnListen ) { - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTSUP; - } - else { - // - // Assume success - // - pSocket->Status = EFI_SUCCESS; - pSocket->errno = 0; - - // - // Verify that the bind operation was successful - // - if ( SOCKET_STATE_BOUND == pSocket->State ) { - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Create the event for SocketAccept completion - // - Status = gBS->CreateEvent ( 0, - TPL_SOCKETS, - NULL, - NULL, - &pSocket->WaitAccept ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_POOL, - "0x%08x: Created WaitAccept event\r\n", - pSocket->WaitAccept )); - // - // Set the maximum FIFO depth - // - if ( 0 >= Backlog ) { - Backlog = MAX_PENDING_CONNECTIONS; - } - else { - if ( SOMAXCONN < Backlog ) { - Backlog = SOMAXCONN; - } - else { - pSocket->MaxFifoDepth = Backlog; - } - } - - // - // Initiate the connection attempt listen - // - Status = pSocket->pApi->pfnListen ( pSocket ); - - // - // Place the socket in the listen state if successful - // - if ( !EFI_ERROR ( Status )) { - pSocket->State = SOCKET_STATE_LISTENING; - pSocket->bListenCalled = TRUE; - } - else { - // - // Not waiting for SocketAccept to complete - // - TempStatus = gBS->CloseEvent ( pSocket->WaitAccept ); - if ( !EFI_ERROR ( TempStatus )) { - DEBUG (( DEBUG_POOL, - "0x%08x: Closed WaitAccept event\r\n", - pSocket->WaitAccept )); - pSocket->WaitAccept = NULL; - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_POOL, - "ERROR - Failed to close WaitAccept event, Status: %r\r\n", - TempStatus )); - ASSERT ( EFI_SUCCESS == TempStatus ); - } - } - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_LISTEN, - "ERROR - Failed to create the WaitAccept event, Status: %r\r\n", - Status )); - pSocket->errno = ENOMEM; - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_LISTEN, - "ERROR - Bind operation must be performed first!\r\n" )); - pSocket->errno = ( SOCKET_STATE_NOT_CONFIGURED == pSocket->State ) ? EDESTADDRREQ - : EINVAL; - Status = EFI_NO_MAPPING; - } - } - } - - // - // Return the operation status - // - if ( NULL != pErrno ) { - if ( NULL != pSocket ) { - *pErrno = pSocket->errno; - } - else { - Status = EFI_INVALID_PARAMETER; - *pErrno = ENOTSOCK; - } - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Get the socket options. - - This routine handles the socket level options and passes the - others to the network specific layer. - - The ::getsockopt routine calls this routine to retrieve the - socket options one at a time by name. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[in] level Option protocol level - @param[in] OptionName Name of the option - @param[out] pOptionValue Buffer to receive the option value - @param[in,out] pOptionLength Length of the buffer in bytes, - upon return length of the option value in bytes - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS - Socket data successfully received - **/ -EFI_STATUS -EslSocketOptionGet ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN int level, - IN int OptionName, - OUT void * __restrict pOptionValue, - IN OUT socklen_t * __restrict pOptionLength, - IN int * pErrno - ) -{ - int errno; - socklen_t LengthInBytes; - socklen_t MaxBytes; - CONST UINT8 * pOptionData; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Assume failure - // - errno = EINVAL; - Status = EFI_INVALID_PARAMETER; - - // - // Validate the socket - // - pSocket = NULL; - if ( NULL == pSocketProtocol ) { - DEBUG (( DEBUG_OPTION, "ERROR - pSocketProtocol is NULL!\r\n" )); - } - else if ( NULL == pOptionValue ) { - DEBUG (( DEBUG_OPTION, "ERROR - No option buffer specified\r\n" )); - } - else if ( NULL == pOptionLength ) { - DEBUG (( DEBUG_OPTION, "ERROR - Option length not specified!\r\n" )); - } - else { - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - LengthInBytes = 0; - MaxBytes = *pOptionLength; - pOptionData = NULL; - switch ( level ) { - default: - // - // See if the protocol will handle the option - // - if ( NULL != pSocket->pApi->pfnOptionGet ) { - if ( pSocket->pApi->DefaultProtocol == level ) { - Status = pSocket->pApi->pfnOptionGet ( pSocket, - OptionName, - (CONST void ** __restrict)&pOptionData, - &LengthInBytes ); - errno = pSocket->errno; - break; - } - else { - // - // Protocol not supported - // - DEBUG (( DEBUG_OPTION, - "ERROR - The socket does not support this protocol!\r\n" )); - } - } - else { - // - // Protocol level not supported - // - DEBUG (( DEBUG_OPTION, - "ERROR - %a does not support any options!\r\n", - pSocket->pApi->pName )); - } - errno = ENOPROTOOPT; - Status = EFI_INVALID_PARAMETER; - break; - - case SOL_SOCKET: - switch ( OptionName ) { - default: - // - // Socket option not supported - // - DEBUG (( DEBUG_INFO | DEBUG_OPTION, "ERROR - Invalid socket option!\r\n" )); - errno = EINVAL; - Status = EFI_INVALID_PARAMETER; - break; - - case SO_ACCEPTCONN: - // - // Return the listen flag - // - pOptionData = (CONST UINT8 *)&pSocket->bListenCalled; - LengthInBytes = sizeof ( pSocket->bListenCalled ); - break; - - case SO_DEBUG: - // - // Return the debug flags - // - pOptionData = (CONST UINT8 *)&pSocket->bOobInLine; - LengthInBytes = sizeof ( pSocket->bOobInLine ); - break; - - case SO_OOBINLINE: - // - // Return the out-of-band inline flag - // - pOptionData = (CONST UINT8 *)&pSocket->bOobInLine; - LengthInBytes = sizeof ( pSocket->bOobInLine ); - break; - - case SO_RCVTIMEO: - // - // Return the receive timeout - // - pOptionData = (CONST UINT8 *)&pSocket->RxTimeout; - LengthInBytes = sizeof ( pSocket->RxTimeout ); - break; - - case SO_RCVBUF: - // - // Return the maximum receive buffer size - // - pOptionData = (CONST UINT8 *)&pSocket->MaxRxBuf; - LengthInBytes = sizeof ( pSocket->MaxRxBuf ); - break; - - case SO_REUSEADDR: - // - // Return the address reuse flag - // - pOptionData = (UINT8 *)&pSocket->bReUseAddr; - LengthInBytes = sizeof ( pSocket->bReUseAddr ); - break; - - case SO_SNDBUF: - // - // Return the maximum transmit buffer size - // - pOptionData = (CONST UINT8 *)&pSocket->MaxTxBuf; - LengthInBytes = sizeof ( pSocket->MaxTxBuf ); - break; - - case SO_TYPE: - // - // Return the socket type - // - pOptionData = (CONST UINT8 *)&pSocket->Type; - LengthInBytes = sizeof ( pSocket->Type ); - break; - } - break; - } - - // - // Return the option length - // - *pOptionLength = LengthInBytes; - - // - // Determine if the option is present - // - if ( 0 != LengthInBytes ) { - // - // Silently truncate the value length - // - if ( LengthInBytes > MaxBytes ) { - DEBUG (( DEBUG_OPTION, - "INFO - Truncating option from %d to %d bytes\r\n", - LengthInBytes, - MaxBytes )); - LengthInBytes = MaxBytes; - } - - // - // Return the value - // - CopyMem ( pOptionValue, pOptionData, LengthInBytes ); - - // - // Zero fill any remaining space - // - if ( LengthInBytes < MaxBytes ) { - ZeroMem ( &((UINT8 *)pOptionValue)[LengthInBytes], MaxBytes - LengthInBytes ); - } - errno = 0; - Status = EFI_SUCCESS; - } - } - - // - // Return the operation status - // - if ( NULL != pErrno ) { - *pErrno = errno; - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Set the socket options. - - This routine handles the socket level options and passes the - others to the network specific layer. - - The ::setsockopt routine calls this routine to adjust the socket - options one at a time by name. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[in] level Option protocol level - @param[in] OptionName Name of the option - @param[in] pOptionValue Buffer containing the option value - @param[in] OptionLength Length of the buffer in bytes - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS - Option successfully set -**/ -EFI_STATUS -EslSocketOptionSet ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN int level, - IN int OptionName, - IN CONST void * pOptionValue, - IN socklen_t OptionLength, - IN int * pErrno - ) -{ - BOOLEAN bTrueFalse; - int errno; - socklen_t LengthInBytes; - UINT8 * pOptionData; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Assume failure - // - errno = EINVAL; - Status = EFI_INVALID_PARAMETER; - - // - // Validate the socket - // - pSocket = NULL; - if ( NULL == pSocketProtocol ) { - DEBUG (( DEBUG_OPTION, "ERROR - pSocketProtocol is NULL!\r\n" )); - } - else if ( NULL == pOptionValue ) { - DEBUG (( DEBUG_OPTION, "ERROR - No option buffer specified\r\n" )); - } - else - { - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - if ( pSocket->bRxDisable || pSocket->bTxDisable ) { - DEBUG (( DEBUG_OPTION, "ERROR - Socket has been shutdown!\r\n" )); - } - else { - LengthInBytes = 0; - pOptionData = NULL; - switch ( level ) { - default: - // - // See if the protocol will handle the option - // - if ( NULL != pSocket->pApi->pfnOptionSet ) { - if ( pSocket->pApi->DefaultProtocol == level ) { - Status = pSocket->pApi->pfnOptionSet ( pSocket, - OptionName, - pOptionValue, - OptionLength ); - errno = pSocket->errno; - break; - } - else { - // - // Protocol not supported - // - DEBUG (( DEBUG_OPTION, - "ERROR - The socket does not support this protocol!\r\n" )); - } - } - else { - // - // Protocol level not supported - // - DEBUG (( DEBUG_OPTION, - "ERROR - %a does not support any options!\r\n", - pSocket->pApi->pName )); - } - errno = ENOPROTOOPT; - Status = EFI_INVALID_PARAMETER; - break; - - case SOL_SOCKET: - switch ( OptionName ) { - default: - // - // Option not supported - // - DEBUG (( DEBUG_OPTION, - "ERROR - Sockets does not support this option!\r\n" )); - errno = EINVAL; - Status = EFI_INVALID_PARAMETER; - break; - - case SO_DEBUG: - // - // Set the debug flags - // - pOptionData = (UINT8 *)&pSocket->bOobInLine; - LengthInBytes = sizeof ( pSocket->bOobInLine ); - break; - - case SO_OOBINLINE: - pOptionData = (UINT8 *)&pSocket->bOobInLine; - LengthInBytes = sizeof ( pSocket->bOobInLine ); - - // - // Validate the option length - // - if ( sizeof ( UINT32 ) == OptionLength ) { - // - // Restrict the input to TRUE or FALSE - // - bTrueFalse = TRUE; - if ( 0 == *(UINT32 *)pOptionValue ) { - bTrueFalse = FALSE; - } - pOptionValue = &bTrueFalse; - } - else { - // - // Force an invalid option length error - // - OptionLength = LengthInBytes - 1; - } - break; - - case SO_RCVTIMEO: - // - // Return the receive timeout - // - pOptionData = (UINT8 *)&pSocket->RxTimeout; - LengthInBytes = sizeof ( pSocket->RxTimeout ); - break; - - case SO_RCVBUF: - // - // Return the maximum receive buffer size - // - pOptionData = (UINT8 *)&pSocket->MaxRxBuf; - LengthInBytes = sizeof ( pSocket->MaxRxBuf ); - break; - - case SO_REUSEADDR: - // - // Return the address reuse flag - // - pOptionData = (UINT8 *)&pSocket->bReUseAddr; - LengthInBytes = sizeof ( pSocket->bReUseAddr ); - break; - - case SO_SNDBUF: - // - // Send buffer size - // - // - // Return the maximum transmit buffer size - // - pOptionData = (UINT8 *)&pSocket->MaxTxBuf; - LengthInBytes = sizeof ( pSocket->MaxTxBuf ); - break; - } - break; - } - - // - // Determine if an option was found - // - if ( 0 != LengthInBytes ) { - // - // Validate the option length - // - if ( LengthInBytes <= OptionLength ) { - // - // Set the option value - // - CopyMem ( pOptionData, pOptionValue, LengthInBytes ); - errno = 0; - Status = EFI_SUCCESS; - } - else { - DEBUG (( DEBUG_OPTION, - "ERROR - Buffer to small, %d bytes < %d bytes!\r\n", - OptionLength, - LengthInBytes )); - } - } - } - } - - // - // Return the operation status - // - if ( NULL != pErrno ) { - *pErrno = errno; - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Allocate a packet for a receive or transmit operation. - - This support routine is called by ::EslSocketRxStart and the - network specific TxBuffer routines to get buffer space for the - next operation. - - @param[in] ppPacket Address to receive the ::ESL_PACKET structure - @param[in] LengthInBytes Length of the packet structure - @param[in] ZeroBytes Length of packet to zero - @param[in] DebugFlags Flags for debug messages - - @retval EFI_SUCCESS - The packet was allocated successfully -**/ -EFI_STATUS -EslSocketPacketAllocate ( - IN ESL_PACKET ** ppPacket, - IN size_t LengthInBytes, - IN size_t ZeroBytes, - IN UINTN DebugFlags - ) -{ - ESL_PACKET * pPacket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Allocate a packet structure - // - LengthInBytes += sizeof ( *pPacket ) - - sizeof ( pPacket->Op ); - Status = gBS->AllocatePool ( EfiRuntimeServicesData, - LengthInBytes, - (VOID **)&pPacket ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DebugFlags | DEBUG_POOL, - "0x%08x: Allocate pPacket, %d bytes\r\n", - pPacket, - LengthInBytes )); - if ( 0 != ZeroBytes ) { - ZeroMem ( &pPacket->Op, ZeroBytes ); - } - pPacket->PacketSize = LengthInBytes; - } - else { - DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INFO, - "ERROR - Packet allocation failed for %d bytes, Status: %r\r\n", - LengthInBytes, - Status )); - pPacket = NULL; - } - - // - // Return the packet - // - *ppPacket = pPacket; - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Free a packet used for receive or transmit operation. - - This support routine is called by the network specific Close - and TxComplete routines and during error cases in RxComplete - and TxBuffer. Note that the network layers typically place - receive packets on the ESL_SOCKET::pRxFree list for reuse. - - @param[in] pPacket Address of an ::ESL_PACKET structure - @param[in] DebugFlags Flags for debug messages - - @retval EFI_SUCCESS - The packet was allocated successfully -**/ -EFI_STATUS -EslSocketPacketFree ( - IN ESL_PACKET * pPacket, - IN UINTN DebugFlags - ) -{ - UINTN LengthInBytes; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Free a packet structure - // - LengthInBytes = pPacket->PacketSize; - Status = gBS->FreePool ( pPacket ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DebugFlags | DEBUG_POOL, - "0x%08x: Free pPacket, %d bytes\r\n", - pPacket, - LengthInBytes )); - } - else { - DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INFO, - "ERROR - Failed to free packet 0x%08x, Status: %r\r\n", - pPacket, - Status )); - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Poll a socket for pending activity. - - This routine builds a detected event mask which is returned to - the caller in the buffer provided. - - The ::poll routine calls this routine to determine if the socket - needs to be serviced as a result of connection, error, receive or - transmit activity. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[in] Events Events of interest for this socket - @param[in] pEvents Address to receive the detected events - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS - Socket successfully polled - @retval EFI_INVALID_PARAMETER - When pEvents is NULL -**/ -EFI_STATUS -EslSocketPoll ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN short Events, - IN short * pEvents, - IN int * pErrno - ) -{ - short DetectedEvents; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - EFI_TPL TplPrevious; - short ValidEvents; - int _errno = EINVAL; - - DEBUG (( DEBUG_POLL, "Entering SocketPoll\r\n" )); - - // - // Assume success - // - Status = EFI_SUCCESS; - DetectedEvents = 0; - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - pSocket->errno = 0; - - // - // Verify the socket state - // - Status = EslSocketIsConfigured ( pSocket ); - if ( !EFI_ERROR ( Status )) { - // - // Check for invalid events - // - ValidEvents = POLLIN - | POLLPRI - | POLLOUT | POLLWRNORM - | POLLERR - | POLLHUP - | POLLNVAL - | POLLRDNORM - | POLLRDBAND - | POLLWRBAND ; - if ( 0 != ( Events & ( ~ValidEvents ))) { - DetectedEvents |= POLLNVAL; - DEBUG (( DEBUG_INFO | DEBUG_POLL, - "ERROR - Invalid event mask, Valid Events: 0x%04x, Invalid Events: 0x%04x\r\n", - Events & ValidEvents, - Events & ( ~ValidEvents ))); - } - else { - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Increase the network performance by extending the - // polling (idle) loop down into the LAN driver - // - EslSocketRxPoll ( pSocket ); - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - - // - // Check for pending connections - // - if ( 0 != pSocket->FifoDepth ) { - // - // A connection is waiting for an accept call - // See posix connect documentation at - // http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.htm - // - DetectedEvents |= POLLIN | POLLRDNORM; - } - if ( pSocket->bConnected ) { - // - // A connection is present - // See posix connect documentation at - // http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.htm - // - DetectedEvents |= POLLOUT | POLLWRNORM; - } - - // - // The following bits are set based upon the POSIX poll documentation at - // http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html - // - - // - // Check for urgent receive data - // - if ( 0 < pSocket->RxOobBytes ) { - DetectedEvents |= POLLRDBAND | POLLPRI | POLLIN; - } - - // - // Check for normal receive data - // - if (( 0 < pSocket->RxBytes ) - || ( EFI_SUCCESS != pSocket->RxError )) { - DetectedEvents |= POLLRDNORM | POLLIN; - } - - // - // Handle the receive errors - // - if (( EFI_SUCCESS != pSocket->RxError ) - && ( 0 == ( DetectedEvents & POLLIN ))) { - DetectedEvents |= POLLERR | POLLIN | POLLRDNORM | POLLRDBAND; - } - - // - // Check for urgent transmit data buffer space - // - if (( MAX_TX_DATA > pSocket->TxOobBytes ) - || ( EFI_SUCCESS != pSocket->TxError )) { - DetectedEvents |= POLLWRBAND; - } - - // - // Check for normal transmit data buffer space - // - if (( MAX_TX_DATA > pSocket->TxBytes ) - || ( EFI_SUCCESS != pSocket->TxError )) { - DetectedEvents |= POLLWRNORM; - } - - // - // Handle the transmit error - // - if ( EFI_ERROR ( pSocket->TxError )) { - DetectedEvents |= POLLERR; - } - _errno = pSocket->errno; - } - } - - // - // Return the detected events - // - *pEvents = DetectedEvents & ( Events - | POLLERR - | POLLHUP - | POLLNVAL ); - if ( NULL != pErrno ) { - *pErrno = _errno; - } - // - // Return the operation status - // - DEBUG (( DEBUG_POLL, "Exiting SocketPoll, Status: %r\r\n", Status )); - return Status; -} - - -/** Allocate and initialize a ESL_PORT structure. - - This routine initializes an ::ESL_PORT structure for use by - the socket. This routine calls a routine via - ESL_PROTOCOL_API::pfnPortAllocate to initialize the network - specific resources. The resources are released later by the - \ref PortCloseStateMachine. - - This support routine is called by: - - to connect the socket with the underlying network adapter - to the socket. - - @param[in] pSocket Address of an ::ESL_SOCKET structure. - @param[in] pService Address of an ::ESL_SERVICE structure. - @param[in] ChildHandle Network protocol child handle - @param[in] pSockAddr Address of a sockaddr structure that contains the - connection point on the local machine. An IPv4 address - of INADDR_ANY specifies that the connection is made to - all of the network stacks on the platform. Specifying a - specific IPv4 address restricts the connection to the - network stack supporting that address. Specifying zero - for the port causes the network layer to assign a port - number from the dynamic range. Specifying a specific - port number causes the network layer to use that port. - @param[in] bBindTest TRUE if EslSocketBindTest should be called - @param[in] DebugFlags Flags for debug messages - @param[out] ppPort Buffer to receive new ::ESL_PORT structure address - - @retval EFI_SUCCESS - Socket successfully created -**/ -EFI_STATUS -EslSocketPortAllocate ( - IN ESL_SOCKET * pSocket, - IN ESL_SERVICE * pService, - IN EFI_HANDLE ChildHandle, - IN CONST struct sockaddr * pSockAddr, - IN BOOLEAN bBindTest, - IN UINTN DebugFlags, - OUT ESL_PORT ** ppPort - ) -{ - UINTN LengthInBytes; - UINT8 * pBuffer; - ESL_IO_MGMT * pIo; - ESL_LAYER * pLayer; - ESL_PORT * pPort; - EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding; - CONST ESL_SOCKET_BINDING * pSocketBinding; - EFI_STATUS Status; - EFI_STATUS TempStatus; - - DBG_ENTER ( ); - - // - // Verify the socket layer synchronization - // - VERIFY_TPL ( TPL_SOCKETS ); - - // - // Use for/break instead of goto - pSocketBinding = pService->pSocketBinding; - for ( ; ; ) { - // - // Allocate a port structure - // - pLayer = &mEslLayer; - LengthInBytes = sizeof ( *pPort ) - + ESL_STRUCTURE_ALIGNMENT_BYTES - + (( pSocketBinding->RxIo - + pSocketBinding->TxIoNormal - + pSocketBinding->TxIoUrgent ) - * sizeof ( ESL_IO_MGMT )); - pPort = (ESL_PORT *) AllocateZeroPool ( LengthInBytes ); - if ( NULL == pPort ) { - Status = EFI_OUT_OF_RESOURCES; - pSocket->errno = ENOMEM; - break; - } - DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT, - "0x%08x: Allocate pPort, %d bytes\r\n", - pPort, - LengthInBytes )); - - // - // Initialize the port - // - pPort->DebugFlags = DebugFlags; - pPort->Handle = ChildHandle; - pPort->pService = pService; - pPort->pServiceBinding = pService->pServiceBinding; - pPort->pSocket = pSocket; - pPort->pSocketBinding = pService->pSocketBinding; - pPort->Signature = PORT_SIGNATURE; - - // - // Open the port protocol - // - Status = gBS->OpenProtocol ( pPort->Handle, - pSocketBinding->pNetworkProtocolGuid, - &pPort->pProtocol.v, - pLayer->ImageHandle, - NULL, - EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to open network protocol GUID on controller 0x%08x\r\n", - pPort->Handle )); - pSocket->errno = EEXIST; - break; - } - DEBUG (( DebugFlags, - "0x%08x: Network protocol GUID opened on controller 0x%08x\r\n", - pPort->pProtocol.v, - pPort->Handle )); - - // - // Initialize the port specific resources - // - Status = pSocket->pApi->pfnPortAllocate ( pPort, - DebugFlags ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Set the local address - // - Status = pSocket->pApi->pfnLocalAddrSet ( pPort, pSockAddr, bBindTest ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Test the address/port configuration - // - if ( bBindTest ) { - Status = EslSocketBindTest ( pPort, pSocket->pApi->BindTestErrno ); - if ( EFI_ERROR ( Status )) { - break; - } - } - - // - // Initialize the receive structures - // - pBuffer = (UINT8 *)&pPort[ 1 ]; - pBuffer = &pBuffer[ ESL_STRUCTURE_ALIGNMENT_BYTES ]; - pBuffer = (UINT8 *)( ESL_STRUCTURE_ALIGNMENT_MASK & (UINTN)pBuffer ); - pIo = (ESL_IO_MGMT *)pBuffer; - if (( 0 != pSocketBinding->RxIo ) - && ( NULL != pSocket->pApi->pfnRxComplete )) { - Status = EslSocketIoInit ( pPort, - &pIo, - pSocketBinding->RxIo, - &pPort->pRxFree, - DebugFlags | DEBUG_POOL, - "receive", - pSocket->pApi->pfnRxComplete ); - if ( EFI_ERROR ( Status )) { - break; - } - } - - // - // Initialize the urgent transmit structures - // - if (( 0 != pSocketBinding->TxIoUrgent ) - && ( NULL != pSocket->pApi->pfnTxOobComplete )) { - Status = EslSocketIoInit ( pPort, - &pIo, - pSocketBinding->TxIoUrgent, - &pPort->pTxOobFree, - DebugFlags | DEBUG_POOL, - "urgent transmit", - pSocket->pApi->pfnTxOobComplete ); - if ( EFI_ERROR ( Status )) { - break; - } - } - - // - // Initialize the normal transmit structures - // - if (( 0 != pSocketBinding->TxIoNormal ) - && ( NULL != pSocket->pApi->pfnTxComplete )) { - Status = EslSocketIoInit ( pPort, - &pIo, - pSocketBinding->TxIoNormal, - &pPort->pTxFree, - DebugFlags | DEBUG_POOL, - "normal transmit", - pSocket->pApi->pfnTxComplete ); - if ( EFI_ERROR ( Status )) { - break; - } - } - - // - // Add this port to the socket - // - pPort->pLinkSocket = pSocket->pPortList; - pSocket->pPortList = pPort; - DEBUG (( DebugFlags, - "0x%08x: Socket adding port: 0x%08x\r\n", - pSocket, - pPort )); - - // - // Add this port to the service - // - pPort->pLinkService = pService->pPortList; - pService->pPortList = pPort; - - // - // Return the port - // - *ppPort = pPort; - break; - } - - // - // Clean up after the error if necessary - // - if ( EFI_ERROR ( Status )) { - if ( NULL != pPort ) { - // - // Close the port - // - EslSocketPortClose ( pPort ); - } - else { - // - // Close the port if necessary - // - pServiceBinding = pService->pServiceBinding; - TempStatus = pServiceBinding->DestroyChild ( pServiceBinding, - ChildHandle ); - if ( !EFI_ERROR ( TempStatus )) { - DEBUG (( DEBUG_BIND | DEBUG_POOL, - "0x%08x: %s port handle destroyed\r\n", - ChildHandle, - pSocketBinding->pName )); - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_BIND | DEBUG_POOL, - "ERROR - Failed to destroy the %s port handle 0x%08x, Status: %r\r\n", - pSocketBinding->pName, - ChildHandle, - TempStatus )); - ASSERT ( EFI_SUCCESS == TempStatus ); - } - } - } - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Close a port. - - This routine releases the resources allocated by ::EslSocketPortAllocate. - This routine calls ESL_PROTOCOL_API::pfnPortClose to release the network - specific resources. - - This routine is called by: - - See the \ref PortCloseStateMachine section. - - @param[in] pPort Address of an ::ESL_PORT structure. - - @retval EFI_SUCCESS The port is closed - @retval other Port close error -**/ -EFI_STATUS -EslSocketPortClose ( - IN ESL_PORT * pPort - ) -{ - UINTN DebugFlags; - ESL_LAYER * pLayer; - ESL_PACKET * pPacket; - ESL_PORT * pPreviousPort; - ESL_SERVICE * pService; - EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding; - CONST ESL_SOCKET_BINDING * pSocketBinding; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Verify the socket layer synchronization - // - VERIFY_TPL ( TPL_SOCKETS ); - - // - // Locate the port in the socket list - // - Status = EFI_SUCCESS; - pLayer = &mEslLayer; - DebugFlags = pPort->DebugFlags; - pSocket = pPort->pSocket; - pPreviousPort = pSocket->pPortList; - if ( pPreviousPort == pPort ) { - // - // Remove this port from the head of the socket list - // - pSocket->pPortList = pPort->pLinkSocket; - } - else { - // - // Locate the port in the middle of the socket list - // - while (( NULL != pPreviousPort ) - && ( pPreviousPort->pLinkSocket != pPort )) { - pPreviousPort = pPreviousPort->pLinkSocket; - } - if ( NULL != pPreviousPort ) { - // - // Remove the port from the middle of the socket list - // - pPreviousPort->pLinkSocket = pPort->pLinkSocket; - } - } - - // - // Locate the port in the service list - // Note that the port may not be in the service list - // if the service has been shutdown. - // - pService = pPort->pService; - if ( NULL != pService ) { - pPreviousPort = pService->pPortList; - if ( pPreviousPort == pPort ) { - // - // Remove this port from the head of the service list - // - pService->pPortList = pPort->pLinkService; - } - else { - // - // Locate the port in the middle of the service list - // - while (( NULL != pPreviousPort ) - && ( pPreviousPort->pLinkService != pPort )) { - pPreviousPort = pPreviousPort->pLinkService; - } - if ( NULL != pPreviousPort ) { - // - // Remove the port from the middle of the service list - // - pPreviousPort->pLinkService = pPort->pLinkService; - } - } - } - - // - // Empty the urgent receive queue - // - while ( NULL != pSocket->pRxOobPacketListHead ) { - pPacket = pSocket->pRxOobPacketListHead; - pSocket->pRxOobPacketListHead = pPacket->pNext; - pSocket->pApi->pfnPacketFree ( pPacket, &pSocket->RxOobBytes ); - EslSocketPacketFree ( pPacket, DEBUG_RX ); - } - pSocket->pRxOobPacketListTail = NULL; - ASSERT ( 0 == pSocket->RxOobBytes ); - - // - // Empty the receive queue - // - while ( NULL != pSocket->pRxPacketListHead ) { - pPacket = pSocket->pRxPacketListHead; - pSocket->pRxPacketListHead = pPacket->pNext; - pSocket->pApi->pfnPacketFree ( pPacket, &pSocket->RxBytes ); - EslSocketPacketFree ( pPacket, DEBUG_RX ); - } - pSocket->pRxPacketListTail = NULL; - ASSERT ( 0 == pSocket->RxBytes ); - - // - // Empty the receive free queue - // - while ( NULL != pSocket->pRxFree ) { - pPacket = pSocket->pRxFree; - pSocket->pRxFree = pPacket->pNext; - EslSocketPacketFree ( pPacket, DEBUG_RX ); - } - - // - // Release the network specific resources - // - if ( NULL != pSocket->pApi->pfnPortClose ) { - Status = pSocket->pApi->pfnPortClose ( pPort ); - } - - // - // Done with the normal transmit events - // - Status = EslSocketIoFree ( pPort, - &pPort->pTxFree, - DebugFlags | DEBUG_POOL, - "normal transmit" ); - - // - // Done with the urgent transmit events - // - Status = EslSocketIoFree ( pPort, - &pPort->pTxOobFree, - DebugFlags | DEBUG_POOL, - "urgent transmit" ); - - // - // Done with the receive events - // - Status = EslSocketIoFree ( pPort, - &pPort->pRxFree, - DebugFlags | DEBUG_POOL, - "receive" ); - - // - // Done with the lower layer network protocol - // - pSocketBinding = pPort->pSocketBinding; - if ( NULL != pPort->pProtocol.v ) { - Status = gBS->CloseProtocol ( pPort->Handle, - pSocketBinding->pNetworkProtocolGuid, - pLayer->ImageHandle, - NULL ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DebugFlags, - "0x%08x: Network protocol GUID closed on controller 0x%08x\r\n", - pPort->pProtocol.v, - pPort->Handle )); - } - else { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to close network protocol GUID on controller 0x%08x, Status: %r\r\n", - pPort->Handle, - Status )); - ASSERT ( EFI_SUCCESS == Status ); - } - } - - // - // Done with the network port - // - pServiceBinding = pPort->pServiceBinding; - if ( NULL != pPort->Handle ) { - Status = pServiceBinding->DestroyChild ( pServiceBinding, - pPort->Handle ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DebugFlags | DEBUG_POOL, - "0x%08x: %s port handle destroyed\r\n", - pPort->Handle, - pSocketBinding->pName )); - } - else { - DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL, - "ERROR - Failed to destroy the %s port handle, Status: %r\r\n", - pSocketBinding->pName, - Status )); - ASSERT ( EFI_SUCCESS == Status ); - } - } - - // - // Release the port structure - // - Status = gBS->FreePool ( pPort ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DebugFlags | DEBUG_POOL, - "0x%08x: Free pPort, %d bytes\r\n", - pPort, - sizeof ( *pPort ))); - } - else { - DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL, - "ERROR - Failed to free pPort: 0x%08x, Status: %r\r\n", - pPort, - Status )); - ASSERT ( EFI_SUCCESS == Status ); - } - - // - // Mark the socket as closed if necessary - // - if ( NULL == pSocket->pPortList ) { - pSocket->State = SOCKET_STATE_CLOSED; - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Socket State: SOCKET_STATE_CLOSED\r\n", - pSocket )); - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Port close state 3. - - This routine attempts to complete the port close operation. - - This routine is called by the TCP layer upon completion of - the close operation and by ::EslSocketPortCloseTxDone. - See the \ref PortCloseStateMachine section. - - @param[in] Event The close completion event - @param[in] pPort Address of an ::ESL_PORT structure. -**/ -VOID -EslSocketPortCloseComplete ( - IN EFI_EVENT Event, - IN ESL_PORT * pPort - ) -{ - ESL_IO_MGMT * pIo; - EFI_STATUS Status; - - DBG_ENTER ( ); - VERIFY_AT_TPL ( TPL_SOCKETS ); - - // Update the port state - pPort->State = PORT_STATE_CLOSE_DONE; - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Port Close State: PORT_STATE_CLOSE_DONE\r\n", - pPort )); - - // Shutdown the receive operation on the port - if ( NULL != pPort->pfnRxCancel ) { - pIo = pPort->pRxActive; - while ( NULL != pIo ) { - EslSocketRxCancel ( pPort, pIo ); - pIo = pIo->pNext; - } - } - - // Determine if the receive operation is pending - Status = EslSocketPortCloseRxDone ( pPort ); - DBG_EXIT_STATUS ( Status ); - --Status; -} - - -/** Port close state 4. - - This routine determines the state of the receive operations and - continues the close operation after the pending receive operations - are cancelled. - - This routine is called by - - to determine the state of the receive operations. - See the \ref PortCloseStateMachine section. - - @param[in] pPort Address of an ::ESL_PORT structure. - - @retval EFI_SUCCESS The port is closed - @retval EFI_NOT_READY The port is still closing - @retval EFI_ALREADY_STARTED Error, the port is in the wrong state, - most likely the routine was called already. -**/ -EFI_STATUS -EslSocketPortCloseRxDone ( - IN ESL_PORT * pPort - ) -{ - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Verify the socket layer synchronization - // - VERIFY_TPL ( TPL_SOCKETS ); - - // - // Verify that the port is closing - // - Status = EFI_ALREADY_STARTED; - if ( PORT_STATE_CLOSE_DONE == pPort->State ) { - // - // Determine if the receive operation is pending - // - Status = EFI_NOT_READY; - if ( NULL == pPort->pRxActive ) { - // - // The receive operation is complete - // Update the port state - // - pPort->State = PORT_STATE_CLOSE_RX_DONE; - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Port Close State: PORT_STATE_CLOSE_RX_DONE\r\n", - pPort )); - - // - // Complete the port close operation - // - Status = EslSocketPortClose ( pPort ); - } - else { - DEBUG_CODE_BEGIN (); - { - ESL_IO_MGMT * pIo; - // - // Display the outstanding receive operations - // - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Port Close: Receive still pending!\r\n", - pPort )); - pIo = pPort->pRxActive; - while ( NULL != pIo ) { - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Packet pending on network adapter\r\n", - pIo->pPacket )); - pIo = pIo->pNext; - } - } - DEBUG_CODE_END ( ); - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Start the close operation on a port, state 1. - - This routine marks the port as closed and initiates the \ref - PortCloseStateMachine. The first step is to allow the \ref - TransmitEngine to run down. - - This routine is called by ::EslSocketCloseStart to initiate the socket - network specific close operation on the socket. - - @param[in] pPort Address of an ::ESL_PORT structure. - @param[in] bCloseNow Set TRUE to abort active transfers - @param[in] DebugFlags Flags for debug messages - - @retval EFI_SUCCESS The port is closed, not normally returned - @retval EFI_NOT_READY The port has started the closing process - @retval EFI_ALREADY_STARTED Error, the port is in the wrong state, - most likely the routine was called already. -**/ -EFI_STATUS -EslSocketPortCloseStart ( - IN ESL_PORT * pPort, - IN BOOLEAN bCloseNow, - IN UINTN DebugFlags - ) -{ - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Verify the socket layer synchronization - // - VERIFY_TPL ( TPL_SOCKETS ); - - // - // Mark the port as closing - // - Status = EFI_ALREADY_STARTED; - pSocket = pPort->pSocket; - pSocket->errno = EALREADY; - if ( PORT_STATE_CLOSE_STARTED > pPort->State ) { - - // - // Update the port state - // - pPort->State = PORT_STATE_CLOSE_STARTED; - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Port Close State: PORT_STATE_CLOSE_STARTED\r\n", - pPort )); - pPort->bCloseNow = bCloseNow; - pPort->DebugFlags = DebugFlags; - - // - // Determine if transmits are complete - // - Status = EslSocketPortCloseTxDone ( pPort ); - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Port close state 2. - - This routine determines the state of the transmit engine and - continue the close operation after the transmission is complete. - The next step is to stop the \ref ReceiveEngine. - See the \ref PortCloseStateMachine section. - - This routine is called by ::EslSocketPortCloseStart to determine - if the transmission is complete. - - @param[in] pPort Address of an ::ESL_PORT structure. - - @retval EFI_SUCCESS The port is closed, not normally returned - @retval EFI_NOT_READY The port is still closing - @retval EFI_ALREADY_STARTED Error, the port is in the wrong state, - most likely the routine was called already. - -**/ -EFI_STATUS -EslSocketPortCloseTxDone ( - IN ESL_PORT * pPort - ) -{ - ESL_IO_MGMT * pIo; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Verify the socket layer synchronization - // - VERIFY_TPL ( TPL_SOCKETS ); - - // - // All transmissions are complete or must be stopped - // Mark the port as TX complete - // - Status = EFI_ALREADY_STARTED; - if ( PORT_STATE_CLOSE_STARTED == pPort->State ) { - // - // Verify that the transmissions are complete - // - pSocket = pPort->pSocket; - if ( pPort->bCloseNow - || ( EFI_SUCCESS != pSocket->TxError ) - || (( NULL == pPort->pTxActive ) - && ( NULL == pPort->pTxOobActive ))) { - // - // Update the port state - // - pPort->State = PORT_STATE_CLOSE_TX_DONE; - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Port Close State: PORT_STATE_CLOSE_TX_DONE\r\n", - pPort )); - - // - // Close the port - // Skip the close operation if the port is not configured - // - Status = EFI_SUCCESS; - pSocket = pPort->pSocket; - if (( pPort->bConfigured ) - && ( NULL != pSocket->pApi->pfnPortCloseOp )) { - // - // Start the close operation - // - Status = pSocket->pApi->pfnPortCloseOp ( pPort ); - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Port Close: Close operation still pending!\r\n", - pPort )); - ASSERT ( EFI_SUCCESS == Status ); - } - else { - // - // The receive operation is complete - // Update the port state - // - EslSocketPortCloseComplete ( NULL, pPort ); - } - } - else { - // - // Transmissions are still active, exit - // - Status = EFI_NOT_READY; - pSocket->errno = EAGAIN; - DEBUG_CODE_BEGIN ( ); - { - ESL_PACKET * pPacket; - - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Port Close: Transmits are still pending!\r\n", - pPort )); - - // - // Display the pending urgent transmit packets - // - pPacket = pSocket->pTxOobPacketListHead; - while ( NULL != pPacket ) { - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Packet pending on urgent TX list, %d bytes\r\n", - pPacket, - pPacket->PacketSize )); - pPacket = pPacket->pNext; - } - - pIo = pPort->pTxOobActive; - while ( NULL != pIo ) { - pPacket = pIo->pPacket; - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Packet active %d bytes, pIo: 0x%08x\r\n", - pPacket, - pPacket->PacketSize, - pIo )); - pIo = pIo->pNext; - } - - // - // Display the pending normal transmit packets - // - pPacket = pSocket->pTxPacketListHead; - while ( NULL != pPacket ) { - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Packet pending on normal TX list, %d bytes\r\n", - pPacket, - pPacket->PacketSize )); - pPacket = pPacket->pNext; - } - - pIo = pPort->pTxActive; - while ( NULL != pIo ) { - pPacket = pIo->pPacket; - DEBUG (( DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Packet active %d bytes, pIo: 0x%08x\r\n", - pPacket, - pPacket->PacketSize, - pIo )); - pIo = pIo->pNext; - } - } - DEBUG_CODE_END (); - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Receive data from a network connection. - - This routine calls the network specific routine to remove the - next portion of data from the receive queue and return it to the - caller. - - The ::recvfrom routine calls this routine to determine if any data - is received from the remote system. Note that the other routines - ::recv and ::read are layered on top of ::recvfrom. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[in] Flags Message control flags - @param[in] BufferLength Length of the the buffer - @param[in] pBuffer Address of a buffer to receive the data. - @param[in] pDataLength Number of received data bytes in the buffer. - @param[out] pAddress Network address to receive the remote system address - @param[in,out] pAddressLength Length of the remote network address structure - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS - Socket data successfully received -**/ -EFI_STATUS -EslSocketReceive ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN INT32 Flags, - IN size_t BufferLength, - IN UINT8 * pBuffer, - OUT size_t * pDataLength, - OUT struct sockaddr * pAddress, - IN OUT socklen_t * pAddressLength, - IN int * pErrno - ) -{ - union { - struct sockaddr_in v4; - struct sockaddr_in6 v6; - } Addr; - socklen_t AddressLength; - BOOLEAN bConsumePacket; - BOOLEAN bUrgentQueue; - size_t DataLength; - ESL_PACKET * pNextPacket; - ESL_PACKET * pPacket; - ESL_PORT * pPort; - ESL_PACKET ** ppQueueHead; - ESL_PACKET ** ppQueueTail; - struct sockaddr * pRemoteAddress; - size_t * pRxDataBytes; - ESL_SOCKET * pSocket; - size_t SkipBytes; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Validate the socket - // - pSocket = NULL; - if ( NULL != pSocketProtocol ) { - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - - // - // Validate the return address parameters - // - if (( NULL == pAddress ) || ( NULL != pAddressLength )) { - // - // Return the transmit error if necessary - // - if ( EFI_SUCCESS != pSocket->TxError ) { - pSocket->errno = EIO; - Status = pSocket->TxError; - pSocket->TxError = EFI_SUCCESS; - } - else { - // - // Verify the socket state - // - Status = EslSocketIsConfigured ( pSocket ); - if ( !EFI_ERROR ( Status )) { - // - // Validate the buffer length - // - if (( NULL == pDataLength ) - || ( NULL == pBuffer )) { - if ( NULL == pDataLength ) { - DEBUG (( DEBUG_RX, - "ERROR - pDataLength is NULL!\r\n" )); - } - else { - DEBUG (( DEBUG_RX, - "ERROR - pBuffer is NULL!\r\n" )); - } - Status = EFI_INVALID_PARAMETER; - pSocket->errno = EFAULT; - } - else { - // - // Verify the API - // - if ( NULL == pSocket->pApi->pfnReceive ) { - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTSUP; - } - else { - // - // Zero the receive address if being returned - // - pRemoteAddress = NULL; - if ( NULL != pAddress ) { - pRemoteAddress = (struct sockaddr *)&Addr; - ZeroMem ( pRemoteAddress, sizeof ( Addr )); - pRemoteAddress->sa_family = pSocket->pApi->AddressFamily; - pRemoteAddress->sa_len = (UINT8)pSocket->pApi->AddressLength; - } - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Assume failure - // - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTCONN; - - // - // Verify that the socket is connected - // - if ( SOCKET_STATE_CONNECTED == pSocket->State ) { - // - // Poll the network to increase performance - // - EslSocketRxPoll ( pSocket ); - - // - // Locate the port - // - pPort = pSocket->pPortList; - if ( NULL != pPort ) { - // - // Determine the queue head - // - bUrgentQueue = (BOOLEAN)( 0 != ( Flags & MSG_OOB )); - if ( bUrgentQueue ) { - ppQueueHead = &pSocket->pRxOobPacketListHead; - ppQueueTail = &pSocket->pRxOobPacketListTail; - pRxDataBytes = &pSocket->RxOobBytes; - } - else { - ppQueueHead = &pSocket->pRxPacketListHead; - ppQueueTail = &pSocket->pRxPacketListTail; - pRxDataBytes = &pSocket->RxBytes; - } - - // - // Determine if there is any data on the queue - // - *pDataLength = 0; - pPacket = *ppQueueHead; - if ( NULL != pPacket ) { - // - // Copy the received data - // - do { - // - // Attempt to receive a packet - // - SkipBytes = 0; - bConsumePacket = (BOOLEAN)( 0 == ( Flags & MSG_PEEK )); - pBuffer = pSocket->pApi->pfnReceive ( pPort, - pPacket, - &bConsumePacket, - BufferLength, - pBuffer, - &DataLength, - (struct sockaddr *)&Addr, - &SkipBytes ); - *pDataLength += DataLength; - BufferLength -= DataLength; - - // - // Determine if the data is being read - // - pNextPacket = pPacket->pNext; - if ( bConsumePacket ) { - // - // All done with this packet - // Account for any discarded data - // - pSocket->pApi->pfnPacketFree ( pPacket, pRxDataBytes ); - if ( 0 != SkipBytes ) { - DEBUG (( DEBUG_RX, - "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n", - pPort, - SkipBytes )); - } - - // - // Remove this packet from the queue - // - *ppQueueHead = pPacket->pNext; - if ( NULL == *ppQueueHead ) { - *ppQueueTail = NULL; - } - - // - // Move the packet to the free queue - // - pPacket->pNext = pSocket->pRxFree; - pSocket->pRxFree = pPacket; - DEBUG (( DEBUG_RX, - "0x%08x: Port freeing packet 0x%08x\r\n", - pPort, - pPacket )); - - // - // Restart the receive operation if necessary - // - if (( NULL != pPort->pRxFree ) - && ( MAX_RX_DATA > pSocket->RxBytes )) { - EslSocketRxStart ( pPort ); - } - } - - // - // Get the next packet - // - pPacket = pNextPacket; - } while (( SOCK_STREAM == pSocket->Type ) - && ( NULL != pPacket ) - && ( 0 < BufferLength )); - - // - // Successful operation - // - Status = EFI_SUCCESS; - pSocket->errno = 0; - } - else { - // - // The queue is empty - // Determine if it is time to return the receive error - // - if ( EFI_ERROR ( pSocket->RxError ) - && ( NULL == pSocket->pRxPacketListHead ) - && ( NULL == pSocket->pRxOobPacketListHead )) { - Status = pSocket->RxError; - pSocket->RxError = EFI_SUCCESS; - switch ( Status ) { - default: - pSocket->errno = EIO; - break; - - case EFI_CONNECTION_FIN: - // - // Continue to return zero bytes received when the - // peer has successfully closed the connection - // - pSocket->RxError = EFI_CONNECTION_FIN; - *pDataLength = 0; - pSocket->errno = 0; - Status = EFI_SUCCESS; - break; - - case EFI_CONNECTION_REFUSED: - pSocket->errno = ECONNREFUSED; - break; - - case EFI_CONNECTION_RESET: - pSocket->errno = ECONNRESET; - break; - - case EFI_HOST_UNREACHABLE: - pSocket->errno = EHOSTUNREACH; - break; - - case EFI_NETWORK_UNREACHABLE: - pSocket->errno = ENETUNREACH; - break; - - case EFI_PORT_UNREACHABLE: - pSocket->errno = EPROTONOSUPPORT; - break; - - case EFI_PROTOCOL_UNREACHABLE: - pSocket->errno = ENOPROTOOPT; - break; - } - } - else { - Status = EFI_NOT_READY; - pSocket->errno = EAGAIN; - } - } - } - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - - if (( !EFI_ERROR ( Status )) && ( NULL != pAddress )) { - // - // Return the remote address if requested, truncate if necessary - // - AddressLength = pRemoteAddress->sa_len; - if ( AddressLength > *pAddressLength ) { - AddressLength = *pAddressLength; - } - DEBUG (( DEBUG_RX, - "Returning the remote address, 0x%016x bytes --> 0x%16x\r\n", *pAddressLength, pAddress )); - ZeroMem ( pAddress, *pAddressLength ); - CopyMem ( pAddress, &Addr, AddressLength ); - - // - // Update the address length - // - *pAddressLength = pRemoteAddress->sa_len; - } - } - } - } - } - - - } - else { - // - // Bad return address pointer and length - // - Status = EFI_INVALID_PARAMETER; - pSocket->errno = EINVAL; - } - } - - // - // Return the operation status - // - if ( NULL != pErrno ) { - if ( NULL != pSocket ) { - *pErrno = pSocket->errno; - } - else { - Status = EFI_INVALID_PARAMETER; - *pErrno = ENOTSOCK; - } - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Cancel the receive operations. - - This routine cancels a pending receive operation. - See the \ref ReceiveEngine section. - - This routine is called by ::EslSocketShutdown when the socket - layer is being shutdown. - - @param[in] pPort Address of an ::ESL_PORT structure - @param[in] pIo Address of an ::ESL_IO_MGMT structure -**/ -VOID -EslSocketRxCancel ( - IN ESL_PORT * pPort, - IN ESL_IO_MGMT * pIo - ) -{ - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Cancel the outstanding receive - // - Status = pPort->pfnRxCancel ( pPort->pProtocol.v, - &pIo->Token ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Packet receive aborted on port: 0x%08x\r\n", - pIo->pPacket, - pPort )); - } - else { - DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Packet receive pending on Port 0x%08x, Status: %r\r\n", - pIo->pPacket, - pPort, - Status )); - } - DBG_EXIT ( ); -} - - -/** Process the receive completion. - - This routine queues the data in FIFO order in either the urgent - or normal data queues depending upon the type of data received. - See the \ref ReceiveEngine section. - - This routine is called when some data is received by: - - - @param[in] pIo Address of an ::ESL_IO_MGMT structure - @param[in] Status Receive status - @param[in] LengthInBytes Length of the receive data - @param[in] bUrgent TRUE if urgent data is received and FALSE - for normal data. -**/ -VOID -EslSocketRxComplete ( - IN ESL_IO_MGMT * pIo, - IN EFI_STATUS Status, - IN UINTN LengthInBytes, - IN BOOLEAN bUrgent - ) -{ - BOOLEAN bUrgentQueue; - ESL_IO_MGMT * pIoNext; - ESL_PACKET * pPacket; - ESL_PORT * pPort; - ESL_PACKET * pPrevious; - ESL_PACKET ** ppQueueHead; - ESL_PACKET ** ppQueueTail; - size_t * pRxBytes; - ESL_SOCKET * pSocket; - - DBG_ENTER ( ); - VERIFY_AT_TPL ( TPL_SOCKETS ); - - // - // Locate the active receive packet - // - pPacket = pIo->pPacket; - pPort = pIo->pPort; - pSocket = pPort->pSocket; - - // - // pPort->pRxActive - // | - // V - // +-------------+ +-------------+ +-------------+ - // Active | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL - // +-------------+ +-------------+ +-------------+ - // - // +-------------+ +-------------+ +-------------+ - // Free | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL - // +-------------+ +-------------+ +-------------+ - // ^ - // | - // pPort->pRxFree - // - // - // Remove the IO structure from the active list - // The following code searches for the entry in the list and does not - // assume that the receive operations complete in the order they were - // issued to the UEFI network layer. - // - pIoNext = pPort->pRxActive; - while (( NULL != pIoNext ) && ( pIoNext != pIo ) && ( pIoNext->pNext != pIo )) - { - pIoNext = pIoNext->pNext; - } - ASSERT ( NULL != pIoNext ); - if ( pIoNext == pIo ) { - pPort->pRxActive = pIo->pNext; // Beginning of list - } - else { - pIoNext->pNext = pIo->pNext; // Middle of list - } - - // - // Free the IO structure - // - pIo->pNext = pPort->pRxFree; - pPort->pRxFree = pIo; - - // - // pRxOobPacketListHead pRxOobPacketListTail - // | | - // V V - // +------------+ +------------+ +------------+ - // Urgent Data | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL - // +------------+ +------------+ +------------+ - // - // +------------+ +------------+ +------------+ - // Normal Data | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL - // +------------+ +------------+ +------------+ - // ^ ^ - // | | - // pRxPacketListHead pRxPacketListTail - // - // - // Determine the queue to use - // - bUrgentQueue = (BOOLEAN)( bUrgent - && pSocket->pApi->bOobSupported - && ( !pSocket->bOobInLine )); - if ( bUrgentQueue ) { - ppQueueHead = &pSocket->pRxOobPacketListHead; - ppQueueTail = &pSocket->pRxOobPacketListTail; - pRxBytes = &pSocket->RxOobBytes; - } - else { - ppQueueHead = &pSocket->pRxPacketListHead; - ppQueueTail = &pSocket->pRxPacketListTail; - pRxBytes = &pSocket->RxBytes; - } - - // - // Determine if this receive was successful - // - if (( !EFI_ERROR ( Status )) - && ( PORT_STATE_CLOSE_STARTED > pPort->State ) - && ( !pSocket->bRxDisable )) { - // - // Account for the received data - // - *pRxBytes += LengthInBytes; - - // - // Log the received data - // - DEBUG (( DEBUG_RX | DEBUG_INFO, - "0x%08x: Packet queued on %s queue of port 0x%08x with 0x%08x bytes of %s data\r\n", - pPacket, - bUrgentQueue ? L"urgent" : L"normal", - pPort, - LengthInBytes, - bUrgent ? L"urgent" : L"normal" )); - - // - // Add the packet to the list tail. - // - pPacket->pNext = NULL; - pPrevious = *ppQueueTail; - if ( NULL == pPrevious ) { - *ppQueueHead = pPacket; - } - else { - pPrevious->pNext = pPacket; - } - *ppQueueTail = pPacket; - - // - // Attempt to restart this receive operation - // - if ( pSocket->MaxRxBuf > pSocket->RxBytes ) { - EslSocketRxStart ( pPort ); - } - else { - DEBUG (( DEBUG_RX, - "0x%08x: Port RX suspended, 0x%08x bytes queued\r\n", - pPort, - pSocket->RxBytes )); - } - } - else { - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_RX | DEBUG_INFO, - "ERROR - Receive error on port 0x%08x, packet 0x%08x, Status:%r\r\n", - pPort, - pPacket, - Status )); - } - - // - // Account for the receive bytes and release the driver's buffer - // - if ( !EFI_ERROR ( Status )) { - *pRxBytes += LengthInBytes; - pSocket->pApi->pfnPacketFree ( pPacket, pRxBytes ); - } - - // - // Receive error, free the packet save the error - // - EslSocketPacketFree ( pPacket, DEBUG_RX ); - if ( !EFI_ERROR ( pSocket->RxError )) { - pSocket->RxError = Status; - } - - // - // Update the port state - // - if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) { - if ( PORT_STATE_CLOSE_DONE == pPort->State ) { - EslSocketPortCloseRxDone ( pPort ); - } - } - else { - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_RX | DEBUG_INFO, - "0x%08x: Port state: PORT_STATE_RX_ERROR, Status: %r\r\n", - pPort, - Status )); - pPort->State = PORT_STATE_RX_ERROR; - } - } - } - - DBG_EXIT ( ); -} - - -/** Poll a socket for pending receive activity. - - This routine is called at elivated TPL and extends the idle - loop which polls a socket down into the LAN driver layer to - determine if there is any receive activity. - - The ::EslSocketPoll, ::EslSocketReceive and ::EslSocketTransmit - routines call this routine when there is nothing to do. - - @param[in] pSocket Address of an ::EFI_SOCKET structure. - **/ -VOID -EslSocketRxPoll ( - IN ESL_SOCKET * pSocket - ) -{ - ESL_PORT * pPort; - - DEBUG (( DEBUG_POLL, "Entering EslSocketRxPoll\r\n" )); - - // - // Increase the network performance by extending the - // polling (idle) loop down into the LAN driver - // - pPort = pSocket->pPortList; - while ( NULL != pPort ) { - // - // Poll the LAN adapter - // - pPort->pfnRxPoll ( pPort->pProtocol.v ); - - // - // Locate the next LAN adapter - // - pPort = pPort->pLinkSocket; - } - - DEBUG (( DEBUG_POLL, "Exiting EslSocketRxPoll\r\n" )); -} - - -/** Start a receive operation. - - This routine posts a receive buffer to the network adapter. - See the \ref ReceiveEngine section. - - This support routine is called by: - - - @param[in] pPort Address of an ::ESL_PORT structure. -**/ -VOID -EslSocketRxStart ( - IN ESL_PORT * pPort - ) -{ - UINT8 * pBuffer; - ESL_IO_MGMT * pIo; - ESL_PACKET * pPacket; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Determine if a receive is already pending - // - Status = EFI_SUCCESS; - pPacket = NULL; - pSocket = pPort->pSocket; - if ( !EFI_ERROR ( pPort->pSocket->RxError )) { - if (( NULL != pPort->pRxFree ) - && ( !pSocket->bRxDisable ) - && ( PORT_STATE_CLOSE_STARTED > pPort->State )) { - // - // Start all of the pending receive operations - // - while ( NULL != pPort->pRxFree ) { - // - // Determine if there are any free packets - // - pPacket = pSocket->pRxFree; - if ( NULL != pPacket ) { - // - // Remove this packet from the free list - // - pSocket->pRxFree = pPacket->pNext; - DEBUG (( DEBUG_RX, - "0x%08x: Port removed packet 0x%08x from free list\r\n", - pPort, - pPacket )); - } - else { - // - // Allocate a packet structure - // - Status = EslSocketPacketAllocate ( &pPacket, - pSocket->pApi->RxPacketBytes, - pSocket->pApi->RxZeroBytes, - DEBUG_RX ); - if ( EFI_ERROR ( Status )) { - pPacket = NULL; - DEBUG (( DEBUG_ERROR | DEBUG_RX, - "0x%08x: Port failed to allocate RX packet, Status: %r\r\n", - pPort, - Status )); - break; - } - } - - // - // Connect the IO and packet structures - // - pIo = pPort->pRxFree; - pIo->pPacket = pPacket; - - // - // Eliminate the need for IP4 and UDP4 specific routines by - // clearing the RX data pointer here. - // - // No driver buffer for this packet - // - // +--------------------+ - // | ESL_IO_MGMT | - // | | - // | +---------------+ - // | | Token | - // | | RxData --> NULL - // +----+---------------+ - // - pBuffer = (UINT8 *)pIo; - pBuffer = &pBuffer[ pSocket->pApi->RxBufferOffset ]; - *(VOID **)pBuffer = NULL; - - // - // Network specific receive packet initialization - // - if ( NULL != pSocket->pApi->pfnRxStart ) { - pSocket->pApi->pfnRxStart ( pPort, pIo ); - } - - // - // Start the receive on the packet - // - Status = pPort->pfnRxStart ( pPort->pProtocol.v, &pIo->Token ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_RX | DEBUG_INFO, - "0x%08x: Packet receive pending on port 0x%08x\r\n", - pPacket, - pPort )); - // - // Allocate the receive control structure - // - pPort->pRxFree = pIo->pNext; - - // - // Mark this receive as pending - // - pIo->pNext = pPort->pRxActive; - pPort->pRxActive = pIo; - - } - else { - DEBUG (( DEBUG_RX | DEBUG_INFO, - "ERROR - Failed to post a receive on port 0x%08x, Status: %r\r\n", - pPort, - Status )); - if ( !EFI_ERROR ( pSocket->RxError )) { - // - // Save the error status - // - pSocket->RxError = Status; - } - - // - // Free the packet - // - pIo->pPacket = NULL; - pPacket->pNext = pSocket->pRxFree; - pSocket->pRxFree = pPacket; - break; - } - } - } - else { - if ( NULL == pPort->pRxFree ) { - DEBUG (( DEBUG_RX | DEBUG_INFO, - "0x%08x: Port, no available ESL_IO_MGMT structures\r\n", - pPort)); - } - if ( pSocket->bRxDisable ) { - DEBUG (( DEBUG_RX | DEBUG_INFO, - "0x%08x: Port, receive disabled!\r\n", - pPort )); - } - if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) { - DEBUG (( DEBUG_RX | DEBUG_INFO, - "0x%08x: Port, is closing!\r\n", - pPort )); - } - } - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_RX, - "ERROR - Previous receive error, Status: %r\r\n", - pPort->pSocket->RxError )); - } - - DBG_EXIT ( ); -} - - -/** Shutdown the socket receive and transmit operations. - - This routine sets a flag to stop future transmissions and calls - the network specific layer to cancel the pending receive operation. - - The ::shutdown routine calls this routine to stop receive and transmit - operations on the socket. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[in] How Which operations to stop - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS - Socket operations successfully shutdown -**/ -EFI_STATUS -EslSocketShutdown ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN int How, - IN int * pErrno - ) -{ - ESL_IO_MGMT * pIo; - ESL_PORT * pPort; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Validate the socket - // - pSocket = NULL; - if ( NULL != pSocketProtocol ) { - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - - // - // Verify that the socket is connected - // - if ( pSocket->bConnected ) { - // - // Validate the How value - // - if (( SHUT_RD <= How ) && ( SHUT_RDWR >= How )) { - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Disable the receiver if requested - // - if (( SHUT_RD == How ) || ( SHUT_RDWR == How )) { - pSocket->bRxDisable = TRUE; - } - - // - // Disable the transmitter if requested - // - if (( SHUT_WR == How ) || ( SHUT_RDWR == How )) { - pSocket->bTxDisable = TRUE; - } - - // - // Cancel the pending receive operations - // - if ( pSocket->bRxDisable ) { - // - // Walk the list of ports - // - pPort = pSocket->pPortList; - while ( NULL != pPort ) { - // - // Walk the list of active receive operations - // - pIo = pPort->pRxActive; - while ( NULL != pIo ) { - EslSocketRxCancel ( pPort, pIo ); - } - - // - // Set the next port - // - pPort = pPort->pLinkSocket; - } - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - else { - // - // Invalid How value - // - pSocket->errno = EINVAL; - Status = EFI_INVALID_PARAMETER; - } - } - else { - // - // The socket is not connected - // - pSocket->errno = ENOTCONN; - Status = EFI_NOT_STARTED; - } - } - - // - // Return the operation status - // - if ( NULL != pErrno ) { - if ( NULL != pSocket ) { - *pErrno = pSocket->errno; - } - else { - Status = EFI_INVALID_PARAMETER; - *pErrno = ENOTSOCK; - } - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Send data using a network connection. - - This routine calls the network specific layer to queue the data - for transmission. Eventually the buffer will reach the head of - the queue and will get transmitted over the network by the - \ref TransmitEngine. For datagram - sockets (SOCK_DGRAM and SOCK_RAW) there is no guarantee that - the data reaches the application running on the remote system. - - The ::sendto routine calls this routine to send data to the remote - system. Note that ::send and ::write are layered on top of ::sendto. - - @param[in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - @param[in] Flags Message control flags - @param[in] BufferLength Length of the the buffer - @param[in] pBuffer Address of a buffer containing the data to send - @param[in] pDataLength Address to receive the number of data bytes sent - @param[in] pAddress Network address of the remote system address - @param[in] AddressLength Length of the remote network address structure - @param[out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS - Socket data successfully queued for transmit -**/ -EFI_STATUS -EslSocketTransmit ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN int Flags, - IN size_t BufferLength, - IN CONST UINT8 * pBuffer, - OUT size_t * pDataLength, - IN const struct sockaddr * pAddress, - IN socklen_t AddressLength, - IN int * pErrno - ) -{ - ESL_SOCKET * pSocket; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Validate the socket - // - pSocket = NULL; - if ( NULL != pSocketProtocol ) { - pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol ); - - // - // Return the transmit error if necessary - // - if ( EFI_SUCCESS != pSocket->TxError ) { - pSocket->errno = EIO; - Status = pSocket->TxError; - pSocket->TxError = EFI_SUCCESS; - } - else { - // - // Verify the socket state - // - Status = EslSocketIsConfigured ( pSocket ); - if ( !EFI_ERROR ( Status )) { - // - // Verify that transmit is still allowed - // - if ( !pSocket->bTxDisable ) { - // - // Validate the buffer length - // - if (( NULL == pDataLength ) - && ( 0 > pDataLength ) - && ( NULL == pBuffer )) { - if ( NULL == pDataLength ) { - DEBUG (( DEBUG_RX, - "ERROR - pDataLength is NULL!\r\n" )); - } - else if ( NULL == pBuffer ) { - DEBUG (( DEBUG_RX, - "ERROR - pBuffer is NULL!\r\n" )); - } - else { - DEBUG (( DEBUG_RX, - "ERROR - Data length < 0!\r\n" )); - } - Status = EFI_INVALID_PARAMETER; - pSocket->errno = EFAULT; - } - else { - // - // Validate the remote network address - // - if (( NULL != pAddress ) - && ( AddressLength < pAddress->sa_len )) { - DEBUG (( DEBUG_TX, - "ERROR - Invalid sin_len field in address\r\n" )); - Status = EFI_INVALID_PARAMETER; - pSocket->errno = EFAULT; - } - else { - // - // Verify the API - // - if ( NULL == pSocket->pApi->pfnTransmit ) { - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTSUP; - } - else { - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Poll the network to increase performance - // - EslSocketRxPoll ( pSocket ); - - // - // Attempt to buffer the packet for transmission - // - Status = pSocket->pApi->pfnTransmit ( pSocket, - Flags, - BufferLength, - pBuffer, - pDataLength, - pAddress, - AddressLength ); - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - } - } - } - else { - // - // The transmitter was shutdown - // - pSocket->errno = EPIPE; - Status = EFI_NOT_STARTED; - } - } - } - } - - // - // Return the operation status - // - if ( NULL != pErrno ) { - if ( NULL != pSocket ) { - *pErrno = pSocket->errno; - } - else { - Status = EFI_INVALID_PARAMETER; - *pErrno = ENOTSOCK; - } - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** Complete the transmit operation. - - This support routine handles the transmit completion processing for - the various network layers. It frees the ::ESL_IO_MGMT structure - and and frees packet resources by calling ::EslSocketPacketFree. - Transmit errors are logged in ESL_SOCKET::TxError. - See the \ref TransmitEngine section. - - This routine is called by: - - - @param[in] pIo Address of an ::ESL_IO_MGMT structure - @param[in] LengthInBytes Length of the data in bytes - @param[in] Status Transmit operation status - @param[in] pQueueType Zero terminated string describing queue type - @param[in] ppQueueHead Transmit queue head address - @param[in] ppQueueTail Transmit queue tail address - @param[in] ppActive Active transmit queue address - @param[in] ppFree Free transmit queue address -**/ -VOID -EslSocketTxComplete ( - IN ESL_IO_MGMT * pIo, - IN UINT32 LengthInBytes, - IN EFI_STATUS Status, - IN CONST CHAR8 * pQueueType, - IN ESL_PACKET ** ppQueueHead, - IN ESL_PACKET ** ppQueueTail, - IN ESL_IO_MGMT ** ppActive, - IN ESL_IO_MGMT ** ppFree - ) -{ - ESL_PACKET * pCurrentPacket; - ESL_IO_MGMT * pIoNext; - ESL_PACKET * pNextPacket; - ESL_PACKET * pPacket; - ESL_PORT * pPort; - ESL_SOCKET * pSocket; - - DBG_ENTER ( ); - VERIFY_AT_TPL ( TPL_SOCKETS ); - - // - // Locate the active transmit packet - // - pPacket = pIo->pPacket; - pPort = pIo->pPort; - pSocket = pPort->pSocket; - - // - // No more packet - // - pIo->pPacket = NULL; - - // - // Remove the IO structure from the active list - // - pIoNext = *ppActive; - while (( NULL != pIoNext ) && ( pIoNext != pIo ) && ( pIoNext->pNext != pIo )) - { - pIoNext = pIoNext->pNext; - } - ASSERT ( NULL != pIoNext ); - if ( pIoNext == pIo ) { - *ppActive = pIo->pNext; // Beginning of list - } - else { - pIoNext->pNext = pIo->pNext; // Middle of list - } - - // - // Free the IO structure - // - pIo->pNext = *ppFree; - *ppFree = pIo; - - // - // Display the results - // - DEBUG (( DEBUG_TX | DEBUG_INFO, - "0x%08x: pIo Released\r\n", - pIo )); - - // - // Save any transmit error - // - if ( EFI_ERROR ( Status )) { - if ( !EFI_ERROR ( pSocket->TxError )) { - pSocket->TxError = Status; - } - DEBUG (( DEBUG_TX | DEBUG_INFO, - "ERROR - Transmit failure for %apacket 0x%08x, Status: %r\r\n", - pQueueType, - pPacket, - Status )); - - // - // Empty the normal transmit list - // - pCurrentPacket = pPacket; - pNextPacket = *ppQueueHead; - while ( NULL != pNextPacket ) { - pPacket = pNextPacket; - pNextPacket = pPacket->pNext; - EslSocketPacketFree ( pPacket, DEBUG_TX ); - } - *ppQueueHead = NULL; - *ppQueueTail = NULL; - pPacket = pCurrentPacket; - } - else { - DEBUG (( DEBUG_TX | DEBUG_INFO, - "0x%08x: %apacket transmitted %d bytes successfully\r\n", - pPacket, - pQueueType, - LengthInBytes )); - - // - // Verify the transmit engine is still running - // - if ( !pPort->bCloseNow ) { - // - // Start the next packet transmission - // - EslSocketTxStart ( pPort, - ppQueueHead, - ppQueueTail, - ppActive, - ppFree ); - } - } - - // - // Release this packet - // - EslSocketPacketFree ( pPacket, DEBUG_TX ); - - // - // Finish the close operation if necessary - // - if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) { - // - // Indicate that the transmit is complete - // - EslSocketPortCloseTxDone ( pPort ); - } - - DBG_EXIT ( ); -} - - -/** Transmit data using a network connection. - - This support routine starts a transmit operation on the - underlying network layer. - - The network specific code calls this routine to start a - transmit operation. See the \ref TransmitEngine section. - - @param[in] pPort Address of an ::ESL_PORT structure - @param[in] ppQueueHead Transmit queue head address - @param[in] ppQueueTail Transmit queue tail address - @param[in] ppActive Active transmit queue address - @param[in] ppFree Free transmit queue address -**/ -VOID -EslSocketTxStart ( - IN ESL_PORT * pPort, - IN ESL_PACKET ** ppQueueHead, - IN ESL_PACKET ** ppQueueTail, - IN ESL_IO_MGMT ** ppActive, - IN ESL_IO_MGMT ** ppFree - ) -{ - UINT8 * pBuffer; - ESL_IO_MGMT * pIo; - ESL_PACKET * pNextPacket; - ESL_PACKET * pPacket; - VOID ** ppTokenData; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Get the packet from the queue head - // - pPacket = *ppQueueHead; - pIo = *ppFree; - if (( NULL != pPacket ) && ( NULL != pIo )) { - pSocket = pPort->pSocket; - // - // *ppQueueHead: pSocket->pRxPacketListHead or pSocket->pRxOobPacketListHead - // | - // V - // +------------+ +------------+ +------------+ - // Data | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL - // +------------+ +------------+ +------------+ - // ^ - // | - // *ppQueueTail: pSocket->pRxPacketListTail or pSocket->pRxOobPacketListTail - // - // - // Remove the packet from the queue - // - pNextPacket = pPacket->pNext; - *ppQueueHead = pNextPacket; - if ( NULL == pNextPacket ) { - *ppQueueTail = NULL; - } - pPacket->pNext = NULL; - - // - // Eliminate the need for IP4 and UDP4 specific routines by - // connecting the token with the TX data control structure here. - // - // +--------------------+ +--------------------+ - // | ESL_IO_MGMT | | ESL_PACKET | - // | | | | - // | +---------------+ +----------------+ | - // | | Token | | Buffer Length | | - // | | TxData --> | Buffer Address | | - // | | | +----------------+---+ - // | | Event | | Data Buffer | - // +----+---------------+ | | - // +--------------------+ - // - // Compute the address of the TxData pointer in the token - // - pBuffer = (UINT8 *)&pIo->Token; - pBuffer = &pBuffer[ pSocket->TxTokenOffset ]; - ppTokenData = (VOID **)pBuffer; - - // - // Compute the address of the TX data control structure in the packet - // - // * EFI_IP4_TRANSMIT_DATA - // * EFI_TCP4_TRANSMIT_DATA - // * EFI_UDP4_TRANSMIT_DATA - // - pBuffer = (UINT8 *)pPacket; - pBuffer = &pBuffer[ pSocket->TxPacketOffset ]; - - // - // Connect the token to the transmit data control structure - // - *ppTokenData = (VOID **)pBuffer; - - // - // Display the results - // - DEBUG (( DEBUG_TX | DEBUG_INFO, - "0x%08x: pIo allocated for pPacket: 0x%08x\r\n", - pIo, - pPacket )); - - // - // Start the transmit operation - // - Status = pPort->pfnTxStart ( pPort->pProtocol.v, - &pIo->Token ); - if ( !EFI_ERROR ( Status )) { - // - // Connect the structures - // - pIo->pPacket = pPacket; - - // - // +-------------+ +-------------+ +-------------+ - // Free | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL - // +-------------+ +-------------+ +-------------+ - // ^ - // | - // *ppFree: pPort->pTxFree or pTxOobFree - // - // - // Remove the IO structure from the queue - // - *ppFree = pIo->pNext; - - // - // *ppActive: pPort->pTxActive or pTxOobActive - // | - // V - // +-------------+ +-------------+ +-------------+ - // Active | ESL_IO_MGMT |-->| ESL_IO_MGMT |-->| ESL_IO_MGMT |--> NULL - // +-------------+ +-------------+ +-------------+ - // - // - // Mark this packet as active - // - pIo->pPacket = pPacket; - pIo->pNext = *ppActive; - *ppActive = pIo; - } - else { - // - // Display the transmit error - // - DEBUG (( DEBUG_TX | DEBUG_INFO, - "0x%08x, 0x%08x: pIo, pPacket transmit failure: %r\r\n", - pIo, - pPacket, - Status )); - if ( EFI_SUCCESS == pSocket->TxError ) { - pSocket->TxError = Status; - } - - // - // Free the IO structure - // - pIo->pNext = *ppFree; - *ppFree = pIo; - - // - // Discard the transmit buffer - // - EslSocketPacketFree ( pPacket, DEBUG_TX ); - } - } - - DBG_EXIT ( ); -} diff --git a/StdLib/EfiSocketLib/Socket.h b/StdLib/EfiSocketLib/Socket.h deleted file mode 100644 index 583be1ffd0..0000000000 --- a/StdLib/EfiSocketLib/Socket.h +++ /dev/null @@ -1,1688 +0,0 @@ -/** @file - Definitions for the Socket layer driver. - - Copyright (c) 2011, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ -#ifndef _SOCKET_H_ -#define _SOCKET_H_ - -#include - -//------------------------------------------------------------------------------ -// Constants -//------------------------------------------------------------------------------ - -#define DEBUG_SOCKET 0x20000000 ///< Display Socket related messages -#define DEBUG_BIND 0x10000000 ///< Display bind related messages -#define DEBUG_LISTEN 0x08000000 ///< Display listen related messages -#define DEBUG_CONNECTION 0x04000000 ///< Display connection list related messages -#define DEBUG_POLL 0x02000000 ///< Display poll messages -#define DEBUG_ACCEPT 0x01000000 ///< Display accept related messages -#define DEBUG_RX 0x00800000 ///< Display receive messages -#define DEBUG_TX 0x00400000 ///< Display transmit messages -#define DEBUG_CLOSE 0x00200000 ///< Display close messages -#define DEBUG_CONNECT 0x00100000 ///< Display connect messages -#define DEBUG_OPTION 0x00080000 ///< Display option messages - -#define MAX_PENDING_CONNECTIONS 1 ///< Maximum connection FIFO depth -#define MAX_RX_DATA 0x01000000 ///< Maximum receive data size -#define MAX_TX_DATA ( MAX_RX_DATA * 2 ) ///< Maximum buffered transmit data in bytes -#define RX_PACKET_DATA 0x00100000 ///< Maximum number of bytes in a RX packet -#define MAX_UDP_RETRANSMIT 16 ///< UDP retransmit attempts to handle address not mapped - -#define ESL_STRUCTURE_ALIGNMENT_BYTES 15 ///< Number of bytes for structure alignment -#define ESL_STRUCTURE_ALIGNMENT_MASK ( ~ESL_STRUCTURE_ALIGNMENT_BYTES ) ///< Mask to align structures - -#define LAYER_SIGNATURE SIGNATURE_32 ('S','k','t','L') ///< ESL_LAYER memory signature -#define SERVICE_SIGNATURE SIGNATURE_32 ('S','k','t','S') ///< ESL_SERVICE memory signature -#define SOCKET_SIGNATURE SIGNATURE_32 ('S','c','k','t') ///< ESL_SOCKET memory signature -#define PORT_SIGNATURE SIGNATURE_32 ('P','o','r','t') ///< ESL_PORT memory signature - - -/** - Socket states -**/ -typedef enum -{ - SOCKET_STATE_NOT_CONFIGURED = 0, ///< socket call was successful - SOCKET_STATE_BOUND, ///< bind call was successful - SOCKET_STATE_LISTENING, ///< listen call was successful - SOCKET_STATE_NO_PORTS, ///< No ports available - SOCKET_STATE_IN_FIFO, ///< Socket on FIFO - SOCKET_STATE_CONNECTING, ///< Connecting to a remote system - SOCKET_STATE_CONNECTED, ///< Accept or connect call was successful - - // - // Close state must be the last in the list - // - SOCKET_STATE_CLOSED ///< Close call was successful -} SOCKET_STATE; - - -/** - Port states -**/ -typedef enum -{ - PORT_STATE_ALLOCATED = 0, ///< Port allocated - PORT_STATE_OPEN, ///< Port opened - PORT_STATE_RX_ERROR, ///< Receive error detected - - // - // Close state must be last in the list! - // - // Using < <= > >= in tests code to detect port close state - // machine has started - // - PORT_STATE_CLOSE_STARTED, ///< Close started on port - PORT_STATE_CLOSE_TX_DONE, ///< Transmits shutdown - PORT_STATE_CLOSE_DONE, ///< Port close operation complete - PORT_STATE_CLOSE_RX_DONE ///< Receives shutdown -} PORT_STATE; - -//------------------------------------------------------------------------------ -// Data Types -//------------------------------------------------------------------------------ - -typedef struct _ESL_IO_MGMT ESL_IO_MGMT;///< Forward declaration -typedef struct _ESL_PACKET ESL_PACKET; ///< Forward declaration -typedef struct _ESL_PORT ESL_PORT; ///< Forward declaration -typedef struct _ESL_SOCKET ESL_SOCKET; ///< Forward declaration - -/** - Receive context for SOCK_RAW sockets using IPv4. -**/ -typedef struct -{ - EFI_IP4_RECEIVE_DATA * pRxData; ///< Receive operation description -} ESL_IP4_RX_DATA; - - -/** - Transmit context for SOCK_RAW sockets using IPv4. -**/ -typedef struct -{ - EFI_IP4_OVERRIDE_DATA Override; ///< Override data - EFI_IP4_TRANSMIT_DATA TxData; ///< Transmit operation description - UINT8 Buffer[ 1 ]; ///< Data buffer -} ESL_IP4_TX_DATA; - - -/** - Receive context for SOCK_STREAM and SOCK_SEQPACKET sockets using TCPv4. -**/ -typedef struct -{ - EFI_TCP4_RECEIVE_DATA RxData; ///< Receive operation description - UINT8 Buffer[ RX_PACKET_DATA ]; ///< Data buffer -} ESL_TCP4_RX_DATA; - - -/** - Transmit context for SOCK_STREAM and SOCK_SEQPACKET sockets using TCPv4. -**/ -typedef struct -{ - EFI_TCP4_TRANSMIT_DATA TxData; ///< Transmit operation description - UINT8 Buffer[ 1 ]; ///< Data buffer -} ESL_TCP4_TX_DATA; - - -/** - Receive context for SOCK_STREAM and SOCK_SEQPACKET sockets using TCPv6. -**/ -typedef struct -{ - EFI_TCP6_RECEIVE_DATA RxData; ///< Receive operation description - UINT8 Buffer[ RX_PACKET_DATA ]; ///< Data buffer -} ESL_TCP6_RX_DATA; - - -/** - Transmit context for SOCK_STREAM and SOCK_SEQPACKET sockets using TCPv6. -**/ -typedef struct -{ - EFI_TCP6_TRANSMIT_DATA TxData; ///< Transmit operation description - UINT8 Buffer[ 1 ]; ///< Data buffer -} ESL_TCP6_TX_DATA; - - -/** - Receive context for SOCK_DGRAM sockets using UDPv4. -**/ -typedef struct -{ - EFI_UDP4_SESSION_DATA Session; ///< Remote network address - EFI_UDP4_RECEIVE_DATA * pRxData; ///< Receive operation description -} ESL_UDP4_RX_DATA; - - -/** - Transmit context for SOCK_DGRAM sockets using UDPv4. -**/ -typedef struct -{ - EFI_UDP4_SESSION_DATA Session; ///< Remote network address - EFI_UDP4_TRANSMIT_DATA TxData; ///< Transmit operation description - UINTN RetransmitCount; ///< Retransmit to handle ARP negotiation - UINT8 Buffer[ 1 ]; ///< Data buffer -} ESL_UDP4_TX_DATA; - - -/** - Receive context for SOCK_DGRAM sockets using UDPv6. -**/ -typedef struct -{ - EFI_UDP6_SESSION_DATA Session; ///< Remote network address - EFI_UDP6_RECEIVE_DATA * pRxData; ///< Receive operation description -} ESL_UDP6_RX_DATA; - - -/** - Transmit context for SOCK_DGRAM sockets using UDPv6. -**/ -typedef struct -{ - EFI_UDP6_SESSION_DATA Session; ///< Remote network address - EFI_UDP6_TRANSMIT_DATA TxData; ///< Transmit operation description - UINTN RetransmitCount; ///< Retransmit to handle ARP negotiation - UINT8 Buffer[ 1 ]; ///< Data buffer -} ESL_UDP6_TX_DATA; - - -/** - Network specific context for transmit and receive packets. -**/ -typedef struct _ESL_PACKET { - ESL_PACKET * pNext; ///< Next packet in the receive list - size_t PacketSize; ///< Size of this data structure - size_t ValidBytes; ///< Length of valid data in bytes - UINT8 * pBuffer; ///< Current data pointer - union { - ESL_IP4_RX_DATA Ip4Rx; ///< Receive operation description - ESL_IP4_TX_DATA Ip4Tx; ///< Transmit operation description - ESL_TCP4_RX_DATA Tcp4Rx; ///< Receive operation description - ESL_TCP4_TX_DATA Tcp4Tx; ///< Transmit operation description - ESL_TCP6_RX_DATA Tcp6Rx; ///< Receive operation description - ESL_TCP6_TX_DATA Tcp6Tx; ///< Transmit operation description - ESL_UDP4_RX_DATA Udp4Rx; ///< Receive operation description - ESL_UDP4_TX_DATA Udp4Tx; ///< Transmit operation description - ESL_UDP6_RX_DATA Udp6Rx; ///< Receive operation description - ESL_UDP6_TX_DATA Udp6Tx; ///< Transmit operation description - } Op; ///< Network specific context -} GCC_ESL_PACKET; - -/** - Service control structure - - The driver uses this structure to manage the network devices. -**/ -typedef struct _ESL_SERVICE { - UINTN Signature; ///< Structure identification - - // - // Links - // - ESL_SERVICE * pNext; ///< Next service in the service list - - // - // Service data - // - CONST ESL_SOCKET_BINDING * pSocketBinding; ///< Name and shutdown routine - EFI_HANDLE Controller; ///< Controller for the service - EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding; ///< Network layer service binding interface - - // - // Network data - // - ESL_PORT * pPortList; ///< List of ports using this service -}GCC_ESL_SERVICE; - -/** - IO management structure - - This structure manages a single operation with the network. -**/ -typedef struct _ESL_IO_MGMT { - ESL_IO_MGMT * pNext; ///< Next TX management structure - ESL_PORT * pPort; ///< Port structure address - ESL_PACKET * pPacket; ///< Packet structure address - union { - EFI_IP4_COMPLETION_TOKEN Ip4Rx; ///< IP4 receive token - EFI_IP4_COMPLETION_TOKEN Ip4Tx; ///< IP4 transmit token - EFI_TCP4_IO_TOKEN Tcp4Rx; ///< TCP4 receive token - EFI_TCP4_IO_TOKEN Tcp4Tx; ///< TCP4 transmit token - EFI_TCP6_IO_TOKEN Tcp6Rx; ///< TCP6 receive token - EFI_TCP6_IO_TOKEN Tcp6Tx; ///< TCP6 transmit token - EFI_UDP4_COMPLETION_TOKEN Udp4Rx; ///< UDP4 receive token - EFI_UDP4_COMPLETION_TOKEN Udp4Tx; ///< UDP4 transmit token - EFI_UDP6_COMPLETION_TOKEN Udp6Rx; ///< UDP6 receive token - EFI_UDP6_COMPLETION_TOKEN Udp6Tx; ///< UDP6 transmit token - } Token; ///< Completion token for the network operation -} GCC_IO_MGMT; - -/** - IP4 context structure - - The driver uses this structure to manage the IP4 connections. -**/ -typedef struct { - // - // IP4 context - // - EFI_IP4_MODE_DATA ModeData; ///< IP4 mode data, includes configuration data - EFI_IPv4_ADDRESS DestinationAddress; ///< Default destination address -} ESL_IP4_CONTEXT; - - -/** - TCP4 context structure - - The driver uses this structure to manage the TCP4 connections. -**/ -typedef struct { - // - // TCP4 context - // - EFI_TCP4_CONFIG_DATA ConfigData; ///< TCP4 configuration data - EFI_TCP4_OPTION Option; ///< TCP4 port options - - // - // Tokens - // - EFI_TCP4_LISTEN_TOKEN ListenToken; ///< Listen control - EFI_TCP4_CONNECTION_TOKEN ConnectToken; ///< Connection control - EFI_TCP4_CLOSE_TOKEN CloseToken; ///< Close control -} ESL_TCP4_CONTEXT; - -/** - TCP6 context structure - - The driver uses this structure to manage the TCP6 connections. -**/ -typedef struct { - // - // TCP6 context - // - EFI_TCP6_CONFIG_DATA ConfigData; ///< TCP6 configuration data - EFI_TCP6_OPTION Option; ///< TCP6 port options - - // - // Tokens - // - EFI_TCP6_LISTEN_TOKEN ListenToken; ///< Listen control - EFI_TCP6_CONNECTION_TOKEN ConnectToken; ///< Connection control - EFI_TCP6_CLOSE_TOKEN CloseToken; ///< Close control -} ESL_TCP6_CONTEXT; - -/** - UDP4 context structure - - The driver uses this structure to manage the UDP4 connections. -**/ -typedef struct { - // - // UDP4 context - // - EFI_UDP4_CONFIG_DATA ConfigData; ///< UDP4 configuration data -} ESL_UDP4_CONTEXT; - -/** - UDP6 context structure - - The driver uses this structure to manage the UDP6 connections. -**/ -typedef struct { - // - // UDP6 context - // - EFI_UDP6_CONFIG_DATA ConfigData; ///< UDP6 configuration data -} ESL_UDP6_CONTEXT; - - -/** - Configure the network layer. - - @param [in] pProtocol Protocol structure address - @param [in] pConfigData Address of the confiuration data - - @return Returns EFI_SUCCESS if the operation is successfully - started. -**/ -typedef -EFI_STATUS -(EFIAPI * PFN_NET_CONFIGURE) ( - IN VOID * pProtocol, - IN VOID * pConfigData - ); - -/** - Hand an I/O operation to the network layer. - - @param [in] pProtocol Protocol structure address - @param [in] pToken Completion token address - - @return Returns EFI_SUCCESS if the operation is successfully - started. -**/ -typedef -EFI_STATUS -(EFIAPI * PFN_NET_IO_START) ( - IN VOID * pProtocol, - IN VOID * pToken - ); - -/** - Poll the LAN adapter for receive packets. - - @param [in] pProtocol Protocol structure address - @param [in] pToken Completion token address - - @return Returns EFI_SUCCESS if the operation is successfully - started. -**/ -typedef -EFI_STATUS -(EFIAPI * PFN_NET_POLL) ( - IN VOID * pProtocol - ); - -/** - Port control structure - - The driver uses this structure to manager the socket's connection - with the network driver. -**/ -typedef struct _ESL_PORT { - UINTN Signature; ///< Structure identification - - // - // List links - // - ESL_PORT * pLinkService; ///< Link in service port list - ESL_PORT * pLinkSocket; ///< Link in socket port list - - // - // Structures - // - ESL_SERVICE * pService; ///< Service for this port - ESL_SOCKET * pSocket; ///< Socket for this port - - // - // Eliminate the pService references during port close - // - EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding; ///< Service binding for network layer - CONST ESL_SOCKET_BINDING * pSocketBinding; ///< Socket binding for network layer - - // - // Port management - // - EFI_HANDLE Handle; ///< Network port handle - PORT_STATE State; ///< State of the port - UINTN DebugFlags; ///< Debug flags used to close the port - BOOLEAN bCloseNow; ///< TRUE = Close the port immediately - BOOLEAN bConfigured; ///< TRUE = Configure call made to network layer - PFN_NET_CONFIGURE pfnConfigure; ///< Configure the network layer - - // - // Transmit data management - // - BOOLEAN bTxFlowControl; ///< TX flow control applied - PFN_NET_IO_START pfnTxStart; ///< Start a transmit on the network - ESL_IO_MGMT * pTxActive; ///< Normal data queue - ESL_IO_MGMT * pTxFree; ///< Normal free queue - - ESL_IO_MGMT * pTxOobActive; ///< Urgent data queue - ESL_IO_MGMT * pTxOobFree; ///< Urgent free queue - - // - // Receive data management - // - PFN_NET_IO_START pfnRxCancel; ///< Cancel a receive on the network - PFN_NET_POLL pfnRxPoll; ///< Poll the LAN adapter for receive packets - PFN_NET_IO_START pfnRxStart; ///< Start a receive on the network - ESL_IO_MGMT * pRxActive; ///< Active receive operation queue - ESL_IO_MGMT * pRxFree; ///< Free structure queue - - // - // Protocol specific management data - // - union { - VOID * v; ///< VOID pointer - EFI_IP4_PROTOCOL * IPv4; ///< IP4 protocol pointer - EFI_TCP4_PROTOCOL * TCPv4; ///< TCP4 protocol pointer - EFI_TCP6_PROTOCOL * TCPv6; ///< TCP6 protocol pointer - EFI_UDP4_PROTOCOL * UDPv4; ///< UDP4 protocol pointer - EFI_UDP6_PROTOCOL * UDPv6; ///< UDP6 protocol pointer - } pProtocol; ///< Protocol structure address - union { - ESL_IP4_CONTEXT Ip4; ///< IPv4 management data - ESL_TCP4_CONTEXT Tcp4; ///< TCPv4 management data - ESL_TCP6_CONTEXT Tcp6; ///< TCPv6 management data - ESL_UDP4_CONTEXT Udp4; ///< UDPv4 management data - ESL_UDP6_CONTEXT Udp6; ///< UDPv6 management data - } Context; ///< Network specific context -}GCC_ESL_PORT; - -/** - Accept a network connection. - - @param [in] pSocket Address of the socket structure. - - @param [in] pSockAddr Address of a buffer to receive the remote - network address. - - @param [in, out] pSockAddrLength Length in bytes of the address buffer. - On output specifies the length of the - remote network address. - - @retval EFI_SUCCESS Remote address is available - @retval Others Remote address not available - - **/ -typedef -EFI_STATUS -(* PFN_API_ACCEPT) ( - IN ESL_SOCKET * pSocket, - IN struct sockaddr * pSockAddr, - IN OUT socklen_t * pSockAddrLength - ); - -/** - Poll for completion of the connection attempt. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @retval EFI_SUCCESS The connection was successfully established. - @retval EFI_NOT_READY The connection is in progress, call this routine again. - @retval Others The connection attempt failed. - - **/ -typedef -EFI_STATUS -(* PFN_API_CONNECT_POLL) ( - IN ESL_SOCKET * pSocket - ); - -/** - Attempt to connect to a remote TCP port - - This routine starts the connection processing for a SOCK_STREAM - or SOCK_SEQPAKCET socket using the TCP network layer. - - This routine is called by ::EslSocketConnect to initiate the TCP - network specific connect operations. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @retval EFI_SUCCESS The connection was successfully established. - @retval EFI_NOT_READY The connection is in progress, call this routine again. - @retval Others The connection attempt failed. - - **/ -typedef -EFI_STATUS -(* PFN_API_CONNECT_START) ( - IN ESL_SOCKET * pSocket - ); - -/** - Get the local socket address - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [out] pAddress Network address to receive the local system address - -**/ -typedef -VOID -(* PFN_API_LOCAL_ADDR_GET) ( - IN ESL_PORT * pPort, - OUT struct sockaddr * pAddress - ); - -/** - Set the local port address. - - This routine sets the local port address. - - This support routine is called by ::EslSocketPortAllocate. - - @param [in] ppPort Address of an ESL_PORT structure - @param [in] pSockAddr Address of a sockaddr structure that contains the - connection point on the local machine. An IPv4 address - of INADDR_ANY specifies that the connection is made to - all of the network stacks on the platform. Specifying a - specific IPv4 address restricts the connection to the - network stack supporting that address. Specifying zero - for the port causes the network layer to assign a port - number from the dynamic range. Specifying a specific - port number causes the network layer to use that port. - @param [in] bBindTest TRUE = run bind testing - - @retval EFI_SUCCESS The operation was successful - - **/ -typedef -EFI_STATUS -(* PFN_API_LOCAL_ADDR_SET) ( - IN ESL_PORT * pPort, - IN CONST struct sockaddr * pSockAddr, - IN BOOLEAN bBindTest - ); - -/** - Process the completion event - - This routine handles the I/O completion event. - - This routine is called by the low level network driver when - the operation is completed. - - @param [in] Event The receive completion event - - @param [in] pIo The address of an ::ESL_IO_MGMT structure - -**/ -typedef -VOID -(* PFN_API_IO_COMPLETE) ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ); - -/** - Determine if the socket is configured. - - - @param [in] pSocket Address of a ESL_SOCKET structure - - @retval EFI_SUCCESS - The port is connected - @retval EFI_NOT_STARTED - The port is not connected - - **/ - typedef - EFI_STATUS - (* PFN_API_IS_CONFIGURED) ( - IN ESL_SOCKET * pSocket - ); - -/** - Establish the known port to listen for network connections. - - @param [in] pSocket Address of the socket structure. - - @retval EFI_SUCCESS - Socket successfully created - @retval Other - Failed to enable the socket for listen - -**/ -typedef -EFI_STATUS -(* PFN_API_LISTEN) ( - IN ESL_SOCKET * pSocket - ); - -/** - Get the option value - - Retrieve the protocol options one at a time by name. - - @param [in] pSocket Address of a ESL_SOCKET structure - @param [in] OptionName Name of the option - @param [out] ppOptionData Buffer to receive address of option value - @param [out] pOptionLength Buffer to receive the option length - - @retval EFI_SUCCESS - Socket data successfully received - - **/ -typedef -EFI_STATUS -(* PFN_API_OPTION_GET) ( - IN ESL_SOCKET * pSocket, - IN int OptionName, - OUT CONST void ** __restrict ppOptionData, - OUT socklen_t * __restrict pOptionLength - ); - -/** - Set the option value - - Adjust the protocol options one at a time by name. - - @param [in] pSocket Address of a ESL_SOCKET structure - @param [in] OptionName Name of the option - @param [in] pOptionValue Buffer containing the option value - @param [in] OptionLength Length of the buffer in bytes - - @retval EFI_SUCCESS - Option successfully set - - **/ -typedef -EFI_STATUS -(* PFN_API_OPTION_SET) ( - IN ESL_SOCKET * pSocket, - IN int OptionName, - IN CONST void * pOptionValue, - IN socklen_t OptionLength - ); - -/** - Free a receive packet - - This routine performs the network specific operations necessary - to free a receive packet. - - This routine is called by ::EslSocketPortCloseTxDone to free a - receive packet. - - @param [in] pPacket Address of an ::ESL_PACKET structure. - @param [in, out] pRxBytes Address of the count of RX bytes - -**/ -typedef -VOID -(* PFN_API_PACKET_FREE) ( - IN ESL_PACKET * pPacket, - IN OUT size_t * pRxBytes - ); - -/** - Initialize the network specific portions of an ::ESL_PORT structure. - - This routine initializes the network specific portions of an - ::ESL_PORT structure for use by the socket. - - This support routine is called by ::EslSocketPortAllocate - to connect the socket with the underlying network adapter - running the IPv4 protocol. - - @param [in] ppPort Address of an ESL_PORT structure - @param [in] DebugFlags Flags for debug messages - - @retval EFI_SUCCESS - Socket successfully created - - **/ -typedef -EFI_STATUS -(* PFN_API_PORT_ALLOC) ( - IN ESL_PORT * pPort, - IN UINTN DebugFlags - ); - -/** - Close a network specific port. - - This routine releases the resources allocated by the - network specific PortAllocate routine. - - This routine is called by ::EslSocketPortCloseRxDone as - the last step of closing processing. - See the \ref PortCloseStateMachine section. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @retval EFI_SUCCESS The port is closed - @retval other Port close error - -**/ -typedef -EFI_STATUS -(* PFN_API_PORT_CLOSE) ( - IN ESL_PORT * pPort - ); - -/** - Perform the network specific close operation on the port. - - This routine performs the network specific operation to - shutdown receive operations on the port. - - This routine is called by the ::EslSocketPortCloseTxDone - routine after the port completes all of the transmission. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @retval EFI_SUCCESS The port is closed, not normally returned - @retval EFI_NOT_READY The port is still closing - @retval EFI_ALREADY_STARTED Error, the port is in the wrong state, - most likely the routine was called already. - -**/ -typedef -EFI_STATUS -(* PFN_API_PORT_CLOSE_OP) ( - IN ESL_PORT * pPort - ); - -/** - Receive data from a network connection. - - This routine attempts to return buffered data to the caller. The - data is removed from the urgent queue if the message flag MSG_OOB - is specified, otherwise data is removed from the normal queue. - See the \ref ReceiveEngine section. - - This routine is called by ::EslSocketReceive to handle the network - specific receive operation. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [in] pPacket Address of an ::ESL_PACKET structure. - - @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @param [out] pAddress Network address to receive the remote system address - - @param [out] pSkipBytes Address to receive the number of bytes skipped - - @return Returns the address of the next free byte in the buffer. - - **/ -typedef -UINT8 * -(* PFN_API_RECEIVE) ( - IN ESL_PORT * pPort, - IN ESL_PACKET * pPacket, - IN BOOLEAN * pbConsumePacket, - IN size_t BufferLength, - IN UINT8 * pBuffer, - OUT size_t * pDataLength, - OUT struct sockaddr * pAddress, - OUT size_t * pSkipBytes - ); - -/** - Get the remote socket address - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [out] pAddress Network address to receive the remote system address - -**/ -typedef -VOID -(* PFN_API_REMOTE_ADDR_GET) ( - IN ESL_PORT * pPort, - OUT struct sockaddr * pAddress - ); - -/** - Set the remote address - - This routine sets the remote address in the port. - - This routine is called by ::EslSocketConnect to specify the - remote network address. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [in] pSockAddr Network address of the remote system. - - @param [in] SockAddrLength Length in bytes of the network address. - - @retval EFI_SUCCESS The operation was successful - - **/ -typedef -EFI_STATUS -(* PFN_API_REMOTE_ADDR_SET) ( - IN ESL_PORT * pPort, - IN CONST struct sockaddr * pSockAddr, - IN socklen_t SockAddrLength - ); - -/** - Start a receive operation - - This routine prepares a packet for the receive operation. - See the \ref ReceiveEngine section. - - This support routine is called by EslSocketRxStart. - - @param [in] pPort Address of an ::ESL_PORT structure. - @param [in] pIo Address of an ::ESL_IO_MGMT structure. - - **/ -typedef -VOID -(* PFN_API_RX_START) ( - IN ESL_PORT * pPort, - IN ESL_IO_MGMT * pIo - ); - -/** - Buffer data for transmission over a network connection. - - @param [in] pSocket Address of a ESL_SOCKET structure - - @param [in] Flags Message control flags - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @param [in] pAddress Network address of the remote system address - - @param [in] AddressLength Length of the remote network address structure - - @retval EFI_SUCCESS - Socket data successfully buffered - -**/ -typedef -EFI_STATUS -(* PFN_API_TRANSMIT) ( - IN ESL_SOCKET * pSocket, - IN int Flags, - IN size_t BufferLength, - IN CONST UINT8 * pBuffer, - OUT size_t * pDataLength, - IN const struct sockaddr * pAddress, - IN socklen_t AddressLength - ); - -/** - Process the transmit completion - - This routine calls ::EslSocketTxComplete to handle the - transmit completion. - - This routine is called by the network layers upon the completion - of a transmit operation. - - @param [in] Event The urgent transmit completion event - - @param [in] pIo The ESL_IO_MGMT structure address - -**/ -typedef -VOID -(* PFN_API_TX_COMPLETE) ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ); - -/** - Verify the adapter's IP address - - This support routine is called by EslSocketBindTest. - - @param [in] pPort Address of an ::ESL_PORT structure. - @param [in] pConfigData Address of the configuration data - - @retval EFI_SUCCESS - The IP address is valid - @retval EFI_NOT_STARTED - The IP address is invalid - - **/ -typedef -EFI_STATUS -(* PFN_API_VERIFY_LOCAL_IP_ADDRESS) ( - IN ESL_PORT * pPort, - IN VOID * pConfigData - ); - -/** - Socket type control structure - - This driver uses this structure to define the API for the socket type. -**/ -typedef struct { - CONST CHAR8 * pName; ///< Protocol name - int DefaultProtocol; ///< Default protocol - UINTN ConfigDataOffset; ///< Offset in ::ESL_PORT to the configuration data - UINTN ServiceListOffset; ///< Offset in ::ESL_LAYER for the list of services - socklen_t MinimumAddressLength; ///< Minimum address length in bytes - socklen_t AddressLength; ///< Address length in bytes - sa_family_t AddressFamily; ///< Address family - UINTN RxPacketBytes; ///< Length of the RX packet allocation - UINTN RxZeroBytes; ///< Number of bytes to zero in RX packet - UINTN RxBufferOffset; ///< Offset of buffer address in ESL_IO_MGMT structure - BOOLEAN bOobSupported; ///< TRUE if out-of-band messages are supported - int BindTestErrno; ///< errno value if EslSocketBindTest fails - PFN_API_ACCEPT pfnAccept; ///< Accept a network connection - PFN_API_CONNECT_POLL pfnConnectPoll; ///< Poll for connection complete - PFN_API_CONNECT_START pfnConnectStart; ///< Start the connection to a remote system - PFN_API_IS_CONFIGURED pfnIsConfigured; ///< Determine if the socket is configured - PFN_API_LOCAL_ADDR_GET pfnLocalAddrGet; ///< Get the local address - PFN_API_LOCAL_ADDR_SET pfnLocalAddrSet; ///< Set the local address - PFN_API_LISTEN pfnListen; ///< Listen for connections on known server port - PFN_API_OPTION_GET pfnOptionGet; ///< Get the option value - PFN_API_OPTION_SET pfnOptionSet; ///< Set the option value - PFN_API_PACKET_FREE pfnPacketFree; ///< Free the receive packet - PFN_API_PORT_ALLOC pfnPortAllocate; ///< Allocate the network specific resources for the port - PFN_API_PORT_CLOSE pfnPortClose; ///< Close the network specific resources for the port - PFN_API_PORT_CLOSE_OP pfnPortCloseOp; ///< Perform the close operation on the port - BOOLEAN bPortCloseComplete; ///< TRUE = Close is complete after close operation - PFN_API_RECEIVE pfnReceive; ///< Attempt to receive some data - PFN_API_REMOTE_ADDR_GET pfnRemoteAddrGet; ///< Get remote address - PFN_API_REMOTE_ADDR_SET pfnRemoteAddrSet; ///< Set the remote system address - PFN_API_IO_COMPLETE pfnRxComplete; ///< RX completion - PFN_API_RX_START pfnRxStart; ///< Start a network specific receive operation - PFN_API_TRANSMIT pfnTransmit; ///< Attempt to buffer a packet for transmit - PFN_API_TX_COMPLETE pfnTxComplete; ///< TX completion for normal data - PFN_API_TX_COMPLETE pfnTxOobComplete; ///< TX completion for urgent data - PFN_API_VERIFY_LOCAL_IP_ADDRESS pfnVerifyLocalIpAddress; ///< Verify the local IP address -} ESL_PROTOCOL_API; - - -/** - Socket control structure - - The driver uses this structure to manage the socket. -**/ -typedef struct _ESL_SOCKET { - UINTN Signature; ///< Structure identification - - // - // Protocol binding - // - EFI_SOCKET_PROTOCOL SocketProtocol; ///< Socket protocol declaration - CONST ESL_PROTOCOL_API * pApi; ///< API for the protocol - - // - // Socket management - // - ESL_SOCKET * pNext; ///< Next socket in the list of sockets - int errno; ///< Error information for this socket - EFI_STATUS Status; ///< Asyncronous error information for this socket - SOCKET_STATE State; ///< Socket state - UINT32 DebugFlags; ///< Debug flags - - // - // Socket options - // - BOOLEAN bIncludeHeader; ///< TRUE if including the IP header - BOOLEAN bListenCalled; ///< TRUE if listen was successfully called - BOOLEAN bOobInLine; ///< TRUE if out-of-band messages are to be received inline with normal data - BOOLEAN bReUseAddr; ///< TRUE if using same address is allowed - - // - // Socket data - // - int Domain; ///< Specifies family of protocols - int Type; ///< Specifies how to make network connection - int Protocol; ///< Specifies lower layer protocol to use - BOOLEAN bAddressSet; ///< Set when the address is specified - BOOLEAN bConfigured; ///< Set after the socket is configured - - BOOLEAN bRxDisable; ///< Receive disabled via shutdown - size_t RxBytes; ///< Total Rx bytes - size_t RxOobBytes; ///< Urgent Rx bytes - EFI_STATUS RxError; ///< Error during receive - - BOOLEAN bTxDisable; ///< Transmit disabled via shutdown - size_t TxBytes; ///< Normal Tx bytes - size_t TxOobBytes; ///< Urgent Tx bytes - EFI_STATUS TxError; ///< Error during transmit - - // - // Pending connection data - // - BOOLEAN bConnected; ///< Set when connected, cleared by poll - EFI_STATUS ConnectStatus; ///< Connection status - UINTN MaxFifoDepth; ///< Maximum FIFO depth - UINTN FifoDepth; ///< Number of sockets in the FIFO - ESL_SOCKET * pFifoHead; ///< Head of the FIFO - ESL_SOCKET * pFifoTail; ///< Tail of the FIFO - ESL_SOCKET * pNextConnection; ///< Link in the FIFO - - // - // Network use - // - ESL_PORT * pPortList; ///< List of ports managed by this socket - EFI_EVENT WaitAccept; ///< Wait for accept completion - - // - // Receive data management - // - UINT32 MaxRxBuf; ///< Maximum size of the receive buffer - struct timeval RxTimeout; ///< Receive timeout - ESL_PACKET * pRxFree; ///< Free packet list - ESL_PACKET * pRxOobPacketListHead;///< Urgent data list head - ESL_PACKET * pRxOobPacketListTail;///< Urgent data list tail - ESL_PACKET * pRxPacketListHead; ///< Normal data list head - ESL_PACKET * pRxPacketListTail; ///< Normal data list tail - - // - // Transmit data management - // - UINTN TxPacketOffset; ///< Offset for data pointer in ::ESL_PACKET - UINTN TxTokenEventOffset; ///< Offset to the Event in the TX token - UINTN TxTokenOffset; ///< Offset for data pointer in TX token - UINT32 MaxTxBuf; ///< Maximum size of the transmit buffer - ESL_PACKET * pTxOobPacketListHead;///< Urgent data list head - ESL_PACKET * pTxOobPacketListTail;///< Urgent data list tail - ESL_PACKET * pTxPacketListHead; ///< Normal data list head - ESL_PACKET * pTxPacketListTail; ///< Normal data list tail -}GCC_ESL_SOCKET; - -#define SOCKET_FROM_PROTOCOL(a) CR (a, ESL_SOCKET, SocketProtocol, SOCKET_SIGNATURE) ///< Locate ESL_SOCKET from protocol - -/** - Socket layer control structure - - The driver uses this structure to manage the driver. -**/ -typedef struct { - UINTN Signature; ///< Structure identification - - // - // Service binding interface - // - CONST EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding; ///< Driver's binding - - // - // Image data - // - EFI_HANDLE ImageHandle; ///< Image handle - - // - // Network services - // - ESL_SERVICE * pIp4List; ///< List of Ip4 services - ESL_SERVICE * pTcp4List; ///< List of Tcp4 services - ESL_SERVICE * pTcp6List; ///< List of Tcp6 services - ESL_SERVICE * pUdp4List; ///< List of Udp4 services - ESL_SERVICE * pUdp6List; ///< List of Udp6 services - - // - // Socket management - // - ESL_SOCKET * pSocketList; ///< List of sockets -} ESL_LAYER; - -#define LAYER_FROM_SERVICE(a) CR (a, ESL_LAYER, ServiceBinding, LAYER_SIGNATURE) ///< Locate ESL_LAYER from service binding - -//------------------------------------------------------------------------------ -// Data -//------------------------------------------------------------------------------ - -extern ESL_LAYER mEslLayer; - -extern CONST ESL_PROTOCOL_API cEslIp4Api; -extern CONST ESL_PROTOCOL_API cEslIp6Api; -extern CONST ESL_PROTOCOL_API cEslTcp4Api; -extern CONST ESL_PROTOCOL_API cEslTcp6Api; -extern CONST ESL_PROTOCOL_API cEslUdp4Api; -extern CONST ESL_PROTOCOL_API cEslUdp6Api; - -extern CONST EFI_SERVICE_BINDING_PROTOCOL mEfiServiceBinding; - -//------------------------------------------------------------------------------ -// Socket Support Routines -//------------------------------------------------------------------------------ - -/** - Allocate and initialize a ESL_SOCKET structure. - - This support function allocates an ::ESL_SOCKET structure - and installs a protocol on ChildHandle. If pChildHandle is a - pointer to NULL, then a new handle is created and returned in - pChildHandle. If pChildHandle is not a pointer to NULL, then - the protocol installs on the existing pChildHandle. - - @param [in, out] pChildHandle Pointer to the handle of the child to create. - If it is NULL, then a new handle is created. - If it is a pointer to an existing UEFI handle, - then the protocol is added to the existing UEFI - handle. - @param [in] DebugFlags Flags for debug messages - @param [in, out] ppSocket The buffer to receive an ::ESL_SOCKET structure address. - - @retval EFI_SUCCESS The protocol was added to ChildHandle. - @retval EFI_INVALID_PARAMETER ChildHandle is NULL. - @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create - the child - @retval other The child handle was not created - -**/ -EFI_STATUS -EFIAPI -EslSocketAllocate ( - IN OUT EFI_HANDLE * pChildHandle, - IN UINTN DebugFlags, - IN OUT ESL_SOCKET ** ppSocket - ); - -/** - Test the bind configuration. - - @param [in] pPort Address of the ::ESL_PORT structure. - @param [in] ErrnoValue errno value if test fails - - @retval EFI_SUCCESS The connection was successfully established. - @retval Others The connection attempt failed. - - **/ -EFI_STATUS -EslSocketBindTest ( - IN ESL_PORT * pPort, - IN int ErrnoValue - ); - -/** - Copy a fragmented buffer into a destination buffer. - - This support routine copies a fragmented buffer to the caller specified buffer. - - This routine is called by ::EslIp4Receive and ::EslUdp4Receive. - - @param [in] FragmentCount Number of fragments in the table - - @param [in] pFragmentTable Address of an EFI_IP4_FRAGMENT_DATA structure - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @return Returns the address of the next free byte in the buffer. - -**/ -UINT8 * -EslSocketCopyFragmentedBuffer ( - IN UINT32 FragmentCount, - IN EFI_IP4_FRAGMENT_DATA * pFragmentTable, - IN size_t BufferLength, - IN UINT8 * pBuffer, - OUT size_t * pDataLength - ); - -/** - Free the socket. - - This routine frees the socket structure and handle resources. - - The ::close routine calls EslServiceFreeProtocol which then calls - this routine to free the socket context structure and close the - handle. - - @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure. - - @param [out] pErrno Address to receive the errno value upon completion. - - @retval EFI_SUCCESS The socket resources were returned successfully. - - **/ -EFI_STATUS -EslSocketFree ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol, - IN int * pErrno - ); - -/** - Free the ESL_IO_MGMT event and structure - - This support routine walks the free list to close the event in - the ESL_IO_MGMT structure and remove the structure from the free - list. - - See the \ref TransmitEngine section. - - @param [in] pPort Address of an ::ESL_PORT structure - @param [in] ppFreeQueue Address of the free queue head - @param [in] DebugFlags Flags for debug messages - @param [in] pEventName Zero terminated string containing the event name - - @retval EFI_SUCCESS - The structures were properly initialized - -**/ -EFI_STATUS -EslSocketIoFree ( - IN ESL_PORT * pPort, - IN ESL_IO_MGMT ** ppFreeQueue, - IN UINTN DebugFlags, - IN CHAR8 * pEventName - ); - -/** - Initialize the ESL_IO_MGMT structures - - This support routine initializes the ESL_IO_MGMT structure and - places them on to a free list. - - This routine is called by the PortAllocate routines to prepare - the transmit engines. See the \ref TransmitEngine section. - - @param [in] pPort Address of an ::ESL_PORT structure - @param [in, out] ppIo Address containing the first structure address. Upon - return this buffer contains the next structure address. - @param [in] TokenCount Number of structures to initialize - @param [in] ppFreeQueue Address of the free queue head - @param [in] DebugFlags Flags for debug messages - @param [in] pEventName Zero terminated string containing the event name - @param [in] pfnCompletion Completion routine address - - @retval EFI_SUCCESS - The structures were properly initialized - -**/ -EFI_STATUS -EslSocketIoInit ( - IN ESL_PORT * pPort, - IN ESL_IO_MGMT ** ppIo, - IN UINTN TokenCount, - IN ESL_IO_MGMT ** ppFreeQueue, - IN UINTN DebugFlags, - IN CHAR8 * pEventName, - IN PFN_API_IO_COMPLETE pfnCompletion - ); - -/** - Determine if the socket is configured - - This support routine is called to determine if the socket if the - configuration call was made to the network layer. The following - routines call this routine to verify that they may be successful - in their operations: -
    -
  • ::EslSocketGetLocalAddress
  • -
  • ::EslSocketGetPeerAddress
  • -
  • ::EslSocketPoll
  • -
  • ::EslSocketReceive
  • -
  • ::EslSocketTransmit
  • -
- - @param [in] pSocket Address of an ::ESL_SOCKET structure - - @retval EFI_SUCCESS - The socket is configured - -**/ -EFI_STATUS -EslSocketIsConfigured ( - IN ESL_SOCKET * pSocket - ); - -/** - Allocate a packet for a receive or transmit operation - - This support routine is called by ::EslSocketRxStart and the - network specific TxBuffer routines to get buffer space for the - next operation. - - @param [in] ppPacket Address to receive the ::ESL_PACKET structure - @param [in] LengthInBytes Length of the packet structure - @param [in] ZeroBytes Length of packet to zero - @param [in] DebugFlags Flags for debug messages - - @retval EFI_SUCCESS - The packet was allocated successfully - - **/ -EFI_STATUS -EslSocketPacketAllocate ( - IN ESL_PACKET ** ppPacket, - IN size_t LengthInBytes, - IN size_t ZeroBytes, - IN UINTN DebugFlags - ); - -/** - Free a packet used for receive or transmit operation - - This support routine is called by the network specific Close - and TxComplete routines and during error cases in RxComplete - and TxBuffer. Note that the network layers typically place - receive packets on the ESL_SOCKET::pRxFree list for reuse. - - @param [in] pPacket Address of an ::ESL_PACKET structure - @param [in] DebugFlags Flags for debug messages - - @retval EFI_SUCCESS - The packet was allocated successfully - - **/ -EFI_STATUS -EslSocketPacketFree ( - IN ESL_PACKET * pPacket, - IN UINTN DebugFlags - ); - -/** - Allocate and initialize a ESL_PORT structure. - - This routine initializes an ::ESL_PORT structure for use by - the socket. This routine calls a routine via - ESL_PROTOCOL_API::pfnPortAllocate to initialize the network - specific resources. The resources are released later by the - \ref PortCloseStateMachine. - - This support routine is called by ::EslSocketBind and - ::EslTcp4ListenComplete to connect the socket with the - underlying network adapter to the socket. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - @param [in] pService Address of an ::ESL_SERVICE structure. - @param [in] ChildHandle TCP4 child handle - @param [in] pSockAddr Address of a sockaddr structure that contains the - connection point on the local machine. An IPv4 address - of INADDR_ANY specifies that the connection is made to - all of the network stacks on the platform. Specifying a - specific IPv4 address restricts the connection to the - network stack supporting that address. Specifying zero - for the port causes the network layer to assign a port - number from the dynamic range. Specifying a specific - port number causes the network layer to use that port. - @param [in] bBindTest TRUE if EslSocketBindTest should be called - @param [in] DebugFlags Flags for debug messages - @param [out] ppPort Buffer to receive new ::ESL_PORT structure address - - @retval EFI_SUCCESS - Socket successfully created - - **/ -EFI_STATUS -EslSocketPortAllocate ( - IN ESL_SOCKET * pSocket, - IN ESL_SERVICE * pService, - IN EFI_HANDLE ChildHandle, - IN CONST struct sockaddr * pSockAddr, - IN BOOLEAN bBindTest, - IN UINTN DebugFlags, - OUT ESL_PORT ** ppPort - ); - -/** - Close a port. - - This routine releases the resources allocated by ::EslSocketPortAllocate. - This routine calls ESL_PROTOCOL_API::pfnPortClose to release the network - specific resources. - - This routine is called by: -
    -
  • ::EslIp4PortAllocate - Port initialization failure
  • -
  • ::EslSocketPortCloseRxDone - Last step of close processing
  • -
  • ::EslTcp4ConnectComplete - Connection failure and reducint the port list to a single port
  • -
  • ::EslTcp4PortAllocate - Port initialization failure
  • -
  • ::EslUdp4PortAllocate - Port initialization failure
  • -
- See the \ref PortCloseStateMachine section. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @retval EFI_SUCCESS The port is closed - @retval other Port close error - -**/ -EFI_STATUS -EslSocketPortClose ( - IN ESL_PORT * pPort - ); - -/** - Process the port close completion event - - This routine attempts to complete the port close operation. - - This routine is called by the TCP layer upon completion of - the close operation. - See the \ref PortCloseStateMachine section. - - @param [in] Event The close completion event - - @param [in] pPort Address of an ::ESL_PORT structure. - -**/ -VOID -EslSocketPortCloseComplete ( - IN EFI_EVENT Event, - IN ESL_PORT * pPort - ); - -/** - Port close state 3 - - This routine determines the state of the receive operations and - continues the close operation after the pending receive operations - are cancelled. - - This routine is called by -
    -
  • ::EslIp4RxComplete
  • -
  • ::EslSocketPortCloseComplete
  • -
  • ::EslSocketPortCloseTxDone
  • -
  • ::EslUdp4RxComplete
  • -
- to determine the state of the receive operations. - See the \ref PortCloseStateMachine section. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @retval EFI_SUCCESS The port is closed - @retval EFI_NOT_READY The port is still closing - @retval EFI_ALREADY_STARTED Error, the port is in the wrong state, - most likely the routine was called already. - -**/ -EFI_STATUS -EslSocketPortCloseRxDone ( - IN ESL_PORT * pPort - ); - -/** - Start the close operation on a port, state 1. - - This routine marks the port as closed and initiates the \ref - PortCloseStateMachine. The first step is to allow the \ref - TransmitEngine to run down. - - This routine is called by ::EslSocketCloseStart to initiate the socket - network specific close operation on the socket. - - @param [in] pPort Address of an ::ESL_PORT structure. - @param [in] bCloseNow Set TRUE to abort active transfers - @param [in] DebugFlags Flags for debug messages - - @retval EFI_SUCCESS The port is closed, not normally returned - @retval EFI_NOT_READY The port has started the closing process - @retval EFI_ALREADY_STARTED Error, the port is in the wrong state, - most likely the routine was called already. - -**/ -EFI_STATUS -EslSocketPortCloseStart ( - IN ESL_PORT * pPort, - IN BOOLEAN bCloseNow, - IN UINTN DebugFlags - ); - -/** - Port close state 2 - - This routine determines the state of the transmit engine and - continue the close operation after the transmission is complete. - The next step is to stop the \ref ReceiveEngine. - See the \ref PortCloseStateMachine section. - - This routine is called by ::EslSocketPortCloseStart to determine - if the transmission is complete. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @retval EFI_SUCCESS The port is closed, not normally returned - @retval EFI_NOT_READY The port is still closing - @retval EFI_ALREADY_STARTED Error, the port is in the wrong state, - most likely the routine was called already. - -**/ -EFI_STATUS -EslSocketPortCloseTxDone ( - IN ESL_PORT * pPort - ); - -/** - Cancel the receive operations - - This routine cancels a pending receive operation. - See the \ref ReceiveEngine section. - - This routine is called by ::EslSocketShutdown when the socket - layer is being shutdown. - - @param [in] pPort Address of an ::ESL_PORT structure - @param [in] pIo Address of an ::ESL_IO_MGMT structure - - **/ -VOID -EslSocketRxCancel ( - IN ESL_PORT * pPort, - IN ESL_IO_MGMT * pIo - ); - -/** - Process the receive completion - - This routine queues the data in FIFO order in either the urgent - or normal data queues depending upon the type of data received. - See the \ref ReceiveEngine section. - - This routine is called when some data is received by: -
    -
  • ::EslIp4RxComplete
  • -
  • ::EslTcp4RxComplete
  • -
  • ::EslUdp4RxComplete
  • -
- - @param [in] pIo Address of an ::ESL_IO_MGMT structure - @param [in] Status Receive status - @param [in] LengthInBytes Length of the receive data - @param [in] bUrgent TRUE if urgent data is received and FALSE - for normal data. - -**/ -VOID -EslSocketRxComplete ( - IN ESL_IO_MGMT * pIo, - IN EFI_STATUS Status, - IN UINTN LengthInBytes, - IN BOOLEAN bUrgent - ); - -/** - Poll a socket for pending receive activity. - - This routine is called at elivated TPL and extends the idle - loop which polls a socket down into the LAN driver layer to - determine if there is any receive activity. - - The ::EslSocketPoll, ::EslSocketReceive and ::EslSocketTransmit - routines call this routine when there is nothing to do. - - @param [in] pSocket Address of an ::EFI_SOCKET structure. - - **/ -VOID -EslSocketRxPoll ( - IN ESL_SOCKET * pSocket - ); - -/** - Start a receive operation - - This routine posts a receive buffer to the network adapter. - See the \ref ReceiveEngine section. - - This support routine is called by: -
    -
  • ::EslIp4Receive to restart the receive engine to release flow control.
  • -
  • ::EslIp4RxComplete to continue the operation of the receive engine if flow control is not being applied.
  • -
  • ::EslIp4SocketIsConfigured to start the recevie engine for the new socket.
  • -
  • ::EslTcp4ListenComplete to start the recevie engine for the new socket.
  • -
  • ::EslTcp4Receive to restart the receive engine to release flow control.
  • -
  • ::EslTcp4RxComplete to continue the operation of the receive engine if flow control is not being applied.
  • -
  • ::EslUdp4Receive to restart the receive engine to release flow control.
  • -
  • ::EslUdp4RxComplete to continue the operation of the receive engine if flow control is not being applied.
  • -
  • ::EslUdp4SocketIsConfigured to start the recevie engine for the new socket.
  • -
- - @param [in] pPort Address of an ::ESL_PORT structure. - - **/ -VOID -EslSocketRxStart ( - IN ESL_PORT * pPort - ); - -/** - Complete the transmit operation - - This support routine handles the transmit completion processing for - the various network layers. It frees the ::ESL_IO_MGMT structure - and and frees packet resources by calling ::EslSocketPacketFree. - Transmit errors are logged in ESL_SOCKET::TxError. - See the \ref TransmitEngine section. - - This routine is called by: -
    -
  • ::EslIp4TxComplete
  • -
  • ::EslTcp4TxComplete
  • -
  • ::EslTcp4TxOobComplete
  • -
  • ::EslUdp4TxComplete
  • -
- - @param [in] pIo Address of an ::ESL_IO_MGMT structure - @param [in] LengthInBytes Length of the data in bytes - @param [in] Status Transmit operation status - @param [in] pQueueType Zero terminated string describing queue type - @param [in] ppQueueHead Transmit queue head address - @param [in] ppQueueTail Transmit queue tail address - @param [in] ppActive Active transmit queue address - @param [in] ppFree Free transmit queue address - - **/ -VOID -EslSocketTxComplete ( - IN ESL_IO_MGMT * pIo, - IN UINT32 LengthInBytes, - IN EFI_STATUS Status, - IN CONST CHAR8 * pQueueType, - IN ESL_PACKET ** ppQueueHead, - IN ESL_PACKET ** ppQueueTail, - IN ESL_IO_MGMT ** ppActive, - IN ESL_IO_MGMT ** ppFree - ); - -/** - Transmit data using a network connection. - - This support routine starts a transmit operation on the - underlying network layer. - - The network specific code calls this routine to start a - transmit operation. See the \ref TransmitEngine section. - - @param [in] pPort Address of an ::ESL_PORT structure - @param [in] ppQueueHead Transmit queue head address - @param [in] ppQueueTail Transmit queue tail address - @param [in] ppActive Active transmit queue address - @param [in] ppFree Free transmit queue address - - **/ -VOID -EslSocketTxStart ( - IN ESL_PORT * pPort, - IN ESL_PACKET ** ppQueueHead, - IN ESL_PACKET ** ppQueueTail, - IN ESL_IO_MGMT ** ppActive, - IN ESL_IO_MGMT ** ppFree - ); - -//------------------------------------------------------------------------------ - -#endif // _SOCKET_H_ diff --git a/StdLib/EfiSocketLib/Tcp4.c b/StdLib/EfiSocketLib/Tcp4.c deleted file mode 100644 index 68477fba6e..0000000000 --- a/StdLib/EfiSocketLib/Tcp4.c +++ /dev/null @@ -1,2432 +0,0 @@ -/** @file - Implement the TCP4 driver support for the socket layer. - - Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
- This program and the accompanying materials are licensed and made available - under the terms and conditions of the BSD License which accompanies this - distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php. - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - - - \section ConnectionManagement Connection Management - - The ::EslTcp4Listen routine initially places the SOCK_STREAM or - SOCK_SEQPACKET socket into a listen state. When a remote machine - makes a connection to the socket, the TCPv4 network layer calls - ::EslTcp4ListenComplete to complete the connection processing. - EslTcp4ListenComplete manages the connections by placing them in - FIFO order in a queue to be serviced by the application. When the - number of connections exceeds the backlog (ESL_SOCKET::MaxFifoDepth), - the new connection is closed. Eventually, the application indirectly - calls ::EslTcp4Accept to remove the next connection from the queue - and get the associated socket. - -**/ - -#include "Socket.h" - - -/** - Attempt to connect to a remote TCP port - - This routine starts the connection processing for a SOCK_STREAM - or SOCK_SEQPAKCET socket using the TCPv4 network layer. It - configures the local TCPv4 connection point and then attempts to - connect to a remote system. Upon completion, the - ::EslTcp4ConnectComplete routine gets called with the connection - status. - - This routine is called by ::EslSocketConnect to initiate the TCPv4 - network specific connect operations. The connection processing is - initiated by this routine and finished by ::EslTcp4ConnectComplete. - This pair of routines walks through the list of local TCPv4 - connection points until a connection to the remote system is - made. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @retval EFI_SUCCESS The connection was successfully established. - @retval EFI_NOT_READY The connection is in progress, call this routine again. - @retval Others The connection attempt failed. - - **/ -EFI_STATUS -EslTcp4ConnectStart ( - IN ESL_SOCKET * pSocket - ); - - -/** - Process the connection attempt - - A system has initiated a connection attempt with a socket in the - listen state. Attempt to complete the connection. - - The TCPv4 layer calls this routine when a connection is made to - the socket in the listen state. See the - \ref ConnectionManagement section. - - @param [in] Event The listen completion event - - @param [in] pPort Address of an ::ESL_PORT structure. - -**/ -VOID -EslTcp4ListenComplete ( - IN EFI_EVENT Event, - IN ESL_PORT * pPort - ); - - -/** - Accept a network connection. - - This routine waits for a network connection to the socket and - returns the remote network address to the caller if requested. - - This routine is called by ::EslSocketAccept to handle the TCPv4 protocol - specific accept operations for SOCK_STREAM and SOCK_SEQPACKET sockets. - See the \ref ConnectionManagement section. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @param [in] pSockAddr Address of a buffer to receive the remote - network address. - - @param [in, out] pSockAddrLength Length in bytes of the address buffer. - On output specifies the length of the - remote network address. - - @retval EFI_SUCCESS Remote address is available - @retval Others Remote address not available - - **/ -EFI_STATUS -EslTcp4Accept ( - IN ESL_SOCKET * pSocket, - IN struct sockaddr * pSockAddr, - IN OUT socklen_t * pSockAddrLength - ) -{ - ESL_PORT * pPort; - struct sockaddr_in * pRemoteAddress; - ESL_TCP4_CONTEXT * pTcp4; - UINT32 RemoteAddress; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Validate the socket length - // - pRemoteAddress = (struct sockaddr_in *) pSockAddr; - if (( NULL == pSockAddrLength ) - || ( sizeof ( *pRemoteAddress ) > *pSockAddrLength )) { - // - // Invalid socket address - // - Status = EFI_INVALID_PARAMETER; - pSocket->errno = EINVAL; - DEBUG (( DEBUG_ACCEPT, - "ERROR - Invalid address length\r\n" )); - } - else { - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Locate the address context - // - pPort = pSocket->pPortList; - pTcp4 = &pPort->Context.Tcp4; - - // - // Fill-in the remote address structure - // - ZeroMem ( pRemoteAddress, sizeof ( *pRemoteAddress )); - pRemoteAddress->sin_len = sizeof ( *pRemoteAddress ); - pRemoteAddress->sin_family = AF_INET; - pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort ); - RemoteAddress = pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3]; - RemoteAddress <<= 8; - RemoteAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2]; - RemoteAddress <<= 8; - RemoteAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1]; - RemoteAddress <<= 8; - RemoteAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0]; - pRemoteAddress->sin_addr.s_addr = RemoteAddress; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the remote connection completion event. - - This routine handles the completion of a connection attempt. It - releases the port (TCPv4 adapter connection) in the case of an - error and start a connection attempt on the next port. If the - connection attempt was successful then this routine releases all - of the other ports. - - This routine is called by the TCPv4 layer when a connect request - completes. It sets the ESL_SOCKET::bConnected flag to notify the - ::EslTcp4ConnectComplete routine that the connection is available. - The flag is set when the connection is established or no more ports - exist in the list. The connection status is passed via - ESL_SOCKET::ConnectStatus. - - @param [in] Event The connect completion event - - @param [in] pPort Address of an ::ESL_PORT structure. - -**/ -VOID -EslTcp4ConnectComplete ( - IN EFI_EVENT Event, - IN ESL_PORT * pPort - ) -{ - BOOLEAN bRemoveFirstPort; - BOOLEAN bRemovePorts; - ESL_PORT * pNextPort; - ESL_SOCKET * pSocket; - ESL_TCP4_CONTEXT * pTcp4; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the TCP context - // - pSocket = pPort->pSocket; - pTcp4 = &pPort->Context.Tcp4; - - // - // Get the connection status - // - bRemoveFirstPort = FALSE; - bRemovePorts = FALSE; - Status = pTcp4->ConnectToken.CompletionToken.Status; - pSocket->ConnectStatus = Status; - if ( !EFI_ERROR ( Status )) { - // - // The connection was successful - // - DEBUG (( DEBUG_CONNECT, - "0x%08x: Port connected to %d.%d.%d.%d:%d\r\n", - pPort, - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0], - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1], - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2], - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3], - pTcp4->ConfigData.AccessPoint.RemotePort )); - - // - // Start the receive operations - // - pSocket->bConfigured = TRUE; - pSocket->State = SOCKET_STATE_CONNECTED; - EslSocketRxStart ( pPort ); - - // - // Remove the rest of the ports - // - bRemovePorts = TRUE; - } - else { - // - // The connection failed - // - if ( pPort->bConfigured ) { - DEBUG (( DEBUG_CONNECT, - "0x%08x: Port connection to %d.%d.%d.%d:%d failed, Status: %r\r\n", - pPort, - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0], - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1], - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2], - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3], - pTcp4->ConfigData.AccessPoint.RemotePort, - Status )); - } - - // - // Close the current port - // - Status = EslSocketPortClose ( pPort ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_CONNECT, - "0x%08x: Port closed\r\n", - pPort )); - } - else { - DEBUG (( DEBUG_CONNECT, - "ERROR - Failed to close port 0x%08x, Status: %r\r\n", - pPort, - Status )); - } - - // - // Try to connect using the next port - // - Status = EslTcp4ConnectStart ( pSocket ); - if ( EFI_NOT_READY != Status ) { - bRemoveFirstPort = TRUE; - } - } - - // - // Remove the ports if necessary - // - if ( bRemoveFirstPort || bRemovePorts ) { - // - // Remove the first port if necessary - // - pPort = pSocket->pPortList; - if (( !bRemoveFirstPort ) && ( NULL != pPort )) { - pPort = pPort->pLinkSocket; - } - - // - // Remove the rest of the list - // - while ( NULL != pPort ) { - pNextPort = pPort->pLinkSocket; - EslSocketPortClose ( pPort ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_CONNECT, - "0x%08x: Port closed\r\n", - pPort )); - } - else { - DEBUG (( DEBUG_CONNECT, - "ERROR - Failed to close port 0x%08x, Status: %r\r\n", - pPort, - Status )); - } - pPort = pNextPort; - } - - // - // Notify the poll routine - // - pSocket->bConnected = TRUE; - } - - DBG_EXIT ( ); -} - - -/** - Poll for completion of the connection attempt. - - This routine polls the ESL_SOCKET::bConnected flag to determine - when the connection attempt is complete. - - This routine is called from ::EslSocketConnect to determine when - the connection is complete. The ESL_SOCKET::bConnected flag is - set by ::EslTcp4ConnectComplete when the TCPv4 layer establishes - a connection or runs out of local network adapters. This routine - gets the connection status from ESL_SOCKET::ConnectStatus. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @retval EFI_SUCCESS The connection was successfully established. - @retval EFI_NOT_READY The connection is in progress, call this routine again. - @retval Others The connection attempt failed. - - **/ -EFI_STATUS -EslTcp4ConnectPoll ( - IN ESL_SOCKET * pSocket - ) -{ - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Determine if the connection is complete - // - if ( !pSocket->bConnected ) { - // - // Not connected - // - pSocket->errno = EAGAIN; - Status = EFI_NOT_READY; - } - else { - // - // The connection processing is complete - // - pSocket->bConnected = FALSE; - - // - // Translate the connection status - // - Status = pSocket->ConnectStatus; - switch ( Status ) { - default: - case EFI_DEVICE_ERROR: - pSocket->errno = EIO; - break; - - case EFI_ABORTED: - pSocket->errno = ECONNABORTED; - break; - - case EFI_ACCESS_DENIED: - pSocket->errno = EACCES; - break; - - case EFI_CONNECTION_RESET: - pSocket->errno = ECONNRESET; - break; - - case EFI_INVALID_PARAMETER: - pSocket->errno = EADDRNOTAVAIL; - break; - - case EFI_HOST_UNREACHABLE: - case EFI_NO_RESPONSE: - pSocket->errno = EHOSTUNREACH; - break; - - case EFI_NO_MAPPING: - pSocket->errno = EAFNOSUPPORT; - break; - - case EFI_NO_MEDIA: - case EFI_NETWORK_UNREACHABLE: - pSocket->errno = ENETDOWN; - break; - - case EFI_OUT_OF_RESOURCES: - pSocket->errno = ENOBUFS; - break; - - case EFI_PORT_UNREACHABLE: - case EFI_PROTOCOL_UNREACHABLE: - case EFI_CONNECTION_REFUSED: - pSocket->errno = ECONNREFUSED; - break; - - case EFI_SUCCESS: - pSocket->errno = 0; - break; - - case EFI_TIMEOUT: - pSocket->errno = ETIMEDOUT; - break; - - case EFI_UNSUPPORTED: - pSocket->errno = EOPNOTSUPP; - break; - } - - // - // Display the translation - // - DEBUG (( DEBUG_CONNECT, - "ERROR - errno: %d, Status: %r\r\n", - pSocket->errno, - Status )); - } - - // - // Return the initialization status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Attempt to connect to a remote TCP port - - This routine starts the connection processing for a SOCK_STREAM - or SOCK_SEQPAKCET socket using the TCPv4 network layer. It - configures the local TCPv4 connection point and then attempts to - connect to a remote system. Upon completion, the - ::EslTcp4ConnectComplete routine gets called with the connection - status. - - This routine is called by ::EslSocketConnect to initiate the TCPv4 - network specific connect operations. The connection processing is - initiated by this routine and finished by ::EslTcp4ConnectComplete. - This pair of routines walks through the list of local TCPv4 - connection points until a connection to the remote system is - made. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @retval EFI_SUCCESS The connection was successfully established. - @retval EFI_NOT_READY The connection is in progress, call this routine again. - @retval Others The connection attempt failed. - - **/ -EFI_STATUS -EslTcp4ConnectStart ( - IN ESL_SOCKET * pSocket - ) -{ - ESL_PORT * pPort; - ESL_TCP4_CONTEXT * pTcp4; - EFI_TCP4_PROTOCOL * pTcp4Protocol; - EFI_SIMPLE_NETWORK_MODE SnpModeData; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Determine if any more local adapters are available - // - pPort = pSocket->pPortList; - if ( NULL != pPort ) { - // - // Configure the port - // - pTcp4 = &pPort->Context.Tcp4; - pTcp4->ConfigData.AccessPoint.ActiveFlag = TRUE; - pTcp4->ConfigData.TimeToLive = 255; - pTcp4Protocol = pPort->pProtocol.TCPv4; - Status = pTcp4Protocol->Configure ( pTcp4Protocol, - &pTcp4->ConfigData ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_CONNECT, - "ERROR - Failed to configure the Tcp4 port, Status: %r\r\n", - Status )); - } - else { - DEBUG (( DEBUG_CONNECT, - "0x%08x: Port configured\r\n", - pPort )); - pPort->bConfigured = TRUE; - - // - // Verify the port connection - // - Status = pTcp4Protocol->GetModeData ( pTcp4Protocol, - NULL, - NULL, - NULL, - NULL, - &SnpModeData ); - if ( !EFI_ERROR ( Status )) { - if ( SnpModeData.MediaPresentSupported - && ( !SnpModeData.MediaPresent )) { - // - // Port is not connected to the network - // - Status = EFI_NO_MEDIA; - } - else { - // - // Attempt the connection to the remote system - // - Status = pTcp4Protocol->Connect ( pTcp4Protocol, - &pTcp4->ConnectToken ); - } - } - if ( EFI_ERROR ( Status )) { - // - // Connection error - // - DEBUG (( DEBUG_CONNECT, - "ERROR - Port 0x%08x not connected, Status: %r\r\n", - pPort, - Status )); - } - } - if ( !EFI_ERROR ( Status )) { - // - // Connection in progress - // - pSocket->errno = EINPROGRESS; - DEBUG (( DEBUG_CONNECT, - "0x%08x: Port attempting connection to %d.%d.%d.%d:%d\r\n", - pPort, - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0], - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1], - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2], - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3], - pTcp4->ConfigData.AccessPoint.RemotePort )); - } - else { - // - // Error return path is through EslTcp4ConnectComplete to - // enable retry on other ports - // - // Status to errno translation gets done in EslTcp4ConnectPoll - // - pTcp4->ConnectToken.CompletionToken.Status = Status; - - // - // Continue with the next port - // - gBS->CheckEvent ( pTcp4->ConnectToken.CompletionToken.Event ); - gBS->SignalEvent ( pTcp4->ConnectToken.CompletionToken.Event ); - } - Status = EFI_NOT_READY; - } - else { - // - // No more local adapters available - // - pSocket->errno = ENETUNREACH; - Status = EFI_NO_RESPONSE; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Establish the known port to listen for network connections. - - This routine places the port into a state that enables connection - attempts. - - This routine is called by ::EslSocketListen to handle the network - specifics of the listen operation for SOCK_STREAM and SOCK_SEQPACKET - sockets. See the \ref ConnectionManagement section. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @retval EFI_SUCCESS - Socket successfully created - @retval Other - Failed to enable the socket for listen - -**/ -EFI_STATUS -EslTcp4Listen ( - IN ESL_SOCKET * pSocket - ) -{ - ESL_PORT * pNextPort; - ESL_PORT * pPort; - ESL_TCP4_CONTEXT * pTcp4; - EFI_TCP4_PROTOCOL * pTcp4Protocol; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Verify the socket layer synchronization - // - VERIFY_TPL ( TPL_SOCKETS ); - - // - // Use for/break instead of goto - // - for ( ; ; ) { - // - // Assume no ports are available - // - pSocket->errno = EOPNOTSUPP; - Status = EFI_NOT_READY; - - // - // Walk the list of ports - // - pPort = pSocket->pPortList; - while ( NULL != pPort ) { - // - // Assume success - // - pSocket->errno = 0; - - // - // Use for/break insteak of goto - // - for ( ; ; ) { - // - // Create the listen completion event - // - pTcp4 = &pPort->Context.Tcp4; - Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_SOCKETS, - (EFI_EVENT_NOTIFY)EslTcp4ListenComplete, - pPort, - &pTcp4->ListenToken.CompletionToken.Event ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR | DEBUG_LISTEN, - "ERROR - Failed to create the listen completion event, Status: %r\r\n", - Status )); - pSocket->errno = ENOMEM; - break; - } - DEBUG (( DEBUG_POOL, - "0x%08x: Created listen completion event\r\n", - pTcp4->ListenToken.CompletionToken.Event )); - - // - // Configure the port - // - pTcp4Protocol = pPort->pProtocol.TCPv4; - Status = pTcp4Protocol->Configure ( pTcp4Protocol, - &pTcp4->ConfigData ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_LISTEN, - "ERROR - Failed to configure the Tcp4 port, Status: %r\r\n", - Status )); - switch ( Status ) { - case EFI_ACCESS_DENIED: - pSocket->errno = EACCES; - break; - - default: - case EFI_DEVICE_ERROR: - pSocket->errno = EIO; - break; - - case EFI_INVALID_PARAMETER: - pSocket->errno = EADDRNOTAVAIL; - break; - - case EFI_NO_MAPPING: - pSocket->errno = EAFNOSUPPORT; - break; - - case EFI_OUT_OF_RESOURCES: - pSocket->errno = ENOBUFS; - break; - - case EFI_UNSUPPORTED: - pSocket->errno = EOPNOTSUPP; - break; - } - break; - } - DEBUG (( DEBUG_LISTEN, - "0x%08x: Port configured\r\n", - pPort )); - pPort->bConfigured = TRUE; - - // - // Start the listen operation on the port - // - Status = pTcp4Protocol->Accept ( pTcp4Protocol, - &pTcp4->ListenToken ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_LISTEN, - "ERROR - Failed Tcp4 accept, Status: %r\r\n", - Status )); - switch ( Status ) { - case EFI_ACCESS_DENIED: - pSocket->errno = EACCES; - break; - - default: - case EFI_DEVICE_ERROR: - pSocket->errno = EIO; - break; - - case EFI_INVALID_PARAMETER: - pSocket->errno = EADDRNOTAVAIL; - break; - - case EFI_NOT_STARTED: - pSocket->errno = ENETDOWN; - break; - - case EFI_OUT_OF_RESOURCES: - pSocket->errno = ENOBUFS; - break; - } - break; - } - DEBUG (( DEBUG_LISTEN, - "0x%08x: Listen pending on Port\r\n", - pPort )); - - // - // Listen is pending on this port - // - break; - } - - // - // Get the next port - // - pNextPort = pPort->pLinkSocket; - - // - // Close the port upon error - // - if ( EFI_ERROR ( Status )) { - EslSocketPortCloseStart ( pPort, TRUE, DEBUG_LISTEN ); - } - - // - // Set the next port - // - pPort = pNextPort; - } - - // - // Determine if any ports are in the listen state - // - if ( NULL == pSocket->pPortList ) { - // - // No ports in the listen state - // - pSocket->MaxFifoDepth = 0; - - // - // Return the last error detected - // - break; - } - - // - // Mark the socket as configured - // - pSocket->bConfigured = TRUE; - Status = EFI_SUCCESS; - pSocket->errno = 0; - - // - // All done - // - DEBUG (( DEBUG_LISTEN, - "0x%08x: pSocket - Listen pending on socket\r\n", - pSocket )); - break; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the connection attempt - - A system has initiated a connection attempt with a socket in the - listen state. Attempt to complete the connection. - - The TCPv4 layer calls this routine when a connection is made to - the socket in the listen state. See the - \ref ConnectionManagement section. - - @param [in] Event The listen completion event - - @param [in] pPort Address of an ::ESL_PORT structure. - -**/ -VOID -EslTcp4ListenComplete ( - IN EFI_EVENT Event, - IN ESL_PORT * pPort - ) -{ - EFI_HANDLE ChildHandle; - struct sockaddr_in LocalAddress; - EFI_TCP4_CONFIG_DATA * pConfigData; - ESL_PORT * pNewPort; - ESL_SOCKET * pNewSocket; - ESL_SOCKET * pSocket; - ESL_TCP4_CONTEXT * pTcp4; - EFI_TCP4_PROTOCOL * pTcp4Protocol; - EFI_STATUS Status; - EFI_HANDLE TcpPortHandle; - EFI_STATUS TempStatus; - - DBG_ENTER ( ); - VERIFY_AT_TPL ( TPL_SOCKETS ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Determine if this connection fits into the connection FIFO - // - pSocket = pPort->pSocket; - TcpPortHandle = pPort->Context.Tcp4.ListenToken.NewChildHandle; - if (( SOCKET_STATE_LISTENING == pSocket->State ) - && ( pSocket->MaxFifoDepth > pSocket->FifoDepth )) { - // - // Allocate a socket for this connection - // - ChildHandle = NULL; - Status = EslSocketAllocate ( &ChildHandle, - DEBUG_CONNECTION, - &pNewSocket ); - if ( !EFI_ERROR ( Status )) { - // - // Clone the socket parameters - // - pNewSocket->pApi = pSocket->pApi; - pNewSocket->Domain = pSocket->Domain; - pNewSocket->Protocol = pSocket->Protocol; - pNewSocket->Type = pSocket->Type; - - // - // Build the local address - // - pTcp4 = &pPort->Context.Tcp4; - LocalAddress.sin_len = (uint8_t)pNewSocket->pApi->MinimumAddressLength; - LocalAddress.sin_family = AF_INET; - LocalAddress.sin_port = 0; - LocalAddress.sin_addr.s_addr = *(UINT32 *)&pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0]; - - // - // Allocate a port for this connection - // Note in this instance Configure may not be called with NULL! - // - Status = EslSocketPortAllocate ( pNewSocket, - pPort->pService, - TcpPortHandle, - (struct sockaddr *)&LocalAddress, - FALSE, - DEBUG_CONNECTION, - &pNewPort ); - if ( !EFI_ERROR ( Status )) { - // - // Restart the listen operation on the port - // - pTcp4Protocol = pPort->pProtocol.TCPv4; - Status = pTcp4Protocol->Accept ( pTcp4Protocol, - &pTcp4->ListenToken ); - - // - // Close the TCP port using SocketClose - // - TcpPortHandle = NULL; - pTcp4 = &pNewPort->Context.Tcp4; - - // - // Check for an accept call error - // - if ( !EFI_ERROR ( Status )) { - // - // Get the port configuration - // - pNewPort->bConfigured = TRUE; - pConfigData = &pTcp4->ConfigData; - pConfigData->ControlOption = &pTcp4->Option; - pTcp4Protocol = pNewPort->pProtocol.TCPv4; - Status = pTcp4Protocol->GetModeData ( pTcp4Protocol, - NULL, - pConfigData, - NULL, - NULL, - NULL ); - if ( !EFI_ERROR ( Status )) { - // - // Add the new socket to the connection FIFO - // - if ( NULL == pSocket->pFifoTail ) { - // - // First connection - // - pSocket->pFifoHead = pNewSocket; - } - else { - // - // Add to end of list. - // - pSocket->pFifoTail->pNextConnection = pNewSocket; - } - pSocket->pFifoTail = pNewSocket; - pSocket->FifoDepth += 1; - - // - // Update the socket state - // - pNewSocket->State = SOCKET_STATE_IN_FIFO; - - // - // Log the connection - // - DEBUG (( DEBUG_CONNECTION | DEBUG_INFO, - "0x%08x: Socket on port %d.%d.%d.%d:%d connected to %d.%d.%d.%d:%d\r\n", - pNewSocket, - pConfigData->AccessPoint.StationAddress.Addr[0], - pConfigData->AccessPoint.StationAddress.Addr[1], - pConfigData->AccessPoint.StationAddress.Addr[2], - pConfigData->AccessPoint.StationAddress.Addr[3], - pConfigData->AccessPoint.StationPort, - pConfigData->AccessPoint.RemoteAddress.Addr[0], - pConfigData->AccessPoint.RemoteAddress.Addr[1], - pConfigData->AccessPoint.RemoteAddress.Addr[2], - pConfigData->AccessPoint.RemoteAddress.Addr[3], - pConfigData->AccessPoint.RemotePort )); - DEBUG (( DEBUG_CONNECTION | DEBUG_INFO, - "0x%08x: Listen socket adding socket 0x%08x to FIFO, depth: %d\r\n", - pSocket, - pNewSocket, - pSocket->FifoDepth )); - - // - // Start the receive operation - // - EslSocketRxStart ( pNewPort ); - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_CONNECTION | DEBUG_INFO, - "ERROR - GetModeData failed on port 0x%08x, Status: %r\r\n", - pNewPort, - Status )); - } - } - else { - // - // The listen failed on this port - // - DEBUG (( DEBUG_LISTEN | DEBUG_INFO, - "ERROR - Listen failed on port 0x%08x, Status: %r\r\n", - pPort, - Status )); - - // - // Close the listening port - // - EslSocketPortCloseStart ( pPort, TRUE, DEBUG_LISTEN ); - } - } - - // - // Done with the socket if necessary - // - if ( EFI_ERROR ( Status )) { - TempStatus = EslSocketCloseStart ( &pNewSocket->SocketProtocol, - TRUE, - &pSocket->errno ); - ASSERT ( EFI_SUCCESS == TempStatus ); - } - } - } - else { - DEBUG (( DEBUG_CONNECTION, - "0x%08x: Socket FIFO full, connection refused\r\n", - pSocket )); - - // - // The FIFO is full or the socket is in the wrong state - // - Status = EFI_BUFFER_TOO_SMALL; - } - - // - // Close the connection if necessary - // - if (( EFI_ERROR ( Status )) - && ( NULL == TcpPortHandle )) { - // - // TODO: Finish this code path - // The new connection does not fit into the connection FIFO - // - // Process: - // Call close - // Release the resources - - } - - DBG_EXIT ( ); -} - - -/** - Get the local socket address. - - This routine returns the IPv4 address and TCP port number associated - with the local socket. - - This routine is called by ::EslSocketGetLocalAddress to determine the - network address for the SOCK_STREAM or SOCK_SEQPACKET socket. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [out] pSockAddr Network address to receive the local system address - -**/ -VOID -EslTcp4LocalAddressGet ( - IN ESL_PORT * pPort, - OUT struct sockaddr * pSockAddr - ) -{ - struct sockaddr_in * pLocalAddress; - ESL_TCP4_CONTEXT * pTcp4; - - DBG_ENTER ( ); - - // - // Return the local address - // - pTcp4 = &pPort->Context.Tcp4; - pLocalAddress = (struct sockaddr_in *)pSockAddr; - pLocalAddress->sin_family = AF_INET; - pLocalAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.StationPort ); - CopyMem ( &pLocalAddress->sin_addr, - &pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0], - sizeof ( pLocalAddress->sin_addr )); - - DBG_EXIT ( ); -} - - -/** - Set the local port address. - - This routine sets the local port address. - - This support routine is called by ::EslSocketPortAllocate. - - @param [in] pPort Address of an ESL_PORT structure - @param [in] pSockAddr Address of a sockaddr structure that contains the - connection point on the local machine. An IPv4 address - of INADDR_ANY specifies that the connection is made to - all of the network stacks on the platform. Specifying a - specific IPv4 address restricts the connection to the - network stack supporting that address. Specifying zero - for the port causes the network layer to assign a port - number from the dynamic range. Specifying a specific - port number causes the network layer to use that port. - - @param [in] bBindTest TRUE = run bind testing - - @retval EFI_SUCCESS The operation was successful - - **/ -EFI_STATUS -EslTcp4LocalAddressSet ( - IN ESL_PORT * pPort, - IN CONST struct sockaddr * pSockAddr, - IN BOOLEAN bBindTest - ) -{ - EFI_TCP4_ACCESS_POINT * pAccessPoint; - CONST struct sockaddr_in * pIpAddress; - CONST UINT8 * pIpv4Address; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Validate the address - // - pIpAddress = (struct sockaddr_in *)pSockAddr; - if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) { - // - // The local address must not be the broadcast address - // - Status = EFI_INVALID_PARAMETER; - pPort->pSocket->errno = EADDRNOTAVAIL; - } - else { - // - // Set the local address - // - pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr; - pAccessPoint = &pPort->Context.Tcp4.ConfigData.AccessPoint; - pAccessPoint->StationAddress.Addr[0] = pIpv4Address[0]; - pAccessPoint->StationAddress.Addr[1] = pIpv4Address[1]; - pAccessPoint->StationAddress.Addr[2] = pIpv4Address[2]; - pAccessPoint->StationAddress.Addr[3] = pIpv4Address[3]; - - // - // Determine if the default address is used - // - pAccessPoint->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr ); - - // - // Set the subnet mask - // - if ( pAccessPoint->UseDefaultAddress ) { - pAccessPoint->SubnetMask.Addr[0] = 0; - pAccessPoint->SubnetMask.Addr[1] = 0; - pAccessPoint->SubnetMask.Addr[2] = 0; - pAccessPoint->SubnetMask.Addr[3] = 0; - } - else { - pAccessPoint->SubnetMask.Addr[0] = 0xff; - pAccessPoint->SubnetMask.Addr[1] = ( 128 <= pAccessPoint->StationAddress.Addr[0]) ? 0xff : 0; - pAccessPoint->SubnetMask.Addr[2] = ( 192 <= pAccessPoint->StationAddress.Addr[0]) ? 0xff : 0; - pAccessPoint->SubnetMask.Addr[3] = ( 224 <= pAccessPoint->StationAddress.Addr[0]) ? 0xff : 0; - } - - // - // Validate the IP address - // - pAccessPoint->StationPort = 0; - Status = bBindTest ? EslSocketBindTest ( pPort, EADDRNOTAVAIL ) - : EFI_SUCCESS; - if ( !EFI_ERROR ( Status )) { - // - // Set the port number - // - pAccessPoint->StationPort = SwapBytes16 ( pIpAddress->sin_port ); - pPort->pSocket->bAddressSet = TRUE; - - // - // Display the local address - // - DEBUG (( DEBUG_BIND, - "0x%08x: Port, Local TCP4 Address: %d.%d.%d.%d:%d\r\n", - pPort, - pAccessPoint->StationAddress.Addr[0], - pAccessPoint->StationAddress.Addr[1], - pAccessPoint->StationAddress.Addr[2], - pAccessPoint->StationAddress.Addr[3], - pAccessPoint->StationPort )); - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Free a receive packet - - This routine performs the network specific operations necessary - to free a receive packet. - - This routine is called by ::EslSocketPortCloseTxDone to free a - receive packet. - - @param [in] pPacket Address of an ::ESL_PACKET structure. - @param [in, out] pRxBytes Address of the count of RX bytes - -**/ -VOID -EslTcp4PacketFree ( - IN ESL_PACKET * pPacket, - IN OUT size_t * pRxBytes - ) -{ - DBG_ENTER ( ); - - // - // Account for the receive bytes - // - *pRxBytes -= pPacket->Op.Tcp4Rx.RxData.DataLength; - DBG_EXIT ( ); -} - - -/** - Initialize the network specific portions of an ::ESL_PORT structure. - - This routine initializes the network specific portions of an - ::ESL_PORT structure for use by the socket. - - This support routine is called by ::EslSocketPortAllocate - to connect the socket with the underlying network adapter - running the TCPv4 protocol. - - @param [in] pPort Address of an ESL_PORT structure - @param [in] DebugFlags Flags for debug messages - - @retval EFI_SUCCESS - Socket successfully created - - **/ -EFI_STATUS -EslTcp4PortAllocate ( - IN ESL_PORT * pPort, - IN UINTN DebugFlags - ) -{ - EFI_TCP4_ACCESS_POINT * pAccessPoint; - ESL_SOCKET * pSocket; - ESL_TCP4_CONTEXT * pTcp4; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Use for/break instead of goto - for ( ; ; ) { - // - // Allocate the close event - // - pSocket = pPort->pSocket; - pTcp4 = &pPort->Context.Tcp4; - Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_SOCKETS, - (EFI_EVENT_NOTIFY)EslSocketPortCloseComplete, - pPort, - &pTcp4->CloseToken.CompletionToken.Event); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to create the close event, Status: %r\r\n", - Status )); - pSocket->errno = ENOMEM; - break; - } - DEBUG (( DEBUG_CLOSE | DEBUG_POOL, - "0x%08x: Created close event\r\n", - pTcp4->CloseToken.CompletionToken.Event )); - - // - // Allocate the connection event - // - Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_SOCKETS, - (EFI_EVENT_NOTIFY)EslTcp4ConnectComplete, - pPort, - &pTcp4->ConnectToken.CompletionToken.Event); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to create the connect event, Status: %r\r\n", - Status )); - pSocket->errno = ENOMEM; - break; - } - DEBUG (( DEBUG_CLOSE | DEBUG_POOL, - "0x%08x: Created connect event\r\n", - pTcp4->ConnectToken.CompletionToken.Event )); - - // - // Initialize the port - // - pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Tcp4Tx.TxData ); - pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Tcp4Tx.CompletionToken.Event ); - pSocket->TxTokenOffset = OFFSET_OF ( EFI_TCP4_IO_TOKEN, Packet.TxData ); - - // - // Save the cancel, receive and transmit addresses - // pPort->pfnRxCancel = NULL; since the UEFI implementation returns EFI_UNSUPPORTED - // - pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.TCPv4->Configure; - pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.TCPv4->Poll; - pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Receive; - pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Transmit; - - // - // Set the configuration flags - // - pAccessPoint = &pPort->Context.Tcp4.ConfigData.AccessPoint; - pAccessPoint->ActiveFlag = FALSE; - pTcp4->ConfigData.TimeToLive = 255; - break; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Close a TCP4 port. - - This routine releases the network specific resources allocated by - ::EslTcp4PortAllocate. - - This routine is called by ::EslSocketPortClose. - See the \ref PortCloseStateMachine section. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @retval EFI_SUCCESS The port is closed - @retval other Port close error - -**/ -EFI_STATUS -EslTcp4PortClose ( - IN ESL_PORT * pPort - ) -{ - UINTN DebugFlags; - ESL_TCP4_CONTEXT * pTcp4; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the port in the socket list - // - Status = EFI_SUCCESS; - DebugFlags = pPort->DebugFlags; - pTcp4 = &pPort->Context.Tcp4; - - // - // Done with the connect event - // - if ( NULL != pTcp4->ConnectToken.CompletionToken.Event ) { - Status = gBS->CloseEvent ( pTcp4->ConnectToken.CompletionToken.Event ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DebugFlags | DEBUG_POOL, - "0x%08x: Closed connect event\r\n", - pTcp4->ConnectToken.CompletionToken.Event )); - } - else { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to close the connect event, Status: %r\r\n", - Status )); - ASSERT ( EFI_SUCCESS == Status ); - } - } - - // - // Done with the close event - // - if ( NULL != pTcp4->CloseToken.CompletionToken.Event ) { - Status = gBS->CloseEvent ( pTcp4->CloseToken.CompletionToken.Event ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DebugFlags | DEBUG_POOL, - "0x%08x: Closed close event\r\n", - pTcp4->CloseToken.CompletionToken.Event )); - } - else { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to close the close event, Status: %r\r\n", - Status )); - ASSERT ( EFI_SUCCESS == Status ); - } - } - - // - // Done with the listen completion event - // - if ( NULL != pTcp4->ListenToken.CompletionToken.Event ) { - Status = gBS->CloseEvent ( pTcp4->ListenToken.CompletionToken.Event ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DebugFlags | DEBUG_POOL, - "0x%08x: Closed listen completion event\r\n", - pTcp4->ListenToken.CompletionToken.Event )); - } - else { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to close the listen completion event, Status: %r\r\n", - Status )); - ASSERT ( EFI_SUCCESS == Status ); - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Perform the network specific close operation on the port. - - This routine performs a cancel operations on the TCPv4 port to - shutdown the receive operations on the port. - - This routine is called by the ::EslSocketPortCloseTxDone - routine after the port completes all of the transmission. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @retval EFI_SUCCESS The port is closed, not normally returned - @retval EFI_NOT_READY The port is still closing - @retval EFI_ALREADY_STARTED Error, the port is in the wrong state, - most likely the routine was called already. - -**/ -EFI_STATUS -EslTcp4PortCloseOp ( - IN ESL_PORT * pPort - ) -{ - ESL_TCP4_CONTEXT * pTcp4; - EFI_TCP4_PROTOCOL * pTcp4Protocol; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Close the configured port - // - Status = EFI_SUCCESS; - pTcp4 = &pPort->Context.Tcp4; - pTcp4Protocol = pPort->pProtocol.TCPv4; - pTcp4->CloseToken.AbortOnClose = pPort->bCloseNow; - Status = pTcp4Protocol->Close ( pTcp4Protocol, - &pTcp4->CloseToken ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Port close started\r\n", - pPort )); - } - else { - DEBUG (( DEBUG_ERROR | pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO, - "ERROR - Close failed on port 0x%08x, Status: %r\r\n", - pPort, - Status )); - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Receive data from a network connection. - - This routine attempts to return buffered data to the caller. The - data is removed from the urgent queue if the message flag MSG_OOB - is specified, otherwise data is removed from the normal queue. - See the \ref ReceiveEngine section. - - This routine is called by ::EslSocketReceive to handle the network - specific receive operation to support SOCK_STREAM and SOCK_SEQPACKET - sockets. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [in] pPacket Address of an ::ESL_PACKET structure. - - @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @param [out] pAddress Network address to receive the remote system address - - @param [out] pSkipBytes Address to receive the number of bytes skipped - - @return Returns the address of the next free byte in the buffer. - - **/ -UINT8 * -EslTcp4Receive ( - IN ESL_PORT * pPort, - IN ESL_PACKET * pPacket, - IN BOOLEAN * pbConsumePacket, - IN size_t BufferLength, - IN UINT8 * pBuffer, - OUT size_t * pDataLength, - OUT struct sockaddr * pAddress, - OUT size_t * pSkipBytes - ) -{ - size_t DataLength; - struct sockaddr_in * pRemoteAddress; - ESL_TCP4_CONTEXT * pTcp4; - - DBG_ENTER ( ); - - // - // Return the remote system address if requested - // - if ( NULL != pAddress ) { - // - // Build the remote address - // - pTcp4 = &pPort->Context.Tcp4; - DEBUG (( DEBUG_RX, - "Getting packet remote address: %d.%d.%d.%d:%d\r\n", - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0], - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1], - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2], - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3], - pTcp4->ConfigData.AccessPoint.RemotePort )); - pRemoteAddress = (struct sockaddr_in *)pAddress; - CopyMem ( &pRemoteAddress->sin_addr, - &pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0], - sizeof ( pRemoteAddress->sin_addr )); - pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort ); - } - - // - // Determine the amount of received data - // - DataLength = pPacket->ValidBytes; - if ( BufferLength < DataLength ) { - DataLength = BufferLength; - } - - // - // Move the data into the buffer - // - DEBUG (( DEBUG_RX, - "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n", - pPort, - pPacket, - pBuffer, - DataLength )); - CopyMem ( pBuffer, pPacket->pBuffer, DataLength ); - - // - // Set the next buffer address - // - pBuffer += DataLength; - - // - // Determine if the data is being read - // - if ( *pbConsumePacket ) { - // - // Account for the bytes consumed - // - pPacket->pBuffer += DataLength; - pPacket->ValidBytes -= DataLength; - DEBUG (( DEBUG_RX, - "0x%08x: Port account for 0x%08x bytes\r\n", - pPort, - DataLength )); - - // - // Determine if the entire packet was consumed - // - if (( 0 == pPacket->ValidBytes ) - || ( SOCK_STREAM != pPort->pSocket->Type )) { - // - // All done with this packet - // Account for any discarded data - // - *pSkipBytes = pPacket->ValidBytes; - } - else - { - // - // More data to consume later - // - *pbConsumePacket = FALSE; - } - } - - // - // Return the data length and the buffer address - // - *pDataLength = DataLength; - DBG_EXIT_HEX ( pBuffer ); - return pBuffer; -} - - -/** - Get the remote socket address. - - This routine returns the address of the remote connection point - associated with the SOCK_STREAM or SOCK_SEQPACKET socket. - - This routine is called by ::EslSocketGetPeerAddress to detemine - the TCPv4 address and por number associated with the network adapter. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [out] pAddress Network address to receive the remote system address - -**/ -VOID -EslTcp4RemoteAddressGet ( - IN ESL_PORT * pPort, - OUT struct sockaddr * pAddress - ) -{ - struct sockaddr_in * pRemoteAddress; - ESL_TCP4_CONTEXT * pTcp4; - - DBG_ENTER ( ); - - // - // Return the remote address - // - pTcp4 = &pPort->Context.Tcp4; - pRemoteAddress = (struct sockaddr_in *)pAddress; - pRemoteAddress->sin_family = AF_INET; - pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort ); - CopyMem ( &pRemoteAddress->sin_addr, - &pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0], - sizeof ( pRemoteAddress->sin_addr )); - - DBG_EXIT ( ); -} - - -/** - Set the remote address - - This routine sets the remote address in the port. - - This routine is called by ::EslSocketConnect to specify the - remote network address. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [in] pSockAddr Network address of the remote system. - - @param [in] SockAddrLength Length in bytes of the network address. - - @retval EFI_SUCCESS The operation was successful - - **/ -EFI_STATUS -EslTcp4RemoteAddressSet ( - IN ESL_PORT * pPort, - IN CONST struct sockaddr * pSockAddr, - IN socklen_t SockAddrLength - ) -{ - CONST struct sockaddr_in * pRemoteAddress; - ESL_TCP4_CONTEXT * pTcp4; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Set the remote address - // - pTcp4 = &pPort->Context.Tcp4; - pRemoteAddress = (struct sockaddr_in *)pSockAddr; - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr ); - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 ); - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 ); - pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 ); - pTcp4->ConfigData.AccessPoint.RemotePort = SwapBytes16 ( pRemoteAddress->sin_port ); - Status = EFI_SUCCESS; - if ( INADDR_BROADCAST == pRemoteAddress->sin_addr.s_addr ) { - DEBUG (( DEBUG_CONNECT, - "ERROR - Invalid remote address\r\n" )); - Status = EFI_INVALID_PARAMETER; - pPort->pSocket->errno = EAFNOSUPPORT; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the receive completion - - This routine queues the data in FIFO order in either the urgent - or normal data queues depending upon the type of data received. - See the \ref ReceiveEngine section. - - This routine is called by the TCPv4 driver when some data is - received. - - Buffer the data that was just received. - - @param [in] Event The receive completion event - - @param [in] pIo Address of an ::ESL_IO_MGMT structure - -**/ -VOID -EslTcp4RxComplete ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ) -{ - BOOLEAN bUrgent; - size_t LengthInBytes; - ESL_PACKET * pPacket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Get the operation status. - // - Status = pIo->Token.Tcp4Rx.CompletionToken.Status; - - // - // +--------------------+ +---------------------------+ - // | ESL_IO_MGMT | | ESL_PACKET | - // | | | | - // | +---------------+ +-----------------------+ | - // | | Token | | EFI_TCP4_RECEIVE_DATA | | - // | | RxData --> | | | - // | | | +-----------------------+---+ - // | | Event | | Data Buffer | - // +----+---------------+ | | - // | | - // +---------------------------+ - // - // - // Duplicate the buffer address and length for use by the - // buffer handling code in EslTcp4Receive. These fields are - // used when a partial read is done of the data from the - // packet. - // - pPacket = pIo->pPacket; - pPacket->pBuffer = pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer; - LengthInBytes = pPacket->Op.Tcp4Rx.RxData.DataLength; - pPacket->ValidBytes = LengthInBytes; - - // - // Get the data type so that it may be linked to the - // correct receive buffer list on the ESL_SOCKET structure - // - bUrgent = pPacket->Op.Tcp4Rx.RxData.UrgentFlag; - - // - // Complete this request - // - EslSocketRxComplete ( pIo, Status, LengthInBytes, bUrgent ); - DBG_EXIT ( ); -} - - -/** - Start a receive operation - - This routine posts a receive buffer to the TCPv4 driver. - See the \ref ReceiveEngine section. - - This support routine is called by EslSocketRxStart. - - @param [in] pPort Address of an ::ESL_PORT structure. - @param [in] pIo Address of an ::ESL_IO_MGMT structure. - - **/ -VOID -EslTcp4RxStart ( - IN ESL_PORT * pPort, - IN ESL_IO_MGMT * pIo - ) -{ - ESL_PACKET * pPacket; - - DBG_ENTER ( ); - - // - // Initialize the buffer for receive - // - pPacket = pIo->pPacket; - pIo->Token.Tcp4Rx.Packet.RxData = &pPacket->Op.Tcp4Rx.RxData; - pPacket->Op.Tcp4Rx.RxData.DataLength = sizeof ( pPacket->Op.Tcp4Rx.Buffer ); - pPacket->Op.Tcp4Rx.RxData.FragmentCount = 1; - pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentLength = pPacket->Op.Tcp4Rx.RxData.DataLength; - pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Tcp4Rx.Buffer[0]; - - DBG_EXIT ( ); -} - - -/** - Determine if the socket is configured. - - This routine uses the flag ESL_SOCKET::bConfigured to determine - if the network layer's configuration routine has been called. - - This routine is called by EslSocketIsConfigured to verify - that the socket has been configured. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @retval EFI_SUCCESS - The port is connected - @retval EFI_NOT_STARTED - The port is not connected - - **/ - EFI_STATUS - EslTcp4SocketIsConfigured ( - IN ESL_SOCKET * pSocket - ) -{ - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Determine the socket configuration status - // - Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED; - - // - // Return the port connected state. - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Buffer data for transmission over a network connection. - - This routine buffers data for the transmit engine in one of two - queues, one for urgent (out-of-band) data and the other for normal - data. The urgent data is provided to TCP as soon as it is available, - allowing the TCP layer to schedule transmission of the urgent data - between packets of normal data. - - This routine is called by ::EslSocketTransmit to buffer - data for transmission. When the \ref TransmitEngine has resources, - this routine will start the transmission of the next buffer on - the network connection. - - Transmission errors are returned during the next transmission or - during the close operation. Only buffering errors are returned - during the current transmission attempt. - - @param [in] pSocket Address of an ::ESL_SOCKET structure - - @param [in] Flags Message control flags - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @param [in] pAddress Network address of the remote system address - - @param [in] AddressLength Length of the remote network address structure - - @retval EFI_SUCCESS - Socket data successfully buffered - - **/ -EFI_STATUS -EslTcp4TxBuffer ( - IN ESL_SOCKET * pSocket, - IN int Flags, - IN size_t BufferLength, - IN CONST UINT8 * pBuffer, - OUT size_t * pDataLength, - IN const struct sockaddr * pAddress, - IN socklen_t AddressLength - ) -{ - BOOLEAN bUrgent; - BOOLEAN bUrgentQueue; - ESL_PACKET * pPacket; - ESL_IO_MGMT ** ppActive; - ESL_IO_MGMT ** ppFree; - ESL_PORT * pPort; - ESL_PACKET ** ppQueueHead; - ESL_PACKET ** ppQueueTail; - ESL_PACKET * pPreviousPacket; - size_t * pTxBytes; - EFI_TCP4_TRANSMIT_DATA * pTxData; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume failure - // - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTCONN; - *pDataLength = 0; - - // - // Verify that the socket is connected - // - if ( SOCKET_STATE_CONNECTED == pSocket->State ) { - // - // Locate the port - // - pPort = pSocket->pPortList; - if ( NULL != pPort ) { - // - // Determine the queue head - // - bUrgent = (BOOLEAN)( 0 != ( Flags & MSG_OOB )); - bUrgentQueue = bUrgent - && ( !pSocket->bOobInLine ) - && pSocket->pApi->bOobSupported; - if ( bUrgentQueue ) { - ppQueueHead = &pSocket->pTxOobPacketListHead; - ppQueueTail = &pSocket->pTxOobPacketListTail; - ppActive = &pPort->pTxOobActive; - ppFree = &pPort->pTxOobFree; - pTxBytes = &pSocket->TxOobBytes; - } - else { - ppQueueHead = &pSocket->pTxPacketListHead; - ppQueueTail = &pSocket->pTxPacketListTail; - ppActive = &pPort->pTxActive; - ppFree = &pPort->pTxFree; - pTxBytes = &pSocket->TxBytes; - } - - // - // Verify that there is enough room to buffer another - // transmit operation - // - if ( pSocket->MaxTxBuf > *pTxBytes ) { - if ( pPort->bTxFlowControl ) { - DEBUG (( DEBUG_TX, - "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\r\n0x%08x: pPort, TX flow control released, Max bytes: %d > %d bufferred bytes\r\n", - pPort, - pSocket->MaxTxBuf, - *pTxBytes )); - pPort->bTxFlowControl = FALSE; - } - - // - // Attempt to allocate the packet - // - Status = EslSocketPacketAllocate ( &pPacket, - sizeof ( pPacket->Op.Tcp4Tx ) - - sizeof ( pPacket->Op.Tcp4Tx.Buffer ) - + BufferLength, - 0, - DEBUG_TX ); - if ( !EFI_ERROR ( Status )) { - // - // Initialize the transmit operation - // - pTxData = &pPacket->Op.Tcp4Tx.TxData; - pTxData->Push = TRUE || bUrgent; - pTxData->Urgent = bUrgent; - pTxData->DataLength = (UINT32) BufferLength; - pTxData->FragmentCount = 1; - pTxData->FragmentTable[0].FragmentLength = (UINT32) BufferLength; - pTxData->FragmentTable[0].FragmentBuffer = &pPacket->Op.Tcp4Tx.Buffer[0]; - - // - // Copy the data into the buffer - // - CopyMem ( &pPacket->Op.Tcp4Tx.Buffer[0], - pBuffer, - BufferLength ); - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Stop transmission after an error - // - if ( !EFI_ERROR ( pSocket->TxError )) { - // - // Display the request - // - DEBUG (( DEBUG_TX, - "Send %d %s bytes from 0x%08x\r\n", - BufferLength, - bUrgent ? L"urgent" : L"normal", - pBuffer )); - - // - // Queue the data for transmission - // - pPacket->pNext = NULL; - pPreviousPacket = *ppQueueTail; - if ( NULL == pPreviousPacket ) { - *ppQueueHead = pPacket; - } - else { - pPreviousPacket->pNext = pPacket; - } - *ppQueueTail = pPacket; - DEBUG (( DEBUG_TX, - "0x%08x: Packet on %s transmit list\r\n", - pPacket, - bUrgentQueue ? L"urgent" : L"normal" )); - - // - // Account for the buffered data - // - *pTxBytes += BufferLength; - *pDataLength = BufferLength; - - // - // Start the transmit engine if it is idle - // - if ( NULL != *ppFree ) { - EslSocketTxStart ( pPort, - ppQueueHead, - ppQueueTail, - ppActive, - ppFree ); - } - } - else { - // - // Previous transmit error - // Stop transmission - // - Status = pSocket->TxError; - pSocket->errno = EIO; - - // - // Free the packet - // - EslSocketPacketFree ( pPacket, DEBUG_TX ); - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - else { - // - // Packet allocation failed - // - pSocket->errno = ENOMEM; - } - } - else { - if ( !pPort->bTxFlowControl ) { - DEBUG (( DEBUG_TX, - "0x%08x: pPort, TX flow control applied, Max bytes %d <= %d bufferred bytes\r\nTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\r\n", - pPort, - pSocket->MaxTxBuf, - *pTxBytes )); - pPort->bTxFlowControl = TRUE; - } - // - // Not enough buffer space available - // - pSocket->errno = EAGAIN; - Status = EFI_NOT_READY; - } - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the normal data transmit completion - - This routine use ::EslSocketTxComplete to perform the transmit - completion processing for normal data. - - This routine is called by the TCPv4 network layer when a - normal data transmit request completes. - - @param [in] Event The normal transmit completion event - - @param [in] pIo The ESL_IO_MGMT structure address - -**/ -VOID -EslTcp4TxComplete ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ) -{ - UINT32 LengthInBytes; - ESL_PACKET * pPacket; - ESL_PORT * pPort; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the active transmit packet - // - pPacket = pIo->pPacket; - pPort = pIo->pPort; - pSocket = pPort->pSocket; - - // - // Get the transmit length and status - // - LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength; - pSocket->TxBytes -= LengthInBytes; - Status = pIo->Token.Tcp4Tx.CompletionToken.Status; - - // - // Complete the transmit operation - // - EslSocketTxComplete ( pIo, - LengthInBytes, - Status, - "Normal ", - &pSocket->pTxPacketListHead, - &pSocket->pTxPacketListTail, - &pPort->pTxActive, - &pPort->pTxFree ); - DBG_EXIT ( ); -} - - -/** - Process the urgent data transmit completion - - This routine use ::EslSocketTxComplete to perform the transmit - completion processing for urgent data. - - This routine is called by the TCPv4 network layer when a - urgent data transmit request completes. - - @param [in] Event The urgent transmit completion event - - @param [in] pIo The ESL_IO_MGMT structure address - -**/ -VOID -EslTcp4TxOobComplete ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ) -{ - UINT32 LengthInBytes; - ESL_PACKET * pPacket; - ESL_PORT * pPort; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the active transmit packet - // - pPacket = pIo->pPacket; - pPort = pIo->pPort; - pSocket = pPort->pSocket; - - // - // Get the transmit length and status - // - LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength; - pSocket->TxOobBytes -= LengthInBytes; - Status = pIo->Token.Tcp4Tx.CompletionToken.Status; - - // - // Complete the transmit operation - // - EslSocketTxComplete ( pIo, - LengthInBytes, - Status, - "Urgent ", - &pSocket->pTxOobPacketListHead, - &pSocket->pTxOobPacketListTail, - &pPort->pTxOobActive, - &pPort->pTxOobFree ); - DBG_EXIT ( ); -} - - -/** - Verify the adapter's IP address - - This support routine is called by EslSocketBindTest. - - @param [in] pPort Address of an ::ESL_PORT structure. - @param [in] pConfigData Address of the configuration data - - @retval EFI_SUCCESS - The IP address is valid - @retval EFI_NOT_STARTED - The IP address is invalid - - **/ -EFI_STATUS -EslTcp4VerifyLocalIpAddress ( - IN ESL_PORT * pPort, - IN EFI_TCP4_CONFIG_DATA * pConfigData - ) -{ - UINTN DataSize; - EFI_TCP4_ACCESS_POINT * pAccess; - EFI_IP4_CONFIG2_INTERFACE_INFO * pIfInfo; - EFI_IP4_CONFIG2_PROTOCOL * pIpConfig2Protocol; - ESL_SERVICE * pService; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Use break instead of goto - // - pIfInfo = NULL; - for ( ; ; ) { - // - // Determine if the IP address is specified - // - pAccess = &pConfigData->AccessPoint; - DEBUG (( DEBUG_BIND, - "UseDefaultAddress: %s\r\n", - pAccess->UseDefaultAddress ? L"TRUE" : L"FALSE" )); - DEBUG (( DEBUG_BIND, - "Requested IP address: %d.%d.%d.%d\r\n", - pAccess->StationAddress.Addr [ 0 ], - pAccess->StationAddress.Addr [ 1 ], - pAccess->StationAddress.Addr [ 2 ], - pAccess->StationAddress.Addr [ 3 ])); - if ( pAccess->UseDefaultAddress - || (( 0 == pAccess->StationAddress.Addr [ 0 ]) - && ( 0 == pAccess->StationAddress.Addr [ 1 ]) - && ( 0 == pAccess->StationAddress.Addr [ 2 ]) - && ( 0 == pAccess->StationAddress.Addr [ 3 ]))) - { - Status = EFI_SUCCESS; - break; - } - - // - // Open the configuration protocol - // - pService = pPort->pService; - Status = gBS->OpenProtocol ( - pService->Controller, - &gEfiIp4Config2ProtocolGuid, - (VOID **)&pIpConfig2Protocol, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR, - "ERROR - IP Configuration Protocol not available, Status: %r\r\n", - Status )); - break; - } - - // - // Get the interface information size. - // - DataSize = 0; - Status = pIpConfig2Protocol->GetData ( - pIpConfig2Protocol, - Ip4Config2DataTypeInterfaceInfo, - &DataSize, - NULL - ); - if ( EFI_BUFFER_TOO_SMALL != Status ) { - DEBUG (( DEBUG_ERROR, - "ERROR - Failed to get the interface information size, Status: %r\r\n", - Status )); - break; - } - - // - // Allocate the interface information buffer - // - pIfInfo = AllocatePool ( DataSize ); - if ( NULL == pIfInfo ) { - DEBUG (( DEBUG_ERROR, - "ERROR - Not enough memory to allocate the interface information buffer!\r\n" )); - Status = EFI_OUT_OF_RESOURCES; - break; - } - - // - // Get the interface info. - // - Status = pIpConfig2Protocol->GetData ( - pIpConfig2Protocol, - Ip4Config2DataTypeInterfaceInfo, - &DataSize, - pIfInfo - ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR, - "ERROR - Failed to return the interface info, Status: %r\r\n", - Status )); - break; - } - - // - // Display the current configuration - // - DEBUG (( DEBUG_BIND, - "Actual adapter IP address: %d.%d.%d.%d\r\n", - pIfInfo->StationAddress.Addr [ 0 ], - pIfInfo->StationAddress.Addr [ 1 ], - pIfInfo->StationAddress.Addr [ 2 ], - pIfInfo->StationAddress.Addr [ 3 ])); - - // - // Assume the port is not configured - // - Status = EFI_SUCCESS; - if (( pAccess->StationAddress.Addr [ 0 ] == pIfInfo->StationAddress.Addr [ 0 ]) - && ( pAccess->StationAddress.Addr [ 1 ] == pIfInfo->StationAddress.Addr [ 1 ]) - && ( pAccess->StationAddress.Addr [ 2 ] == pIfInfo->StationAddress.Addr [ 2 ]) - && ( pAccess->StationAddress.Addr [ 3 ] == pIfInfo->StationAddress.Addr [ 3 ])) { - break; - } - - // - // The IP address did not match - // - Status = EFI_NOT_STARTED; - break; - } - - // - // Free the buffer if necessary - // - if ( NULL != pIfInfo ) { - FreePool ( pIfInfo ); - } - - // - // Return the IP address status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Interface between the socket layer and the network specific - code that supports SOCK_STREAM and SOCK_SEQPACKET sockets - over TCPv4. -**/ -CONST ESL_PROTOCOL_API cEslTcp4Api = { - "TCPv4", - IPPROTO_TCP, - OFFSET_OF ( ESL_PORT, Context.Tcp4.ConfigData ), - OFFSET_OF ( ESL_LAYER, pTcp4List ), - OFFSET_OF ( struct sockaddr_in, sin_zero ), - sizeof ( struct sockaddr_in ), - AF_INET, - sizeof (((ESL_PACKET *)0 )->Op.Tcp4Rx ), - OFFSET_OF ( ESL_PACKET, Op.Tcp4Rx.Buffer ) - OFFSET_OF ( ESL_PACKET, Op ), - OFFSET_OF ( ESL_IO_MGMT, Token.Tcp4Rx.Packet.RxData ), - TRUE, - EADDRINUSE, - EslTcp4Accept, - EslTcp4ConnectPoll, - EslTcp4ConnectStart, - EslTcp4SocketIsConfigured, - EslTcp4LocalAddressGet, - EslTcp4LocalAddressSet, - EslTcp4Listen, - NULL, // OptionGet - NULL, // OptionSet - EslTcp4PacketFree, - EslTcp4PortAllocate, - EslTcp4PortClose, - EslTcp4PortCloseOp, - FALSE, - EslTcp4Receive, - EslTcp4RemoteAddressGet, - EslTcp4RemoteAddressSet, - EslTcp4RxComplete, - EslTcp4RxStart, - EslTcp4TxBuffer, - EslTcp4TxComplete, - EslTcp4TxOobComplete, - (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslTcp4VerifyLocalIpAddress -}; diff --git a/StdLib/EfiSocketLib/Tcp6.c b/StdLib/EfiSocketLib/Tcp6.c deleted file mode 100644 index 0f6d2d6ac9..0000000000 --- a/StdLib/EfiSocketLib/Tcp6.c +++ /dev/null @@ -1,2596 +0,0 @@ -/** @file - Implement the TCP6 driver support for the socket layer. - - Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.
- This program and the accompanying materials are licensed and made available - under the terms and conditions of the BSD License which accompanies this - distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php. - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - - - \section ConnectionManagement Connection Management - - The ::EslTcp6Listen routine initially places the SOCK_STREAM or - SOCK_SEQPACKET socket into a listen state. When a remote machine - makes a connection to the socket, the TCPv6 network layer calls - ::EslTcp6ListenComplete to complete the connection processing. - EslTcp6ListenComplete manages the connections by placing them in - FIFO order in a queue to be serviced by the application. When the - number of connections exceeds the backlog (ESL_SOCKET::MaxFifoDepth), - the new connection is closed. Eventually, the application indirectly - calls ::EslTcp6Accept to remove the next connection from the queue - and get the associated socket. - -**/ - -#include "Socket.h" - - -/** - Attempt to connect to a remote TCP port - - This routine starts the connection processing for a SOCK_STREAM - or SOCK_SEQPAKCET socket using the TCPv6 network layer. It - configures the local TCPv6 connection point and then attempts to - connect to a remote system. Upon completion, the - ::EslTcp6ConnectComplete routine gets called with the connection - status. - - This routine is called by ::EslSocketConnect to initiate the TCPv6 - network specific connect operations. The connection processing is - initiated by this routine and finished by ::EslTcp6ConnectComplete. - This pair of routines walks through the list of local TCPv6 - connection points until a connection to the remote system is - made. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @retval EFI_SUCCESS The connection was successfully established. - @retval EFI_NOT_READY The connection is in progress, call this routine again. - @retval Others The connection attempt failed. - - **/ -EFI_STATUS -EslTcp6ConnectStart ( - IN ESL_SOCKET * pSocket - ); - - -/** - Process the connection attempt - - A system has initiated a connection attempt with a socket in the - listen state. Attempt to complete the connection. - - The TCPv6 layer calls this routine when a connection is made to - the socket in the listen state. See the - \ref ConnectionManagement section. - - @param [in] Event The listen completion event - - @param [in] pPort Address of an ::ESL_PORT structure. - -**/ -VOID -EslTcp6ListenComplete ( - IN EFI_EVENT Event, - IN ESL_PORT * pPort - ); - - -/** - Accept a network connection. - - This routine waits for a network connection to the socket and - returns the remote network address to the caller if requested. - - This routine is called by ::EslSocketAccept to handle the TCPv6 protocol - specific accept operations for SOCK_STREAM and SOCK_SEQPACKET sockets. - See the \ref ConnectionManagement section. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @param [in] pSockAddr Address of a buffer to receive the remote - network address. - - @param [in, out] pSockAddrLength Length in bytes of the address buffer. - On output specifies the length of the - remote network address. - - @retval EFI_SUCCESS Remote address is available - @retval Others Remote address not available - - **/ -EFI_STATUS -EslTcp6Accept ( - IN ESL_SOCKET * pSocket, - IN struct sockaddr * pSockAddr, - IN OUT socklen_t * pSockAddrLength - ) -{ - ESL_PORT * pPort; - struct sockaddr_in6 * pRemoteAddress; - ESL_TCP6_CONTEXT * pTcp6; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Validate the socket length - // - pRemoteAddress = (struct sockaddr_in6 *) pSockAddr; - if (( NULL == pSockAddrLength ) - || ( sizeof ( *pRemoteAddress ) > *pSockAddrLength )) { - // - // Invalid socket address - // - Status = EFI_INVALID_PARAMETER; - pSocket->errno = EINVAL; - DEBUG (( DEBUG_ACCEPT, - "ERROR - Invalid address length\r\n" )); - } - else { - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Locate the address context - // - pPort = pSocket->pPortList; - pTcp6 = &pPort->Context.Tcp6; - - // - // Fill-in the remote address structure - // - ZeroMem ( pRemoteAddress, sizeof ( *pRemoteAddress )); - pRemoteAddress->sin6_len = sizeof ( *pRemoteAddress ); - pRemoteAddress->sin6_family = AF_INET6; - pRemoteAddress->sin6_port = SwapBytes16 ( pTcp6->ConfigData.AccessPoint.RemotePort ); - CopyMem ( &pRemoteAddress->sin6_addr.__u6_addr.__u6_addr8 [ 0 ], - &pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0], - sizeof ( pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr )); - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the remote connection completion event. - - This routine handles the completion of a connection attempt. It - releases the port (TCPv6 adapter connection) in the case of an - error and start a connection attempt on the next port. If the - connection attempt was successful then this routine releases all - of the other ports. - - This routine is called by the TCPv6 layer when a connect request - completes. It sets the ESL_SOCKET::bConnected flag to notify the - ::EslTcp6ConnectComplete routine that the connection is available. - The flag is set when the connection is established or no more ports - exist in the list. The connection status is passed via - ESL_SOCKET::ConnectStatus. - - @param [in] Event The connect completion event - - @param [in] pPort Address of an ::ESL_PORT structure. - -**/ -VOID -EslTcp6ConnectComplete ( - IN EFI_EVENT Event, - IN ESL_PORT * pPort - ) -{ - BOOLEAN bRemoveFirstPort; - BOOLEAN bRemovePorts; - ESL_PORT * pNextPort; - ESL_SOCKET * pSocket; - ESL_TCP6_CONTEXT * pTcp6; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the TCP context - // - pSocket = pPort->pSocket; - pTcp6 = &pPort->Context.Tcp6; - - // - // Get the connection status - // - bRemoveFirstPort = FALSE; - bRemovePorts = FALSE; - Status = pTcp6->ConnectToken.CompletionToken.Status; - pSocket->ConnectStatus = Status; - if ( !EFI_ERROR ( Status )) { - // - // The connection was successful - // - DEBUG (( DEBUG_CONNECT, - "0x%08x: Port connected to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", - pPort, - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[1], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[2], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[3], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[4], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[5], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[6], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[7], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[8], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[9], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[10], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[11], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[12], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[13], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[14], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[15], - pTcp6->ConfigData.AccessPoint.RemotePort )); - - // - // Start the receive operations - // - pSocket->bConfigured = TRUE; - pSocket->State = SOCKET_STATE_CONNECTED; - EslSocketRxStart ( pPort ); - - // - // Remove the rest of the ports - // - bRemovePorts = TRUE; - } - else { - // - // The connection failed - // - if ( pPort->bConfigured ) { - DEBUG (( DEBUG_CONNECT, - "0x%08x: Port connection to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d failed, Status: %r\r\n", - pPort, - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[1], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[2], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[3], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[4], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[5], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[6], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[7], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[8], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[9], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[10], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[11], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[12], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[13], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[14], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[15], - pTcp6->ConfigData.AccessPoint.RemotePort, - Status )); - } - - // - // Close the current port - // - Status = EslSocketPortClose ( pPort ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_CONNECT, - "0x%08x: Port closed\r\n", - pPort )); - } - else { - DEBUG (( DEBUG_CONNECT, - "ERROR - Failed to close port 0x%08x, Status: %r\r\n", - pPort, - Status )); - } - - // - // Try to connect using the next port - // - Status = EslTcp6ConnectStart ( pSocket ); - if ( EFI_NOT_READY != Status ) { - bRemoveFirstPort = TRUE; - } - } - - // - // Remove the ports if necessary - // - if ( bRemoveFirstPort || bRemovePorts ) { - // - // Remove the first port if necessary - // - pPort = pSocket->pPortList; - if (( !bRemoveFirstPort ) && ( NULL != pPort )) { - pPort = pPort->pLinkSocket; - } - - // - // Remove the rest of the list - // - while ( NULL != pPort ) { - pNextPort = pPort->pLinkSocket; - EslSocketPortClose ( pPort ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_CONNECT, - "0x%08x: Port closed\r\n", - pPort )); - } - else { - DEBUG (( DEBUG_CONNECT, - "ERROR - Failed to close port 0x%08x, Status: %r\r\n", - pPort, - Status )); - } - pPort = pNextPort; - } - - // - // Notify the poll routine - // - pSocket->bConnected = TRUE; - } - - DBG_EXIT ( ); -} - - -/** - Poll for completion of the connection attempt. - - This routine polls the ESL_SOCKET::bConnected flag to determine - when the connection attempt is complete. - - This routine is called from ::EslSocketConnect to determine when - the connection is complete. The ESL_SOCKET::bConnected flag is - set by ::EslTcp6ConnectComplete when the TCPv6 layer establishes - a connection or runs out of local network adapters. This routine - gets the connection status from ESL_SOCKET::ConnectStatus. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @retval EFI_SUCCESS The connection was successfully established. - @retval EFI_NOT_READY The connection is in progress, call this routine again. - @retval Others The connection attempt failed. - - **/ -EFI_STATUS -EslTcp6ConnectPoll ( - IN ESL_SOCKET * pSocket - ) -{ - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Determine if the connection is complete - // - if ( !pSocket->bConnected ) { - // - // Not connected - // - pSocket->errno = EAGAIN; - Status = EFI_NOT_READY; - } - else { - // - // The connection processing is complete - // - pSocket->bConnected = FALSE; - - // - // Translate the connection status - // - Status = pSocket->ConnectStatus; - switch ( Status ) { - default: - case EFI_DEVICE_ERROR: - pSocket->errno = EIO; - break; - - case EFI_ABORTED: - pSocket->errno = ECONNABORTED; - break; - - case EFI_ACCESS_DENIED: - pSocket->errno = EACCES; - break; - - case EFI_CONNECTION_RESET: - pSocket->errno = ECONNRESET; - break; - - case EFI_INVALID_PARAMETER: - pSocket->errno = EADDRNOTAVAIL; - break; - - case EFI_HOST_UNREACHABLE: - case EFI_NO_RESPONSE: - pSocket->errno = EHOSTUNREACH; - break; - - case EFI_NO_MAPPING: - pSocket->errno = EAFNOSUPPORT; - break; - - case EFI_NO_MEDIA: - case EFI_NETWORK_UNREACHABLE: - pSocket->errno = ENETDOWN; - break; - - case EFI_OUT_OF_RESOURCES: - pSocket->errno = ENOBUFS; - break; - - case EFI_PORT_UNREACHABLE: - case EFI_PROTOCOL_UNREACHABLE: - case EFI_CONNECTION_REFUSED: - pSocket->errno = ECONNREFUSED; - break; - - case EFI_SUCCESS: - pSocket->errno = 0; - break; - - case EFI_TIMEOUT: - pSocket->errno = ETIMEDOUT; - break; - - case EFI_UNSUPPORTED: - pSocket->errno = EOPNOTSUPP; - break; - } - - // - // Display the translation - // - DEBUG (( DEBUG_CONNECT, - "ERROR - errno: %d, Status: %r\r\n", - pSocket->errno, - Status )); - } - - // - // Return the initialization status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Attempt to connect to a remote TCP port - - This routine starts the connection processing for a SOCK_STREAM - or SOCK_SEQPAKCET socket using the TCPv6 network layer. It - configures the local TCPv6 connection point and then attempts to - connect to a remote system. Upon completion, the - ::EslTcp6ConnectComplete routine gets called with the connection - status. - - This routine is called by ::EslSocketConnect to initiate the TCPv6 - network specific connect operations. The connection processing is - initiated by this routine and finished by ::EslTcp6ConnectComplete. - This pair of routines walks through the list of local TCPv6 - connection points until a connection to the remote system is - made. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @retval EFI_SUCCESS The connection was successfully established. - @retval EFI_NOT_READY The connection is in progress, call this routine again. - @retval Others The connection attempt failed. - - **/ -EFI_STATUS -EslTcp6ConnectStart ( - IN ESL_SOCKET * pSocket - ) -{ - ESL_PORT * pPort; - ESL_TCP6_CONTEXT * pTcp6; - EFI_TCP6_PROTOCOL * pTcp6Protocol; - EFI_SIMPLE_NETWORK_MODE SnpModeData; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Determine if any more local adapters are available - // - pPort = pSocket->pPortList; - if ( NULL != pPort ) { - // - // Configure the port - // - pTcp6 = &pPort->Context.Tcp6; - pTcp6->ConfigData.AccessPoint.ActiveFlag = TRUE; - pTcp6->ConfigData.TrafficClass = 0; - pTcp6->ConfigData.HopLimit = 255; - pTcp6Protocol = pPort->pProtocol.TCPv6; - Status = pTcp6Protocol->Configure ( pTcp6Protocol, - &pTcp6->ConfigData ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_CONNECT, - "ERROR - Failed to configure the Tcp6 port, Status: %r\r\n", - Status )); - } - else { - DEBUG (( DEBUG_CONNECT, - "0x%08x: Port configured\r\n", - pPort )); - pPort->bConfigured = TRUE; - - // - // Verify the port connection - // - Status = pTcp6Protocol->GetModeData ( pTcp6Protocol, - NULL, - NULL, - NULL, - NULL, - &SnpModeData ); - if ( !EFI_ERROR ( Status )) { - if ( SnpModeData.MediaPresentSupported - && ( !SnpModeData.MediaPresent )) { - // - // Port is not connected to the network - // - Status = EFI_NO_MEDIA; - } - else { - // - // Attempt the connection to the remote system - // - Status = pTcp6Protocol->Connect ( pTcp6Protocol, - &pTcp6->ConnectToken ); - } - } - if ( EFI_ERROR ( Status )) { - // - // Connection error - // - DEBUG (( DEBUG_CONNECT, - "ERROR - Port 0x%08x not connected, Status: %r\r\n", - pPort, - Status )); - } - } - if ( !EFI_ERROR ( Status )) { - // - // Connection in progress - // - pSocket->errno = EINPROGRESS; - DEBUG (( DEBUG_CONNECT, - "0x%08x: Port attempting connection to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", - pPort, - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[1], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[2], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[3], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[4], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[5], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[6], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[7], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[8], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[9], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[10], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[11], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[12], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[13], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[14], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[15], - pTcp6->ConfigData.AccessPoint.RemotePort )); - } - else { - // - // Error return path is through EslTcp6ConnectComplete to - // enable retry on other ports - // - // Status to errno translation gets done in EslTcp4ConnectPoll - // - pTcp6->ConnectToken.CompletionToken.Status = Status; - - // - // Continue with the next port - // - gBS->CheckEvent ( pTcp6->ConnectToken.CompletionToken.Event ); - gBS->SignalEvent ( pTcp6->ConnectToken.CompletionToken.Event ); - } - Status = EFI_NOT_READY; - } - else { - // - // No more local adapters available - // - pSocket->errno = ENETUNREACH; - Status = EFI_NO_RESPONSE; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Establish the known port to listen for network connections. - - This routine places the port into a state that enables connection - attempts. - - This routine is called by ::EslSocketListen to handle the network - specifics of the listen operation for SOCK_STREAM and SOCK_SEQPACKET - sockets. See the \ref ConnectionManagement section. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @retval EFI_SUCCESS - Socket successfully created - @retval Other - Failed to enable the socket for listen - -**/ -EFI_STATUS -EslTcp6Listen ( - IN ESL_SOCKET * pSocket - ) -{ - ESL_PORT * pNextPort; - ESL_PORT * pPort; - ESL_TCP6_CONTEXT * pTcp6; - EFI_TCP6_PROTOCOL * pTcp6Protocol; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Verify the socket layer synchronization - // - VERIFY_TPL ( TPL_SOCKETS ); - - // - // Use for/break instead of goto - // - for ( ; ; ) { - // - // Assume no ports are available - // - pSocket->errno = EOPNOTSUPP; - Status = EFI_NOT_READY; - - // - // Walk the list of ports - // - pPort = pSocket->pPortList; - while ( NULL != pPort ) { - // - // Assume success - // - pSocket->errno = 0; - - // - // Use for/break insteak of goto - // - for ( ; ; ) { - // - // Create the listen completion event - // - pTcp6 = &pPort->Context.Tcp6; - Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_SOCKETS, - (EFI_EVENT_NOTIFY)EslTcp6ListenComplete, - pPort, - &pTcp6->ListenToken.CompletionToken.Event ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR | DEBUG_LISTEN, - "ERROR - Failed to create the listen completion event, Status: %r\r\n", - Status )); - pSocket->errno = ENOMEM; - break; - } - DEBUG (( DEBUG_POOL, - "0x%08x: Created listen completion event\r\n", - pTcp6->ListenToken.CompletionToken.Event )); - - // - // Configure the port - // - pTcp6Protocol = pPort->pProtocol.TCPv6; - Status = pTcp6Protocol->Configure ( pTcp6Protocol, - &pTcp6->ConfigData ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_LISTEN, - "ERROR - Failed to configure the Tcp6 port, Status: %r\r\n", - Status )); - switch ( Status ) { - case EFI_ACCESS_DENIED: - pSocket->errno = EACCES; - break; - - default: - case EFI_DEVICE_ERROR: - pSocket->errno = EIO; - break; - - case EFI_INVALID_PARAMETER: - pSocket->errno = EADDRNOTAVAIL; - break; - - case EFI_NO_MAPPING: - pSocket->errno = EAFNOSUPPORT; - break; - - case EFI_OUT_OF_RESOURCES: - pSocket->errno = ENOBUFS; - break; - - case EFI_UNSUPPORTED: - pSocket->errno = EOPNOTSUPP; - break; - } - break; - } - DEBUG (( DEBUG_LISTEN, - "0x%08x: Port configured\r\n", - pPort )); - pPort->bConfigured = TRUE; - - // - // Start the listen operation on the port - // - Status = pTcp6Protocol->Accept ( pTcp6Protocol, - &pTcp6->ListenToken ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_LISTEN, - "ERROR - Failed Tcp6 accept, Status: %r\r\n", - Status )); - switch ( Status ) { - case EFI_ACCESS_DENIED: - pSocket->errno = EACCES; - break; - - default: - case EFI_DEVICE_ERROR: - pSocket->errno = EIO; - break; - - case EFI_INVALID_PARAMETER: - pSocket->errno = EADDRNOTAVAIL; - break; - - case EFI_NOT_STARTED: - pSocket->errno = ENETDOWN; - break; - - case EFI_OUT_OF_RESOURCES: - pSocket->errno = ENOBUFS; - break; - } - break; - } - DEBUG (( DEBUG_LISTEN, - "0x%08x: Listen pending on Port\r\n", - pPort )); - - // - // Listen is pending on this port - // - break; - } - - // - // Get the next port - // - pNextPort = pPort->pLinkSocket; - - // - // Close the port upon error - // - if ( EFI_ERROR ( Status )) { - EslSocketPortCloseStart ( pPort, TRUE, DEBUG_LISTEN ); - } - - // - // Set the next port - // - pPort = pNextPort; - } - - // - // Determine if any ports are in the listen state - // - if ( NULL == pSocket->pPortList ) { - // - // No ports in the listen state - // - pSocket->MaxFifoDepth = 0; - - // - // Return the last error detected - // - break; - } - - // - // Mark the socket as configured - // - pSocket->bConfigured = TRUE; - Status = EFI_SUCCESS; - pSocket->errno = 0; - - // - // All done - // - DEBUG (( DEBUG_LISTEN, - "0x%08x: pSocket - Listen pending on socket\r\n", - pSocket )); - break; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the connection attempt - - A system has initiated a connection attempt with a socket in the - listen state. Attempt to complete the connection. - - The TCPv6 layer calls this routine when a connection is made to - the socket in the listen state. See the - \ref ConnectionManagement section. - - @param [in] Event The listen completion event - - @param [in] pPort Address of an ::ESL_PORT structure. - -**/ -VOID -EslTcp6ListenComplete ( - IN EFI_EVENT Event, - IN ESL_PORT * pPort - ) -{ - EFI_HANDLE ChildHandle; - struct sockaddr_in6 LocalAddress; - EFI_TCP6_CONFIG_DATA * pConfigData; - ESL_PORT * pNewPort; - ESL_SOCKET * pNewSocket; - ESL_SOCKET * pSocket; - ESL_TCP6_CONTEXT * pTcp6; - EFI_TCP6_PROTOCOL * pTcp6Protocol; - EFI_STATUS Status; - EFI_HANDLE TcpPortHandle; - EFI_STATUS TempStatus; - - DBG_ENTER ( ); - VERIFY_AT_TPL ( TPL_SOCKETS ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Determine if this connection fits into the connection FIFO - // - pSocket = pPort->pSocket; - TcpPortHandle = pPort->Context.Tcp6.ListenToken.NewChildHandle; - if (( SOCKET_STATE_LISTENING == pSocket->State ) - && ( pSocket->MaxFifoDepth > pSocket->FifoDepth )) { - // - // Allocate a socket for this connection - // - ChildHandle = NULL; - Status = EslSocketAllocate ( &ChildHandle, - DEBUG_CONNECTION, - &pNewSocket ); - if ( !EFI_ERROR ( Status )) { - // - // Clone the socket parameters - // - pNewSocket->pApi = pSocket->pApi; - pNewSocket->Domain = pSocket->Domain; - pNewSocket->Protocol = pSocket->Protocol; - pNewSocket->Type = pSocket->Type; - - // - // Build the local address - // - pTcp6 = &pPort->Context.Tcp6; - LocalAddress.sin6_len = (uint8_t)pNewSocket->pApi->MinimumAddressLength; - LocalAddress.sin6_family = AF_INET6; - LocalAddress.sin6_port = 0; - CopyMem ( &LocalAddress.sin6_addr.__u6_addr.__u6_addr8 [ 0 ], - &pTcp6->ConfigData.AccessPoint.StationAddress.Addr [ 0 ], - sizeof ( pTcp6->ConfigData.AccessPoint.StationAddress.Addr )); - - // - // Allocate a port for this connection - // Note in this instance Configure may not be called with NULL! - // - Status = EslSocketPortAllocate ( pNewSocket, - pPort->pService, - TcpPortHandle, - (struct sockaddr *)&LocalAddress, - FALSE, - DEBUG_CONNECTION, - &pNewPort ); - if ( !EFI_ERROR ( Status )) { - // - // Restart the listen operation on the port - // - pTcp6Protocol = pPort->pProtocol.TCPv6; - Status = pTcp6Protocol->Accept ( pTcp6Protocol, - &pTcp6->ListenToken ); - - // - // Close the TCP port using SocketClose - // - TcpPortHandle = NULL; - pTcp6 = &pNewPort->Context.Tcp6; - - // - // Check for an accept call error - // - if ( !EFI_ERROR ( Status )) { - // - // Get the port configuration - // - pNewPort->bConfigured = TRUE; - pConfigData = &pTcp6->ConfigData; - pConfigData->ControlOption = &pTcp6->Option; - pTcp6Protocol = pNewPort->pProtocol.TCPv6; - Status = pTcp6Protocol->GetModeData ( pTcp6Protocol, - NULL, - pConfigData, - NULL, - NULL, - NULL ); - if ( !EFI_ERROR ( Status )) { - // - // Add the new socket to the connection FIFO - // - if ( NULL == pSocket->pFifoTail ) { - // - // First connection - // - pSocket->pFifoHead = pNewSocket; - } - else { - // - // Add to end of list. - // - pSocket->pFifoTail->pNextConnection = pNewSocket; - } - pSocket->pFifoTail = pNewSocket; - pSocket->FifoDepth += 1; - - // - // Update the socket state - // - pNewSocket->State = SOCKET_STATE_IN_FIFO; - - // - // Log the connection - // - DEBUG (( DEBUG_CONNECTION | DEBUG_INFO, - "0x%08x: Socket on port [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d connected to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", - pNewSocket, - pConfigData->AccessPoint.StationAddress.Addr[0], - pConfigData->AccessPoint.StationAddress.Addr[1], - pConfigData->AccessPoint.StationAddress.Addr[2], - pConfigData->AccessPoint.StationAddress.Addr[3], - pConfigData->AccessPoint.StationAddress.Addr[4], - pConfigData->AccessPoint.StationAddress.Addr[5], - pConfigData->AccessPoint.StationAddress.Addr[6], - pConfigData->AccessPoint.StationAddress.Addr[7], - pConfigData->AccessPoint.StationAddress.Addr[8], - pConfigData->AccessPoint.StationAddress.Addr[9], - pConfigData->AccessPoint.StationAddress.Addr[10], - pConfigData->AccessPoint.StationAddress.Addr[11], - pConfigData->AccessPoint.StationAddress.Addr[12], - pConfigData->AccessPoint.StationAddress.Addr[13], - pConfigData->AccessPoint.StationAddress.Addr[14], - pConfigData->AccessPoint.StationAddress.Addr[15], - pConfigData->AccessPoint.StationPort, - pConfigData->AccessPoint.RemoteAddress.Addr[0], - pConfigData->AccessPoint.RemoteAddress.Addr[1], - pConfigData->AccessPoint.RemoteAddress.Addr[2], - pConfigData->AccessPoint.RemoteAddress.Addr[3], - pConfigData->AccessPoint.RemoteAddress.Addr[4], - pConfigData->AccessPoint.RemoteAddress.Addr[5], - pConfigData->AccessPoint.RemoteAddress.Addr[6], - pConfigData->AccessPoint.RemoteAddress.Addr[7], - pConfigData->AccessPoint.RemoteAddress.Addr[8], - pConfigData->AccessPoint.RemoteAddress.Addr[9], - pConfigData->AccessPoint.RemoteAddress.Addr[10], - pConfigData->AccessPoint.RemoteAddress.Addr[11], - pConfigData->AccessPoint.RemoteAddress.Addr[12], - pConfigData->AccessPoint.RemoteAddress.Addr[13], - pConfigData->AccessPoint.RemoteAddress.Addr[14], - pConfigData->AccessPoint.RemoteAddress.Addr[15], - pConfigData->AccessPoint.RemotePort )); - DEBUG (( DEBUG_CONNECTION | DEBUG_INFO, - "0x%08x: Listen socket adding socket 0x%08x to FIFO, depth: %d\r\n", - pSocket, - pNewSocket, - pSocket->FifoDepth )); - - // - // Start the receive operation - // - EslSocketRxStart ( pNewPort ); - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_CONNECTION | DEBUG_INFO, - "ERROR - GetModeData failed on port 0x%08x, Status: %r\r\n", - pNewPort, - Status )); - } - } - else { - // - // The listen failed on this port - // - DEBUG (( DEBUG_LISTEN | DEBUG_INFO, - "ERROR - Listen failed on port 0x%08x, Status: %r\r\n", - pPort, - Status )); - - // - // Close the listening port - // - EslSocketPortCloseStart ( pPort, TRUE, DEBUG_LISTEN ); - } - } - - // - // Done with the socket if necessary - // - if ( EFI_ERROR ( Status )) { - TempStatus = EslSocketCloseStart ( &pNewSocket->SocketProtocol, - TRUE, - &pSocket->errno ); - ASSERT ( EFI_SUCCESS == TempStatus ); - } - } - } - else { - DEBUG (( DEBUG_CONNECTION, - "0x%08x: Socket FIFO full, connection refused\r\n", - pSocket )); - - // - // The FIFO is full or the socket is in the wrong state - // - Status = EFI_BUFFER_TOO_SMALL; - } - - // - // Close the connection if necessary - // - if (( EFI_ERROR ( Status )) - && ( NULL == TcpPortHandle )) { - // - // TODO: Finish this code path - // The new connection does not fit into the connection FIFO - // - // Process: - // Call close - // Release the resources - - } - - DBG_EXIT ( ); -} - - -/** - Get the local socket address. - - This routine returns the IPv6 address and TCP port number associated - with the local socket. - - This routine is called by ::EslSocketGetLocalAddress to determine the - network address for the SOCK_STREAM or SOCK_SEQPACKET socket. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [out] pSockAddr Network address to receive the local system address - -**/ -VOID -EslTcp6LocalAddressGet ( - IN ESL_PORT * pPort, - OUT struct sockaddr * pSockAddr - ) -{ - struct sockaddr_in6 * pLocalAddress; - ESL_TCP6_CONTEXT * pTcp6; - - DBG_ENTER ( ); - - // - // Return the local address - // - pTcp6 = &pPort->Context.Tcp6; - pLocalAddress = (struct sockaddr_in6 *)pSockAddr; - pLocalAddress->sin6_family = AF_INET6; - pLocalAddress->sin6_port = SwapBytes16 ( pTcp6->ConfigData.AccessPoint.StationPort ); - CopyMem ( &pLocalAddress->sin6_addr, - &pTcp6->ConfigData.AccessPoint.StationAddress.Addr[0], - sizeof ( pLocalAddress->sin6_addr )); - - DBG_EXIT ( ); -} - - -/** - Set the local port address. - - This routine sets the local port address. - - This support routine is called by ::EslSocketPortAllocate. - - @param [in] pPort Address of an ESL_PORT structure - @param [in] pSockAddr Address of a sockaddr structure that contains the - connection point on the local machine. An IPv6 address - of INADDR_ANY specifies that the connection is made to - all of the network stacks on the platform. Specifying a - specific IPv6 address restricts the connection to the - network stack supporting that address. Specifying zero - for the port causes the network layer to assign a port - number from the dynamic range. Specifying a specific - port number causes the network layer to use that port. - - @param [in] bBindTest TRUE = run bind testing - - @retval EFI_SUCCESS The operation was successful - - **/ -EFI_STATUS -EslTcp6LocalAddressSet ( - IN ESL_PORT * pPort, - IN CONST struct sockaddr * pSockAddr, - IN BOOLEAN bBindTest - ) -{ - EFI_TCP6_ACCESS_POINT * pAccessPoint; - CONST struct sockaddr_in6 * pIpAddress; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Validate the address - // - pIpAddress = (struct sockaddr_in6 *)pSockAddr; -// -// TODO: Fix the following check -// -/* - if ( INADDR_BROADCAST == pIpAddress->sin6_addr.s_addr ) { - // - // The local address must not be the broadcast address - // - Status = EFI_INVALID_PARAMETER; - pPort->pSocket->errno = EADDRNOTAVAIL; - } - else { -*/ -{ - // - // Set the local address - // - pAccessPoint = &pPort->Context.Tcp6.ConfigData.AccessPoint; - CopyMem ( &pAccessPoint->StationAddress.Addr[0], - &pIpAddress->sin6_addr.__u6_addr.__u6_addr8 [ 0 ], - sizeof ( pIpAddress->sin6_addr.__u6_addr.__u6_addr8 [ 0 ])); - - // - // Validate the IP address - // - pAccessPoint->StationPort = 0; - Status = bBindTest ? EslSocketBindTest ( pPort, EADDRNOTAVAIL ) - : EFI_SUCCESS; - if ( !EFI_ERROR ( Status )) { - // - // Set the port number - // - pAccessPoint->StationPort = SwapBytes16 ( pIpAddress->sin6_port ); - pPort->pSocket->bAddressSet = TRUE; - - // - // Display the local address - // - DEBUG (( DEBUG_BIND, - "0x%08x: Port, Local Tcp6 Address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", - pPort, - pAccessPoint->StationAddress.Addr[0], - pAccessPoint->StationAddress.Addr[1], - pAccessPoint->StationAddress.Addr[2], - pAccessPoint->StationAddress.Addr[3], - pAccessPoint->StationAddress.Addr[4], - pAccessPoint->StationAddress.Addr[5], - pAccessPoint->StationAddress.Addr[6], - pAccessPoint->StationAddress.Addr[7], - pAccessPoint->StationAddress.Addr[8], - pAccessPoint->StationAddress.Addr[9], - pAccessPoint->StationAddress.Addr[10], - pAccessPoint->StationAddress.Addr[11], - pAccessPoint->StationAddress.Addr[12], - pAccessPoint->StationAddress.Addr[13], - pAccessPoint->StationAddress.Addr[14], - pAccessPoint->StationAddress.Addr[15], - pAccessPoint->StationPort )); - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Free a receive packet - - This routine performs the network specific operations necessary - to free a receive packet. - - This routine is called by ::EslSocketPortCloseTxDone to free a - receive packet. - - @param [in] pPacket Address of an ::ESL_PACKET structure. - @param [in, out] pRxBytes Address of the count of RX bytes - -**/ -VOID -EslTcp6PacketFree ( - IN ESL_PACKET * pPacket, - IN OUT size_t * pRxBytes - ) -{ - DBG_ENTER ( ); - - // - // Account for the receive bytes - // - *pRxBytes -= pPacket->Op.Tcp6Rx.RxData.DataLength; - DBG_EXIT ( ); -} - - -/** - Initialize the network specific portions of an ::ESL_PORT structure. - - This routine initializes the network specific portions of an - ::ESL_PORT structure for use by the socket. - - This support routine is called by ::EslSocketPortAllocate - to connect the socket with the underlying network adapter - running the TCPv6 protocol. - - @param [in] pPort Address of an ESL_PORT structure - @param [in] DebugFlags Flags for debug messages - - @retval EFI_SUCCESS - Socket successfully created - - **/ -EFI_STATUS -EslTcp6PortAllocate ( - IN ESL_PORT * pPort, - IN UINTN DebugFlags - ) -{ - EFI_TCP6_ACCESS_POINT * pAccessPoint; - ESL_SOCKET * pSocket; - ESL_TCP6_CONTEXT * pTcp6; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Use for/break instead of goto - for ( ; ; ) { - // - // Allocate the close event - // - pSocket = pPort->pSocket; - pTcp6 = &pPort->Context.Tcp6; - Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_SOCKETS, - (EFI_EVENT_NOTIFY)EslSocketPortCloseComplete, - pPort, - &pTcp6->CloseToken.CompletionToken.Event); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to create the close event, Status: %r\r\n", - Status )); - pSocket->errno = ENOMEM; - break; - } - DEBUG (( DEBUG_CLOSE | DEBUG_POOL, - "0x%08x: Created close event\r\n", - pTcp6->CloseToken.CompletionToken.Event )); - - // - // Allocate the connection event - // - Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_SOCKETS, - (EFI_EVENT_NOTIFY)EslTcp6ConnectComplete, - pPort, - &pTcp6->ConnectToken.CompletionToken.Event); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to create the connect event, Status: %r\r\n", - Status )); - pSocket->errno = ENOMEM; - break; - } - DEBUG (( DEBUG_CLOSE | DEBUG_POOL, - "0x%08x: Created connect event\r\n", - pTcp6->ConnectToken.CompletionToken.Event )); - - // - // Initialize the port - // - pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Tcp6Tx.TxData ); - pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Tcp6Tx.CompletionToken.Event ); - pSocket->TxTokenOffset = OFFSET_OF ( EFI_TCP6_IO_TOKEN, Packet.TxData ); - - // - // Save the cancel, receive and transmit addresses - // pPort->pfnRxCancel = NULL; since the UEFI implementation returns EFI_UNSUPPORTED - // - pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.TCPv6->Configure; - pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.TCPv6->Poll; - pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv6->Receive; - pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv6->Transmit; - - // - // Set the configuration flags - // - pAccessPoint = &pPort->Context.Tcp6.ConfigData.AccessPoint; - pAccessPoint->ActiveFlag = FALSE; - pTcp6->ConfigData.TrafficClass = 0; - pTcp6->ConfigData.HopLimit = 255; - break; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Close a Tcp6 port. - - This routine releases the network specific resources allocated by - ::EslTcp6PortAllocate. - - This routine is called by ::EslSocketPortClose. - See the \ref PortCloseStateMachine section. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @retval EFI_SUCCESS The port is closed - @retval other Port close error - -**/ -EFI_STATUS -EslTcp6PortClose ( - IN ESL_PORT * pPort - ) -{ - UINTN DebugFlags; - ESL_TCP6_CONTEXT * pTcp6; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the port in the socket list - // - Status = EFI_SUCCESS; - DebugFlags = pPort->DebugFlags; - pTcp6 = &pPort->Context.Tcp6; - - // - // Done with the connect event - // - if ( NULL != pTcp6->ConnectToken.CompletionToken.Event ) { - Status = gBS->CloseEvent ( pTcp6->ConnectToken.CompletionToken.Event ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DebugFlags | DEBUG_POOL, - "0x%08x: Closed connect event\r\n", - pTcp6->ConnectToken.CompletionToken.Event )); - } - else { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to close the connect event, Status: %r\r\n", - Status )); - ASSERT ( EFI_SUCCESS == Status ); - } - } - - // - // Done with the close event - // - if ( NULL != pTcp6->CloseToken.CompletionToken.Event ) { - Status = gBS->CloseEvent ( pTcp6->CloseToken.CompletionToken.Event ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DebugFlags | DEBUG_POOL, - "0x%08x: Closed close event\r\n", - pTcp6->CloseToken.CompletionToken.Event )); - } - else { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to close the close event, Status: %r\r\n", - Status )); - ASSERT ( EFI_SUCCESS == Status ); - } - } - - // - // Done with the listen completion event - // - if ( NULL != pTcp6->ListenToken.CompletionToken.Event ) { - Status = gBS->CloseEvent ( pTcp6->ListenToken.CompletionToken.Event ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DebugFlags | DEBUG_POOL, - "0x%08x: Closed listen completion event\r\n", - pTcp6->ListenToken.CompletionToken.Event )); - } - else { - DEBUG (( DEBUG_ERROR | DebugFlags, - "ERROR - Failed to close the listen completion event, Status: %r\r\n", - Status )); - ASSERT ( EFI_SUCCESS == Status ); - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Perform the network specific close operation on the port. - - This routine performs a cancel operations on the TCPv6 port to - shutdown the receive operations on the port. - - This routine is called by the ::EslSocketPortCloseTxDone - routine after the port completes all of the transmission. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @retval EFI_SUCCESS The port is closed, not normally returned - @retval EFI_NOT_READY The port is still closing - @retval EFI_ALREADY_STARTED Error, the port is in the wrong state, - most likely the routine was called already. - -**/ -EFI_STATUS -EslTcp6PortCloseOp ( - IN ESL_PORT * pPort - ) -{ - ESL_TCP6_CONTEXT * pTcp6; - EFI_TCP6_PROTOCOL * pTcp6Protocol; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Close the configured port - // - Status = EFI_SUCCESS; - pTcp6 = &pPort->Context.Tcp6; - pTcp6Protocol = pPort->pProtocol.TCPv6; - pTcp6->CloseToken.AbortOnClose = pPort->bCloseNow; - Status = pTcp6Protocol->Close ( pTcp6Protocol, - &pTcp6->CloseToken ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO, - "0x%08x: Port close started\r\n", - pPort )); - } - else { - DEBUG (( DEBUG_ERROR | pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO, - "ERROR - Close failed on port 0x%08x, Status: %r\r\n", - pPort, - Status )); - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Receive data from a network connection. - - This routine attempts to return buffered data to the caller. The - data is removed from the urgent queue if the message flag MSG_OOB - is specified, otherwise data is removed from the normal queue. - See the \ref ReceiveEngine section. - - This routine is called by ::EslSocketReceive to handle the network - specific receive operation to support SOCK_STREAM and SOCK_SEQPACKET - sockets. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [in] pPacket Address of an ::ESL_PACKET structure. - - @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @param [out] pAddress Network address to receive the remote system address - - @param [out] pSkipBytes Address to receive the number of bytes skipped - - @return Returns the address of the next free byte in the buffer. - - **/ -UINT8 * -EslTcp6Receive ( - IN ESL_PORT * pPort, - IN ESL_PACKET * pPacket, - IN BOOLEAN * pbConsumePacket, - IN size_t BufferLength, - IN UINT8 * pBuffer, - OUT size_t * pDataLength, - OUT struct sockaddr * pAddress, - OUT size_t * pSkipBytes - ) -{ - size_t DataLength; - struct sockaddr_in6 * pRemoteAddress; - ESL_TCP6_CONTEXT * pTcp6; - - DBG_ENTER ( ); - - // - // Return the remote system address if requested - // - if ( NULL != pAddress ) { - // - // Build the remote address - // - pTcp6 = &pPort->Context.Tcp6; - DEBUG (( DEBUG_RX, - "Getting packet remote address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[1], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[2], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[3], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[4], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[5], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[6], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[7], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[8], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[9], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[10], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[11], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[12], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[13], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[14], - pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[15], - pTcp6->ConfigData.AccessPoint.RemotePort )); - pRemoteAddress = (struct sockaddr_in6 *)pAddress; - CopyMem ( &pRemoteAddress->sin6_addr, - &pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0], - sizeof ( pRemoteAddress->sin6_addr )); - pRemoteAddress->sin6_port = SwapBytes16 ( pTcp6->ConfigData.AccessPoint.RemotePort ); - } - - // - // Determine the amount of received data - // - DataLength = pPacket->ValidBytes; - if ( BufferLength < DataLength ) { - DataLength = BufferLength; - } - - // - // Move the data into the buffer - // - DEBUG (( DEBUG_RX, - "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n", - pPort, - pPacket, - pBuffer, - DataLength )); - CopyMem ( pBuffer, pPacket->pBuffer, DataLength ); - - // - // Set the next buffer address - // - pBuffer += DataLength; - - // - // Determine if the data is being read - // - if ( *pbConsumePacket ) { - // - // Account for the bytes consumed - // - pPacket->pBuffer += DataLength; - pPacket->ValidBytes -= DataLength; - DEBUG (( DEBUG_RX, - "0x%08x: Port account for 0x%08x bytes\r\n", - pPort, - DataLength )); - - // - // Determine if the entire packet was consumed - // - if (( 0 == pPacket->ValidBytes ) - || ( SOCK_STREAM != pPort->pSocket->Type )) { - // - // All done with this packet - // Account for any discarded data - // - *pSkipBytes = pPacket->ValidBytes; - } - else - { - // - // More data to consume later - // - *pbConsumePacket = FALSE; - } - } - - // - // Return the data length and the buffer address - // - *pDataLength = DataLength; - DBG_EXIT_HEX ( pBuffer ); - return pBuffer; -} - - -/** - Get the remote socket address. - - This routine returns the address of the remote connection point - associated with the SOCK_STREAM or SOCK_SEQPACKET socket. - - This routine is called by ::EslSocketGetPeerAddress to detemine - the TCPv6 address and por number associated with the network adapter. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [out] pAddress Network address to receive the remote system address - -**/ -VOID -EslTcp6RemoteAddressGet ( - IN ESL_PORT * pPort, - OUT struct sockaddr * pAddress - ) -{ - struct sockaddr_in6 * pRemoteAddress; - ESL_TCP6_CONTEXT * pTcp6; - - DBG_ENTER ( ); - - // - // Return the remote address - // - pTcp6 = &pPort->Context.Tcp6; - pRemoteAddress = (struct sockaddr_in6 *)pAddress; - pRemoteAddress->sin6_family = AF_INET6; - pRemoteAddress->sin6_port = SwapBytes16 ( pTcp6->ConfigData.AccessPoint.RemotePort ); - CopyMem ( &pRemoteAddress->sin6_addr, - &pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0], - sizeof ( pRemoteAddress->sin6_addr )); - - DBG_EXIT ( ); -} - - -/** - Set the remote address - - This routine sets the remote address in the port. - - This routine is called by ::EslSocketConnect to specify the - remote network address. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [in] pSockAddr Network address of the remote system. - - @param [in] SockAddrLength Length in bytes of the network address. - - @retval EFI_SUCCESS The operation was successful - - **/ -EFI_STATUS -EslTcp6RemoteAddressSet ( - IN ESL_PORT * pPort, - IN CONST struct sockaddr * pSockAddr, - IN socklen_t SockAddrLength - ) -{ - CONST struct sockaddr_in6 * pRemoteAddress; - ESL_TCP6_CONTEXT * pTcp6; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Set the remote address - // - pTcp6 = &pPort->Context.Tcp6; - pRemoteAddress = (struct sockaddr_in6 *)pSockAddr; - CopyMem ( &pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr [ 0 ], - &pRemoteAddress->sin6_addr.__u6_addr.__u6_addr8 [ 0 ], - sizeof ( pRemoteAddress->sin6_addr.__u6_addr.__u6_addr8 )); - pTcp6->ConfigData.AccessPoint.RemotePort = SwapBytes16 ( pRemoteAddress->sin6_port ); - Status = EFI_SUCCESS; - -// -// TODO: Fix the following check -// -/* - if ( INADDR_BROADCAST == pRemoteAddress->sin6_addr.s_addr ) { - DEBUG (( DEBUG_CONNECT, - "ERROR - Invalid remote address\r\n" )); - Status = EFI_INVALID_PARAMETER; - pPort->pSocket->errno = EAFNOSUPPORT; - } -*/ - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the receive completion - - This routine queues the data in FIFO order in either the urgent - or normal data queues depending upon the type of data received. - See the \ref ReceiveEngine section. - - This routine is called by the TCPv6 driver when some data is - received. - - Buffer the data that was just received. - - @param [in] Event The receive completion event - - @param [in] pIo Address of an ::ESL_IO_MGMT structure - -**/ -VOID -EslTcp6RxComplete ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ) -{ - BOOLEAN bUrgent; - size_t LengthInBytes; - ESL_PACKET * pPacket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Get the operation status. - // - Status = pIo->Token.Tcp6Rx.CompletionToken.Status; - - // - // +--------------------+ +---------------------------+ - // | ESL_IO_MGMT | | ESL_PACKET | - // | | | | - // | +---------------+ +-----------------------+ | - // | | Token | | EFI_Tcp6_RECEIVE_DATA | | - // | | RxData --> | | | - // | | | +-----------------------+---+ - // | | Event | | Data Buffer | - // +----+---------------+ | | - // | | - // +---------------------------+ - // - // - // Duplicate the buffer address and length for use by the - // buffer handling code in EslTcp6Receive. These fields are - // used when a partial read is done of the data from the - // packet. - // - pPacket = pIo->pPacket; - pPacket->pBuffer = pPacket->Op.Tcp6Rx.RxData.FragmentTable[0].FragmentBuffer; - LengthInBytes = pPacket->Op.Tcp6Rx.RxData.DataLength; - pPacket->ValidBytes = LengthInBytes; - - // - // Get the data type so that it may be linked to the - // correct receive buffer list on the ESL_SOCKET structure - // - bUrgent = pPacket->Op.Tcp6Rx.RxData.UrgentFlag; - - // - // Complete this request - // - EslSocketRxComplete ( pIo, Status, LengthInBytes, bUrgent ); - DBG_EXIT ( ); -} - - -/** - Start a receive operation - - This routine posts a receive buffer to the TCPv6 driver. - See the \ref ReceiveEngine section. - - This support routine is called by EslSocketRxStart. - - @param [in] pPort Address of an ::ESL_PORT structure. - @param [in] pIo Address of an ::ESL_IO_MGMT structure. - - **/ -VOID -EslTcp6RxStart ( - IN ESL_PORT * pPort, - IN ESL_IO_MGMT * pIo - ) -{ - ESL_PACKET * pPacket; - - DBG_ENTER ( ); - - // - // Initialize the buffer for receive - // - pPacket = pIo->pPacket; - pIo->Token.Tcp6Rx.Packet.RxData = &pPacket->Op.Tcp6Rx.RxData; - pPacket->Op.Tcp6Rx.RxData.DataLength = sizeof ( pPacket->Op.Tcp6Rx.Buffer ); - pPacket->Op.Tcp6Rx.RxData.FragmentCount = 1; - pPacket->Op.Tcp6Rx.RxData.FragmentTable[0].FragmentLength = pPacket->Op.Tcp6Rx.RxData.DataLength; - pPacket->Op.Tcp6Rx.RxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Tcp6Rx.Buffer[0]; - - DBG_EXIT ( ); -} - - -/** - Determine if the socket is configured. - - This routine uses the flag ESL_SOCKET::bConfigured to determine - if the network layer's configuration routine has been called. - - This routine is called by EslSocketIsConfigured to verify - that the socket has been configured. - - @param [in] pSocket Address of an ::ESL_SOCKET structure. - - @retval EFI_SUCCESS - The port is connected - @retval EFI_NOT_STARTED - The port is not connected - - **/ - EFI_STATUS - EslTcp6SocketIsConfigured ( - IN ESL_SOCKET * pSocket - ) -{ - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Determine the socket configuration status - // - Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED; - - // - // Return the port connected state. - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Buffer data for transmission over a network connection. - - This routine buffers data for the transmit engine in one of two - queues, one for urgent (out-of-band) data and the other for normal - data. The urgent data is provided to TCP as soon as it is available, - allowing the TCP layer to schedule transmission of the urgent data - between packets of normal data. - - This routine is called by ::EslSocketTransmit to buffer - data for transmission. When the \ref TransmitEngine has resources, - this routine will start the transmission of the next buffer on - the network connection. - - Transmission errors are returned during the next transmission or - during the close operation. Only buffering errors are returned - during the current transmission attempt. - - @param [in] pSocket Address of an ::ESL_SOCKET structure - - @param [in] Flags Message control flags - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @param [in] pAddress Network address of the remote system address - - @param [in] AddressLength Length of the remote network address structure - - @retval EFI_SUCCESS - Socket data successfully buffered - - **/ -EFI_STATUS -EslTcp6TxBuffer ( - IN ESL_SOCKET * pSocket, - IN int Flags, - IN size_t BufferLength, - IN CONST UINT8 * pBuffer, - OUT size_t * pDataLength, - IN const struct sockaddr * pAddress, - IN socklen_t AddressLength - ) -{ - BOOLEAN bUrgent; - BOOLEAN bUrgentQueue; - ESL_PACKET * pPacket; - ESL_IO_MGMT ** ppActive; - ESL_IO_MGMT ** ppFree; - ESL_PORT * pPort; - ESL_PACKET ** ppQueueHead; - ESL_PACKET ** ppQueueTail; - ESL_PACKET * pPreviousPacket; - size_t * pTxBytes; - EFI_TCP6_TRANSMIT_DATA * pTxData; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume failure - // - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTCONN; - *pDataLength = 0; - - // - // Verify that the socket is connected - // - if ( SOCKET_STATE_CONNECTED == pSocket->State ) { - // - // Locate the port - // - pPort = pSocket->pPortList; - if ( NULL != pPort ) { - // - // Determine the queue head - // - bUrgent = (BOOLEAN)( 0 != ( Flags & MSG_OOB )); - bUrgentQueue = bUrgent - && ( !pSocket->bOobInLine ) - && pSocket->pApi->bOobSupported; - if ( bUrgentQueue ) { - ppQueueHead = &pSocket->pTxOobPacketListHead; - ppQueueTail = &pSocket->pTxOobPacketListTail; - ppActive = &pPort->pTxOobActive; - ppFree = &pPort->pTxOobFree; - pTxBytes = &pSocket->TxOobBytes; - } - else { - ppQueueHead = &pSocket->pTxPacketListHead; - ppQueueTail = &pSocket->pTxPacketListTail; - ppActive = &pPort->pTxActive; - ppFree = &pPort->pTxFree; - pTxBytes = &pSocket->TxBytes; - } - - // - // Verify that there is enough room to buffer another - // transmit operation - // - if ( pSocket->MaxTxBuf > *pTxBytes ) { - if ( pPort->bTxFlowControl ) { - DEBUG (( DEBUG_TX, - "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\r\n0x%08x: pPort, TX flow control released, Max bytes: %d > %d bufferred bytes\r\n", - pPort, - pSocket->MaxTxBuf, - *pTxBytes )); - pPort->bTxFlowControl = FALSE; - } - - // - // Attempt to allocate the packet - // - Status = EslSocketPacketAllocate ( &pPacket, - sizeof ( pPacket->Op.Tcp6Tx ) - - sizeof ( pPacket->Op.Tcp6Tx.Buffer ) - + BufferLength, - 0, - DEBUG_TX ); - if ( !EFI_ERROR ( Status )) { - // - // Initialize the transmit operation - // - pTxData = &pPacket->Op.Tcp6Tx.TxData; - pTxData->Push = TRUE || bUrgent; - pTxData->Urgent = bUrgent; - pTxData->DataLength = (UINT32) BufferLength; - pTxData->FragmentCount = 1; - pTxData->FragmentTable[0].FragmentLength = (UINT32) BufferLength; - pTxData->FragmentTable[0].FragmentBuffer = &pPacket->Op.Tcp6Tx.Buffer[0]; - - // - // Copy the data into the buffer - // - CopyMem ( &pPacket->Op.Tcp6Tx.Buffer[0], - pBuffer, - BufferLength ); - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Stop transmission after an error - // - if ( !EFI_ERROR ( pSocket->TxError )) { - // - // Display the request - // - DEBUG (( DEBUG_TX, - "Send %d %s bytes from 0x%08x\r\n", - BufferLength, - bUrgent ? L"urgent" : L"normal", - pBuffer )); - - // - // Queue the data for transmission - // - pPacket->pNext = NULL; - pPreviousPacket = *ppQueueTail; - if ( NULL == pPreviousPacket ) { - *ppQueueHead = pPacket; - } - else { - pPreviousPacket->pNext = pPacket; - } - *ppQueueTail = pPacket; - DEBUG (( DEBUG_TX, - "0x%08x: Packet on %s transmit list\r\n", - pPacket, - bUrgentQueue ? L"urgent" : L"normal" )); - - // - // Account for the buffered data - // - *pTxBytes += BufferLength; - *pDataLength = BufferLength; - - // - // Start the transmit engine if it is idle - // - if ( NULL != *ppFree ) { - EslSocketTxStart ( pPort, - ppQueueHead, - ppQueueTail, - ppActive, - ppFree ); - } - } - else { - // - // Previous transmit error - // Stop transmission - // - Status = pSocket->TxError; - pSocket->errno = EIO; - - // - // Free the packet - // - EslSocketPacketFree ( pPacket, DEBUG_TX ); - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - else { - // - // Packet allocation failed - // - pSocket->errno = ENOMEM; - } - } - else { - if ( !pPort->bTxFlowControl ) { - DEBUG (( DEBUG_TX, - "0x%08x: pPort, TX flow control applied, Max bytes %d <= %d bufferred bytes\r\nTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\r\n", - pPort, - pSocket->MaxTxBuf, - *pTxBytes )); - pPort->bTxFlowControl = TRUE; - } - // - // Not enough buffer space available - // - pSocket->errno = EAGAIN; - Status = EFI_NOT_READY; - } - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the normal data transmit completion - - This routine use ::EslSocketTxComplete to perform the transmit - completion processing for normal data. - - This routine is called by the TCPv6 network layer when a - normal data transmit request completes. - - @param [in] Event The normal transmit completion event - - @param [in] pIo The ESL_IO_MGMT structure address - -**/ -VOID -EslTcp6TxComplete ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ) -{ - UINT32 LengthInBytes; - ESL_PACKET * pPacket; - ESL_PORT * pPort; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the active transmit packet - // - pPacket = pIo->pPacket; - pPort = pIo->pPort; - pSocket = pPort->pSocket; - - // - // Get the transmit length and status - // - LengthInBytes = pPacket->Op.Tcp6Tx.TxData.DataLength; - pSocket->TxBytes -= LengthInBytes; - Status = pIo->Token.Tcp6Tx.CompletionToken.Status; - - // - // Complete the transmit operation - // - EslSocketTxComplete ( pIo, - LengthInBytes, - Status, - "Normal ", - &pSocket->pTxPacketListHead, - &pSocket->pTxPacketListTail, - &pPort->pTxActive, - &pPort->pTxFree ); - DBG_EXIT ( ); -} - - -/** - Process the urgent data transmit completion - - This routine use ::EslSocketTxComplete to perform the transmit - completion processing for urgent data. - - This routine is called by the TCPv6 network layer when a - urgent data transmit request completes. - - @param [in] Event The urgent transmit completion event - - @param [in] pIo The ESL_IO_MGMT structure address - -**/ -VOID -EslTcp6TxOobComplete ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ) -{ - UINT32 LengthInBytes; - ESL_PACKET * pPacket; - ESL_PORT * pPort; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the active transmit packet - // - pPacket = pIo->pPacket; - pPort = pIo->pPort; - pSocket = pPort->pSocket; - - // - // Get the transmit length and status - // - LengthInBytes = pPacket->Op.Tcp6Tx.TxData.DataLength; - pSocket->TxOobBytes -= LengthInBytes; - Status = pIo->Token.Tcp6Tx.CompletionToken.Status; - - // - // Complete the transmit operation - // - EslSocketTxComplete ( pIo, - LengthInBytes, - Status, - "Urgent ", - &pSocket->pTxOobPacketListHead, - &pSocket->pTxOobPacketListTail, - &pPort->pTxOobActive, - &pPort->pTxOobFree ); - DBG_EXIT ( ); -} - - -/** - Verify the adapter's IP address - - This support routine is called by EslSocketBindTest. - - @param [in] pPort Address of an ::ESL_PORT structure. - @param [in] pConfigData Address of the configuration data - - @retval EFI_SUCCESS - The IP address is valid - @retval EFI_NOT_STARTED - The IP address is invalid - - **/ -EFI_STATUS -EslTcp6VerifyLocalIpAddress ( - IN ESL_PORT * pPort, - IN EFI_TCP6_CONFIG_DATA * pConfigData - ) -{ - UINTN AddressCount; - EFI_IP6_ADDRESS_INFO * pAddressInfo; - UINTN DataSize; - EFI_TCP6_ACCESS_POINT * pAccess; - EFI_IP6_CONFIG_INTERFACE_INFO * pIpConfigData; - EFI_IP6_CONFIG_PROTOCOL * pIpConfigProtocol; - ESL_SERVICE * pService; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Use break instead of goto - // - pIpConfigData = NULL; - for ( ; ; ) { - // - // Determine if the IP address is specified - // - pAccess = &pConfigData->AccessPoint; - DEBUG (( DEBUG_BIND, - "Requested IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n", - pAccess->StationAddress.Addr[0], - pAccess->StationAddress.Addr[1], - pAccess->StationAddress.Addr[2], - pAccess->StationAddress.Addr[3], - pAccess->StationAddress.Addr[4], - pAccess->StationAddress.Addr[5], - pAccess->StationAddress.Addr[6], - pAccess->StationAddress.Addr[7], - pAccess->StationAddress.Addr[8], - pAccess->StationAddress.Addr[9], - pAccess->StationAddress.Addr[10], - pAccess->StationAddress.Addr[11], - pAccess->StationAddress.Addr[12], - pAccess->StationAddress.Addr[13], - pAccess->StationAddress.Addr[14], - pAccess->StationAddress.Addr[15])); - if (( 0 == pAccess->StationAddress.Addr [ 0 ]) - && ( 0 == pAccess->StationAddress.Addr [ 1 ]) - && ( 0 == pAccess->StationAddress.Addr [ 2 ]) - && ( 0 == pAccess->StationAddress.Addr [ 3 ]) - && ( 0 == pAccess->StationAddress.Addr [ 4 ]) - && ( 0 == pAccess->StationAddress.Addr [ 5 ]) - && ( 0 == pAccess->StationAddress.Addr [ 6 ]) - && ( 0 == pAccess->StationAddress.Addr [ 7 ]) - && ( 0 == pAccess->StationAddress.Addr [ 8 ]) - && ( 0 == pAccess->StationAddress.Addr [ 9 ]) - && ( 0 == pAccess->StationAddress.Addr [ 10 ]) - && ( 0 == pAccess->StationAddress.Addr [ 11 ]) - && ( 0 == pAccess->StationAddress.Addr [ 12 ]) - && ( 0 == pAccess->StationAddress.Addr [ 13 ]) - && ( 0 == pAccess->StationAddress.Addr [ 14 ]) - && ( 0 == pAccess->StationAddress.Addr [ 15 ])) - { - Status = EFI_SUCCESS; - break; - } - - // - // Open the configuration protocol - // - pService = pPort->pService; - Status = gBS->OpenProtocol ( pService->Controller, - &gEfiIp6ConfigProtocolGuid, - (VOID **)&pIpConfigProtocol, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR, - "ERROR - IP Configuration Protocol not available, Status: %r\r\n", - Status )); - break; - } - - // - // Get the IP configuration data size - // - DataSize = 0; - Status = pIpConfigProtocol->GetData ( pIpConfigProtocol, - Ip6ConfigDataTypeInterfaceInfo, - &DataSize, - NULL ); - if ( EFI_BUFFER_TOO_SMALL != Status ) { - DEBUG (( DEBUG_ERROR, - "ERROR - Failed to get IP Configuration data size, Status: %r\r\n", - Status )); - break; - } - - // - // Allocate the configuration data buffer - // - pIpConfigData = AllocatePool ( DataSize ); - if ( NULL == pIpConfigData ) { - DEBUG (( DEBUG_ERROR, - "ERROR - Not enough memory to allocate IP Configuration data!\r\n" )); - Status = EFI_OUT_OF_RESOURCES; - break; - } - - // - // Get the IP configuration - // - Status = pIpConfigProtocol->GetData ( pIpConfigProtocol, - Ip6ConfigDataTypeInterfaceInfo, - &DataSize, - pIpConfigData ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR, - "ERROR - Failed to return IP Configuration data, Status: %r\r\n", - Status )); - break; - } - - // - // Display the current configuration - // - DEBUG (( DEBUG_BIND, - "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n", - pIpConfigData->HwAddress.Addr [ 0 ], - pIpConfigData->HwAddress.Addr [ 1 ], - pIpConfigData->HwAddress.Addr [ 2 ], - pIpConfigData->HwAddress.Addr [ 3 ], - pIpConfigData->HwAddress.Addr [ 4 ], - pIpConfigData->HwAddress.Addr [ 5 ], - pIpConfigData->HwAddress.Addr [ 6 ], - pIpConfigData->HwAddress.Addr [ 7 ], - pIpConfigData->HwAddress.Addr [ 8 ], - pIpConfigData->HwAddress.Addr [ 9 ], - pIpConfigData->HwAddress.Addr [ 10 ], - pIpConfigData->HwAddress.Addr [ 11 ], - pIpConfigData->HwAddress.Addr [ 12 ], - pIpConfigData->HwAddress.Addr [ 13 ], - pIpConfigData->HwAddress.Addr [ 14 ], - pIpConfigData->HwAddress.Addr [ 15 ])); - - // - // Validate the hardware address - // - Status = EFI_SUCCESS; - if (( 16 == pIpConfigData->HwAddressSize ) - && ( pAccess->StationAddress.Addr [ 0 ] == pIpConfigData->HwAddress.Addr [ 0 ]) - && ( pAccess->StationAddress.Addr [ 1 ] == pIpConfigData->HwAddress.Addr [ 1 ]) - && ( pAccess->StationAddress.Addr [ 2 ] == pIpConfigData->HwAddress.Addr [ 2 ]) - && ( pAccess->StationAddress.Addr [ 3 ] == pIpConfigData->HwAddress.Addr [ 3 ]) - && ( pAccess->StationAddress.Addr [ 4 ] == pIpConfigData->HwAddress.Addr [ 4 ]) - && ( pAccess->StationAddress.Addr [ 5 ] == pIpConfigData->HwAddress.Addr [ 5 ]) - && ( pAccess->StationAddress.Addr [ 6 ] == pIpConfigData->HwAddress.Addr [ 6 ]) - && ( pAccess->StationAddress.Addr [ 7 ] == pIpConfigData->HwAddress.Addr [ 7 ]) - && ( pAccess->StationAddress.Addr [ 8 ] == pIpConfigData->HwAddress.Addr [ 8 ]) - && ( pAccess->StationAddress.Addr [ 9 ] == pIpConfigData->HwAddress.Addr [ 9 ]) - && ( pAccess->StationAddress.Addr [ 10 ] == pIpConfigData->HwAddress.Addr [ 10 ]) - && ( pAccess->StationAddress.Addr [ 11 ] == pIpConfigData->HwAddress.Addr [ 11 ]) - && ( pAccess->StationAddress.Addr [ 12 ] == pIpConfigData->HwAddress.Addr [ 12 ]) - && ( pAccess->StationAddress.Addr [ 13 ] == pIpConfigData->HwAddress.Addr [ 13 ]) - && ( pAccess->StationAddress.Addr [ 14 ] == pIpConfigData->HwAddress.Addr [ 14 ]) - && ( pAccess->StationAddress.Addr [ 15 ] == pIpConfigData->HwAddress.Addr [ 15 ])) { - break; - } - - // - // Walk the list of other IP addresses assigned to this adapter - // - for ( AddressCount = 0; pIpConfigData->AddressInfoCount > AddressCount; AddressCount += 1 ) { - pAddressInfo = &pIpConfigData->AddressInfo [ AddressCount ]; - - // - // Display the IP address - // - DEBUG (( DEBUG_BIND, - "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n", - pAddressInfo->Address.Addr [ 0 ], - pAddressInfo->Address.Addr [ 1 ], - pAddressInfo->Address.Addr [ 2 ], - pAddressInfo->Address.Addr [ 3 ], - pAddressInfo->Address.Addr [ 4 ], - pAddressInfo->Address.Addr [ 5 ], - pAddressInfo->Address.Addr [ 6 ], - pAddressInfo->Address.Addr [ 7 ], - pAddressInfo->Address.Addr [ 8 ], - pAddressInfo->Address.Addr [ 9 ], - pAddressInfo->Address.Addr [ 10 ], - pAddressInfo->Address.Addr [ 11 ], - pAddressInfo->Address.Addr [ 12 ], - pAddressInfo->Address.Addr [ 13 ], - pAddressInfo->Address.Addr [ 14 ], - pAddressInfo->Address.Addr [ 15 ])); - - // - // Validate the IP address - // - if (( pAccess->StationAddress.Addr [ 0 ] == pAddressInfo->Address.Addr [ 0 ]) - && ( pAccess->StationAddress.Addr [ 1 ] == pAddressInfo->Address.Addr [ 1 ]) - && ( pAccess->StationAddress.Addr [ 2 ] == pAddressInfo->Address.Addr [ 2 ]) - && ( pAccess->StationAddress.Addr [ 3 ] == pAddressInfo->Address.Addr [ 3 ]) - && ( pAccess->StationAddress.Addr [ 4 ] == pAddressInfo->Address.Addr [ 4 ]) - && ( pAccess->StationAddress.Addr [ 5 ] == pAddressInfo->Address.Addr [ 5 ]) - && ( pAccess->StationAddress.Addr [ 6 ] == pAddressInfo->Address.Addr [ 6 ]) - && ( pAccess->StationAddress.Addr [ 7 ] == pAddressInfo->Address.Addr [ 7 ]) - && ( pAccess->StationAddress.Addr [ 8 ] == pAddressInfo->Address.Addr [ 8 ]) - && ( pAccess->StationAddress.Addr [ 9 ] == pAddressInfo->Address.Addr [ 9 ]) - && ( pAccess->StationAddress.Addr [ 10 ] == pAddressInfo->Address.Addr [ 10 ]) - && ( pAccess->StationAddress.Addr [ 11 ] == pAddressInfo->Address.Addr [ 11 ]) - && ( pAccess->StationAddress.Addr [ 12 ] == pAddressInfo->Address.Addr [ 12 ]) - && ( pAccess->StationAddress.Addr [ 13 ] == pAddressInfo->Address.Addr [ 13 ]) - && ( pAccess->StationAddress.Addr [ 14 ] == pAddressInfo->Address.Addr [ 14 ]) - && ( pAccess->StationAddress.Addr [ 15 ] == pAddressInfo->Address.Addr [ 15 ])) { - break; - } - } - if ( pIpConfigData->AddressInfoCount > AddressCount ) { - break; - } - - // - // The IP address did not match - // - Status = EFI_NOT_STARTED; - break; - } - - // - // Free the buffer if necessary - // - if ( NULL != pIpConfigData ) { - FreePool ( pIpConfigData ); - } - - // - // Return the IP address status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Interface between the socket layer and the network specific - code that supports SOCK_STREAM and SOCK_SEQPACKET sockets - over TCPv6. -**/ -CONST ESL_PROTOCOL_API cEslTcp6Api = { - "TCPv6", - IPPROTO_TCP, - OFFSET_OF ( ESL_PORT, Context.Tcp6.ConfigData ), - OFFSET_OF ( ESL_LAYER, pTcp6List ), - sizeof ( struct sockaddr_in6 ), - sizeof ( struct sockaddr_in6 ), - AF_INET6, - sizeof (((ESL_PACKET *)0 )->Op.Tcp6Rx ), - OFFSET_OF ( ESL_PACKET, Op.Tcp6Rx.Buffer ) - OFFSET_OF ( ESL_PACKET, Op ), - OFFSET_OF ( ESL_IO_MGMT, Token.Tcp6Rx.Packet.RxData ), - TRUE, - EADDRINUSE, - EslTcp6Accept, - EslTcp6ConnectPoll, - EslTcp6ConnectStart, - EslTcp6SocketIsConfigured, - EslTcp6LocalAddressGet, - EslTcp6LocalAddressSet, - EslTcp6Listen, - NULL, // OptionGet - NULL, // OptionSet - EslTcp6PacketFree, - EslTcp6PortAllocate, - EslTcp6PortClose, - EslTcp6PortCloseOp, - FALSE, - EslTcp6Receive, - EslTcp6RemoteAddressGet, - EslTcp6RemoteAddressSet, - EslTcp6RxComplete, - EslTcp6RxStart, - EslTcp6TxBuffer, - EslTcp6TxComplete, - EslTcp6TxOobComplete, - (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslTcp6VerifyLocalIpAddress -}; diff --git a/StdLib/EfiSocketLib/Udp4.c b/StdLib/EfiSocketLib/Udp4.c deleted file mode 100644 index ef2f9e321b..0000000000 --- a/StdLib/EfiSocketLib/Udp4.c +++ /dev/null @@ -1,1232 +0,0 @@ -/** @file - Implement the UDP4 driver support for the socket layer. - - Copyright (c) 2011 - 2015, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "Socket.h" - - -/** - Get the local socket address - - This routine returns the IPv4 address and UDP port number associated - with the local socket. - - This routine is called by ::EslSocketGetLocalAddress to determine the - network address for the SOCK_DGRAM socket. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [out] pSockAddr Network address to receive the local system address - -**/ -VOID -EslUdp4LocalAddressGet ( - IN ESL_PORT * pPort, - OUT struct sockaddr * pSockAddr - ) -{ - struct sockaddr_in * pLocalAddress; - ESL_UDP4_CONTEXT * pUdp4; - - DBG_ENTER ( ); - - // - // Return the local address - // - pUdp4 = &pPort->Context.Udp4; - pLocalAddress = (struct sockaddr_in *)pSockAddr; - pLocalAddress->sin_family = AF_INET; - pLocalAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.StationPort ); - CopyMem ( &pLocalAddress->sin_addr, - &pUdp4->ConfigData.StationAddress.Addr[0], - sizeof ( pLocalAddress->sin_addr )); - - DBG_EXIT ( ); -} - - -/** - Set the local port address. - - This routine sets the local port address. - - This support routine is called by ::EslSocketPortAllocate. - - @param [in] pPort Address of an ESL_PORT structure - @param [in] pSockAddr Address of a sockaddr structure that contains the - connection point on the local machine. An IPv4 address - of INADDR_ANY specifies that the connection is made to - all of the network stacks on the platform. Specifying a - specific IPv4 address restricts the connection to the - network stack supporting that address. Specifying zero - for the port causes the network layer to assign a port - number from the dynamic range. Specifying a specific - port number causes the network layer to use that port. - - @param [in] bBindTest TRUE = run bind testing - - @retval EFI_SUCCESS The operation was successful - - **/ -EFI_STATUS -EslUdp4LocalAddressSet ( - IN ESL_PORT * pPort, - IN CONST struct sockaddr * pSockAddr, - IN BOOLEAN bBindTest - ) -{ - EFI_UDP4_CONFIG_DATA * pConfig; - CONST struct sockaddr_in * pIpAddress; - CONST UINT8 * pIpv4Address; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Validate the address - // - pIpAddress = (struct sockaddr_in *)pSockAddr; - if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) { - // - // The local address must not be the broadcast address - // - Status = EFI_INVALID_PARAMETER; - pPort->pSocket->errno = EADDRNOTAVAIL; - } - else { - // - // Set the local address - // - pIpAddress = (struct sockaddr_in *)pSockAddr; - pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr; - pConfig = &pPort->Context.Udp4.ConfigData; - pConfig->StationAddress.Addr[0] = pIpv4Address[0]; - pConfig->StationAddress.Addr[1] = pIpv4Address[1]; - pConfig->StationAddress.Addr[2] = pIpv4Address[2]; - pConfig->StationAddress.Addr[3] = pIpv4Address[3]; - - // - // Determine if the default address is used - // - pConfig->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr ); - - // - // Set the subnet mask - // - if ( pConfig->UseDefaultAddress ) { - pConfig->SubnetMask.Addr[0] = 0; - pConfig->SubnetMask.Addr[1] = 0; - pConfig->SubnetMask.Addr[2] = 0; - pConfig->SubnetMask.Addr[3] = 0; - } - else { - pConfig->SubnetMask.Addr[0] = 0xff; - pConfig->SubnetMask.Addr[1] = ( 128 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0; - pConfig->SubnetMask.Addr[2] = ( 192 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0; - pConfig->SubnetMask.Addr[3] = ( 224 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0; - } - - // - // Validate the IP address - // - pConfig->StationPort = 0; - Status = bBindTest ? EslSocketBindTest ( pPort, EADDRNOTAVAIL ) - : EFI_SUCCESS; - if ( !EFI_ERROR ( Status )) { - // - // Set the port number - // - pConfig->StationPort = SwapBytes16 ( pIpAddress->sin_port ); - - // - // Display the local address - // - DEBUG (( DEBUG_BIND, - "0x%08x: Port, Local UDP4 Address: %d.%d.%d.%d:%d\r\n", - pPort, - pConfig->StationAddress.Addr[0], - pConfig->StationAddress.Addr[1], - pConfig->StationAddress.Addr[2], - pConfig->StationAddress.Addr[3], - pConfig->StationPort )); - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Free a receive packet - - This routine performs the network specific operations necessary - to free a receive packet. - - This routine is called by ::EslSocketPortCloseTxDone to free a - receive packet. - - @param [in] pPacket Address of an ::ESL_PACKET structure. - @param [in, out] pRxBytes Address of the count of RX bytes - -**/ -VOID -EslUdp4PacketFree ( - IN ESL_PACKET * pPacket, - IN OUT size_t * pRxBytes - ) -{ - EFI_UDP4_RECEIVE_DATA * pRxData; - - DBG_ENTER ( ); - - // - // Account for the receive bytes - // - pRxData = pPacket->Op.Udp4Rx.pRxData; - *pRxBytes -= pRxData->DataLength; - - // - // Disconnect the buffer from the packet - // - pPacket->Op.Udp4Rx.pRxData = NULL; - - // - // Return the buffer to the UDP4 driver - // - gBS->SignalEvent ( pRxData->RecycleSignal ); - DBG_EXIT ( ); -} - - -/** - Initialize the network specific portions of an ::ESL_PORT structure. - - This routine initializes the network specific portions of an - ::ESL_PORT structure for use by the socket. - - This support routine is called by ::EslSocketPortAllocate - to connect the socket with the underlying network adapter - running the UDPv4 protocol. - - @param [in] pPort Address of an ESL_PORT structure - @param [in] DebugFlags Flags for debug messages - - @retval EFI_SUCCESS - Socket successfully created - - **/ -EFI_STATUS -EslUdp4PortAllocate ( - IN ESL_PORT * pPort, - IN UINTN DebugFlags - ) -{ - EFI_UDP4_CONFIG_DATA * pConfig; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Initialize the port - // - pSocket = pPort->pSocket; - pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Udp4Tx.TxData ); - pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Udp4Tx.Event ); - pSocket->TxTokenOffset = OFFSET_OF ( EFI_UDP4_COMPLETION_TOKEN, Packet.TxData ); - - // - // Save the cancel, receive and transmit addresses - // - pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.UDPv4->Configure; - pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Cancel; - pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.UDPv4->Poll; - pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Receive; - pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Transmit; - - // - // Set the configuration flags - // - pConfig = &pPort->Context.Udp4.ConfigData; - pConfig->TimeToLive = 255; - pConfig->AcceptAnyPort = FALSE; - pConfig->AcceptBroadcast = FALSE; - pConfig->AcceptPromiscuous = FALSE; - pConfig->AllowDuplicatePort = TRUE; - pConfig->DoNotFragment = FALSE; - Status = EFI_SUCCESS; - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Receive data from a network connection. - - This routine attempts to return buffered data to the caller. The - data is removed from the urgent queue if the message flag MSG_OOB - is specified, otherwise data is removed from the normal queue. - See the \ref ReceiveEngine section. - - This routine is called by ::EslSocketReceive to handle the network - specific receive operation to support SOCK_DGRAM sockets. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [in] pPacket Address of an ::ESL_PACKET structure. - - @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @param [out] pAddress Network address to receive the remote system address - - @param [out] pSkipBytes Address to receive the number of bytes skipped - - @return Returns the address of the next free byte in the buffer. - - **/ -UINT8 * -EslUdp4Receive ( - IN ESL_PORT * pPort, - IN ESL_PACKET * pPacket, - IN BOOLEAN * pbConsumePacket, - IN size_t BufferLength, - IN UINT8 * pBuffer, - OUT size_t * pDataLength, - OUT struct sockaddr * pAddress, - OUT size_t * pSkipBytes - ) -{ - size_t DataBytes; - struct sockaddr_in * pRemoteAddress; - EFI_UDP4_RECEIVE_DATA * pRxData; - - DBG_ENTER ( ); - - pRxData = pPacket->Op.Udp4Rx.pRxData; - // - // Return the remote system address if requested - // - if ( NULL != pAddress ) { - // - // Build the remote address - // - DEBUG (( DEBUG_RX, - "Getting packet remote address: %d.%d.%d.%d:%d\r\n", - pRxData->UdpSession.SourceAddress.Addr[0], - pRxData->UdpSession.SourceAddress.Addr[1], - pRxData->UdpSession.SourceAddress.Addr[2], - pRxData->UdpSession.SourceAddress.Addr[3], - pRxData->UdpSession.SourcePort )); - pRemoteAddress = (struct sockaddr_in *)pAddress; - CopyMem ( &pRemoteAddress->sin_addr, - &pRxData->UdpSession.SourceAddress.Addr[0], - sizeof ( pRemoteAddress->sin_addr )); - pRemoteAddress->sin_port = SwapBytes16 ( pRxData->UdpSession.SourcePort ); - } - - // - // Copy the received data - // - pBuffer = EslSocketCopyFragmentedBuffer ( pRxData->FragmentCount, - (EFI_IP4_FRAGMENT_DATA *)&pRxData->FragmentTable[0], - BufferLength, - pBuffer, - &DataBytes ); - - // - // Determine if the data is being read - // - if ( *pbConsumePacket ) { - // - // Display for the bytes consumed - // - DEBUG (( DEBUG_RX, - "0x%08x: Port account for 0x%08x bytes\r\n", - pPort, - DataBytes )); - - // - // Account for any discarded data - // - *pSkipBytes = pRxData->DataLength - DataBytes; - } - - // - // Return the data length and the buffer address - // - *pDataLength = DataBytes; - DBG_EXIT_HEX ( pBuffer ); - return pBuffer; -} - - -/** - Get the remote socket address - - This routine returns the address of the remote connection point - associated with the SOCK_DGRAM socket. - - This routine is called by ::EslSocketGetPeerAddress to detemine - the UDPv4 address and port number associated with the network adapter. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [out] pAddress Network address to receive the remote system address - -**/ -VOID -EslUdp4RemoteAddressGet ( - IN ESL_PORT * pPort, - OUT struct sockaddr * pAddress - ) -{ - struct sockaddr_in * pRemoteAddress; - ESL_UDP4_CONTEXT * pUdp4; - - DBG_ENTER ( ); - - // - // Return the remote address - // - pUdp4 = &pPort->Context.Udp4; - pRemoteAddress = (struct sockaddr_in *)pAddress; - pRemoteAddress->sin_family = AF_INET; - pRemoteAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.RemotePort ); - CopyMem ( &pRemoteAddress->sin_addr, - &pUdp4->ConfigData.RemoteAddress.Addr[0], - sizeof ( pRemoteAddress->sin_addr )); - - DBG_EXIT ( ); -} - - -/** - Set the remote address - - This routine sets the remote address in the port. - - This routine is called by ::EslSocketConnect to specify the - remote network address. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [in] pSockAddr Network address of the remote system. - - @param [in] SockAddrLength Length in bytes of the network address. - - @retval EFI_SUCCESS The operation was successful - - **/ -EFI_STATUS -EslUdp4RemoteAddressSet ( - IN ESL_PORT * pPort, - IN CONST struct sockaddr * pSockAddr, - IN socklen_t SockAddrLength - ) -{ - CONST struct sockaddr_in * pRemoteAddress; - ESL_UDP4_CONTEXT * pUdp4; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Set the remote address - // - pUdp4 = &pPort->Context.Udp4; - pRemoteAddress = (struct sockaddr_in *)pSockAddr; - pUdp4->ConfigData.RemoteAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr ); - pUdp4->ConfigData.RemoteAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 ); - pUdp4->ConfigData.RemoteAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 ); - pUdp4->ConfigData.RemoteAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 ); - pUdp4->ConfigData.RemotePort = SwapBytes16 ( pRemoteAddress->sin_port ); - pPort->pSocket->bAddressSet = TRUE; - Status = EFI_SUCCESS; - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the receive completion - - This routine keeps the UDPv4 driver's buffer and queues it in - in FIFO order to the data queue. The UDP4 driver's buffer will - be returned by either ::EslUdp4Receive or ::EslSocketPortCloseTxDone. - See the \ref ReceiveEngine section. - - This routine is called by the UDPv4 driver when data is - received. - - @param [in] Event The receive completion event - - @param [in] pIo Address of an ::ESL_IO_MGMT structure - -**/ -VOID -EslUdp4RxComplete ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ) -{ - size_t LengthInBytes; - ESL_PACKET * pPacket; - EFI_UDP4_RECEIVE_DATA * pRxData; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Get the operation status. - // - Status = pIo->Token.Udp4Rx.Status; - - // - // Get the packet length - // - pRxData = pIo->Token.Udp4Rx.Packet.RxData; - LengthInBytes = pRxData->DataLength; - - // - // +--------------------+ +-----------------------+ - // | ESL_IO_MGMT | | Data Buffer | - // | | | (Driver owned) | - // | +---------------+ +-----------------------+ - // | | Token | ^ - // | | Rx Event | | - // | | | +-----------------------+ - // | | RxData --> | EFI_UDP4_RECEIVE_DATA | - // +----+---------------+ | (Driver owned) | - // +-----------------------+ - // +--------------------+ ^ - // | ESL_PACKET | . - // | | . - // | +---------------+ . - // | | pRxData --> NULL ....... - // +----+---------------+ - // - // - // Save the data in the packet - // - pPacket = pIo->pPacket; - pPacket->Op.Udp4Rx.pRxData = pRxData; - - // - // Complete this request - // - EslSocketRxComplete ( pIo, Status, LengthInBytes, FALSE ); - DBG_EXIT ( ); -} - - -/** - Determine if the socket is configured. - - This routine uses the flag ESL_SOCKET::bConfigured to determine - if the network layer's configuration routine has been called. - This routine calls the bind and configuration routines if they - were not already called. After the port is configured, the - \ref ReceiveEngine is started. - - This routine is called by EslSocketIsConfigured to verify - that the socket is configured. - - @param [in] pSocket Address of an ::ESL_SOCKET structure - - @retval EFI_SUCCESS - The port is connected - @retval EFI_NOT_STARTED - The port is not connected - - **/ - EFI_STATUS - EslUdp4SocketIsConfigured ( - IN ESL_SOCKET * pSocket - ) -{ - EFI_UDP4_CONFIG_DATA * pConfigData; - ESL_PORT * pPort; - ESL_PORT * pNextPort; - ESL_UDP4_CONTEXT * pUdp4; - EFI_UDP4_PROTOCOL * pUdp4Protocol; - EFI_STATUS Status; - struct sockaddr_in LocalAddress; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Configure the port if necessary - // - if ( !pSocket->bConfigured ) { - // - // Fill in the port list if necessary - // - pSocket->errno = ENETDOWN; - if ( NULL == pSocket->pPortList ) { - LocalAddress.sin_len = sizeof ( LocalAddress ); - LocalAddress.sin_family = AF_INET; - LocalAddress.sin_addr.s_addr = 0; - LocalAddress.sin_port = 0; - Status = EslSocketBind ( &pSocket->SocketProtocol, - (struct sockaddr *)&LocalAddress, - LocalAddress.sin_len, - &pSocket->errno ); - } - - // - // Walk the port list - // - pPort = pSocket->pPortList; - while ( NULL != pPort ) { - // - // Attempt to configure the port - // - pNextPort = pPort->pLinkSocket; - pUdp4 = &pPort->Context.Udp4; - pUdp4Protocol = pPort->pProtocol.UDPv4; - pConfigData = &pUdp4->ConfigData; - DEBUG (( DEBUG_TX, - "0x%08x: pPort Configuring for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n", - pPort, - pConfigData->StationAddress.Addr[0], - pConfigData->StationAddress.Addr[1], - pConfigData->StationAddress.Addr[2], - pConfigData->StationAddress.Addr[3], - pConfigData->StationPort, - pConfigData->RemoteAddress.Addr[0], - pConfigData->RemoteAddress.Addr[1], - pConfigData->RemoteAddress.Addr[2], - pConfigData->RemoteAddress.Addr[3], - pConfigData->RemotePort )); - Status = pUdp4Protocol->Configure ( pUdp4Protocol, - pConfigData ); - if ( !EFI_ERROR ( Status )) { - // - // Update the configuration data - // - Status = pUdp4Protocol->GetModeData ( pUdp4Protocol, - pConfigData, - NULL, - NULL, - NULL ); - } - if ( EFI_ERROR ( Status )) { - if ( !pSocket->bConfigured ) { - DEBUG (( DEBUG_LISTEN, - "ERROR - Failed to configure the Udp4 port, Status: %r\r\n", - Status )); - switch ( Status ) { - case EFI_ACCESS_DENIED: - pSocket->errno = EACCES; - break; - - default: - case EFI_DEVICE_ERROR: - pSocket->errno = EIO; - break; - - case EFI_INVALID_PARAMETER: - pSocket->errno = EADDRNOTAVAIL; - break; - - case EFI_NO_MAPPING: - pSocket->errno = EAFNOSUPPORT; - break; - - case EFI_OUT_OF_RESOURCES: - pSocket->errno = ENOBUFS; - break; - - case EFI_UNSUPPORTED: - pSocket->errno = EOPNOTSUPP; - break; - } - } - } - else { - DEBUG (( DEBUG_TX, - "0x%08x: pPort Configured for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n", - pPort, - pConfigData->StationAddress.Addr[0], - pConfigData->StationAddress.Addr[1], - pConfigData->StationAddress.Addr[2], - pConfigData->StationAddress.Addr[3], - pConfigData->StationPort, - pConfigData->RemoteAddress.Addr[0], - pConfigData->RemoteAddress.Addr[1], - pConfigData->RemoteAddress.Addr[2], - pConfigData->RemoteAddress.Addr[3], - pConfigData->RemotePort )); - pPort->bConfigured = TRUE; - pSocket->bConfigured = TRUE; - - // - // Start the first read on the port - // - EslSocketRxStart ( pPort ); - - // - // The socket is connected - // - pSocket->State = SOCKET_STATE_CONNECTED; - pSocket->errno = 0; - } - - // - // Set the next port - // - pPort = pNextPort; - } - } - - // - // Determine the socket configuration status - // - Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED; - - // - // Return the port connected state. - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Buffer data for transmission over a network connection. - - This routine buffers data for the transmit engine in the normal - data queue. When the \ref TransmitEngine has resources, this - routine will start the transmission of the next buffer on the - network connection. - - This routine is called by ::EslSocketTransmit to buffer - data for transmission. The data is copied into a local buffer - freeing the application buffer for reuse upon return. When - necessary, this routine starts the transmit engine that - performs the data transmission on the network connection. The - transmit engine transmits the data a packet at a time over the - network connection. - - Transmission errors are returned during the next transmission or - during the close operation. Only buffering errors are returned - during the current transmission attempt. - - @param [in] pSocket Address of an ::ESL_SOCKET structure - - @param [in] Flags Message control flags - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @param [in] pAddress Network address of the remote system address - - @param [in] AddressLength Length of the remote network address structure - - @retval EFI_SUCCESS - Socket data successfully buffered - -**/ -EFI_STATUS -EslUdp4TxBuffer ( - IN ESL_SOCKET * pSocket, - IN int Flags, - IN size_t BufferLength, - IN CONST UINT8 * pBuffer, - OUT size_t * pDataLength, - IN const struct sockaddr * pAddress, - IN socklen_t AddressLength - ) -{ - ESL_PACKET * pPacket; - ESL_PACKET * pPreviousPacket; - ESL_PORT * pPort; - const struct sockaddr_in * pRemoteAddress; - ESL_UDP4_CONTEXT * pUdp4; - size_t * pTxBytes; - ESL_UDP4_TX_DATA * pTxData; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume failure - // - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTCONN; - *pDataLength = 0; - - // - // Verify that the socket is connected - // - if ( SOCKET_STATE_CONNECTED == pSocket->State ) { - // - // Verify that there is enough room to buffer another - // transmit operation - // - pTxBytes = &pSocket->TxBytes; - if ( pSocket->MaxTxBuf > *pTxBytes ) { - // - // Locate the port - // - pPort = pSocket->pPortList; - while ( NULL != pPort ) { - // - // Determine the queue head - // - pUdp4 = &pPort->Context.Udp4; - - // - // Attempt to allocate the packet - // - Status = EslSocketPacketAllocate ( &pPacket, - sizeof ( pPacket->Op.Udp4Tx ) - - sizeof ( pPacket->Op.Udp4Tx.Buffer ) - + BufferLength, - 0, - DEBUG_TX ); - if ( !EFI_ERROR ( Status )) { - // - // Initialize the transmit operation - // - pTxData = &pPacket->Op.Udp4Tx; - pTxData->TxData.GatewayAddress = NULL; - pTxData->TxData.UdpSessionData = NULL; - pTxData->TxData.DataLength = (UINT32) BufferLength; - pTxData->TxData.FragmentCount = 1; - pTxData->TxData.FragmentTable[0].FragmentLength = (UINT32) BufferLength; - pTxData->TxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Udp4Tx.Buffer[0]; - pTxData->RetransmitCount = 0; - - // - // Set the remote system address if necessary - // - pTxData->TxData.UdpSessionData = NULL; - if ( NULL != pAddress ) { - pRemoteAddress = (const struct sockaddr_in *)pAddress; - pTxData->Session.SourceAddress.Addr[0] = pUdp4->ConfigData.StationAddress.Addr[0]; - pTxData->Session.SourceAddress.Addr[1] = pUdp4->ConfigData.StationAddress.Addr[1]; - pTxData->Session.SourceAddress.Addr[2] = pUdp4->ConfigData.StationAddress.Addr[2]; - pTxData->Session.SourceAddress.Addr[3] = pUdp4->ConfigData.StationAddress.Addr[3]; - pTxData->Session.SourcePort = 0; - pTxData->Session.DestinationAddress.Addr[0] = (UINT8)pRemoteAddress->sin_addr.s_addr; - pTxData->Session.DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 ); - pTxData->Session.DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 ); - pTxData->Session.DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 ); - pTxData->Session.DestinationPort = SwapBytes16 ( pRemoteAddress->sin_port ); - - // - // Use the remote system address when sending this packet - // - pTxData->TxData.UdpSessionData = &pTxData->Session; - } - - // - // Copy the data into the buffer - // - CopyMem ( &pPacket->Op.Udp4Tx.Buffer[0], - pBuffer, - BufferLength ); - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Display the request - // - DEBUG (( DEBUG_TX, - "Send %d bytes from 0x%08x to %d.%d.%d.%d:%d\r\n", - BufferLength, - pBuffer, - pTxData->Session.DestinationAddress.Addr[0], - pTxData->Session.DestinationAddress.Addr[1], - pTxData->Session.DestinationAddress.Addr[2], - pTxData->Session.DestinationAddress.Addr[3], - pTxData->Session.DestinationPort )); - - // - // Queue the data for transmission - // - pPacket->pNext = NULL; - pPreviousPacket = pSocket->pTxPacketListTail; - if ( NULL == pPreviousPacket ) { - pSocket->pTxPacketListHead = pPacket; - } - else { - pPreviousPacket->pNext = pPacket; - } - pSocket->pTxPacketListTail = pPacket; - DEBUG (( DEBUG_TX, - "0x%08x: Packet on transmit list\r\n", - pPacket )); - - // - // Account for the buffered data - // - *pTxBytes += BufferLength; - *pDataLength = BufferLength; - - // - // Start the transmit engine if it is idle - // - if ( NULL != pPort->pTxFree ) { - pPacket = pSocket->pTxPacketListHead; - EslSocketTxStart ( pPort, - &pSocket->pTxPacketListHead, - &pSocket->pTxPacketListTail, - &pPort->pTxActive, - &pPort->pTxFree ); - - // - // Ignore any transmit error - // - if ( EFI_ERROR ( pSocket->TxError )) { - DEBUG (( DEBUG_TX, - "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n", - pPort, - pPacket, - pSocket->TxError )); - } - pSocket->TxError = EFI_SUCCESS; - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - else { - // - // Packet allocation failed - // - pSocket->errno = ENOMEM; - break; - } - - // - // Set the next port - // - pPort = pPort->pLinkSocket; - } - } - else { - // - // Not enough buffer space available - // - pSocket->errno = EAGAIN; - Status = EFI_NOT_READY; - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the transmit completion - - This routine use ::EslSocketTxComplete to perform the transmit - completion processing for data packets. - - This routine is called by the UDPv4 network layer when a data - transmit request completes. - - @param [in] Event The normal transmit completion event - - @param [in] pIo Address of an ::ESL_IO_MGMT structure - -**/ -VOID -EslUdp4TxComplete ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ) -{ - UINT32 LengthInBytes; - ESL_PORT * pPort; - ESL_PACKET * pPacket; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the active transmit packet - // - pPacket = pIo->pPacket; - pPort = pIo->pPort; - pSocket = pPort->pSocket; - - // - // Get the transmit length and status - // - LengthInBytes = pPacket->Op.Udp4Tx.TxData.DataLength; - pSocket->TxBytes -= LengthInBytes; - Status = pIo->Token.Udp4Tx.Status; - - // - // Ignore the transmit error - // - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_TX, - "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n", - pPort, - pPacket, - Status )); - Status = EFI_SUCCESS; - } - - // - // Complete the transmit operation - // - EslSocketTxComplete ( pIo, - LengthInBytes, - Status, - "UDP ", - &pSocket->pTxPacketListHead, - &pSocket->pTxPacketListTail, - &pPort->pTxActive, - &pPort->pTxFree ); - DBG_EXIT ( ); -} - - -/** - Verify the adapter's IP address - - This support routine is called by EslSocketBindTest. - - @param [in] pPort Address of an ::ESL_PORT structure. - @param [in] pConfigData Address of the configuration data - - @retval EFI_SUCCESS - The IP address is valid - @retval EFI_NOT_STARTED - The IP address is invalid - - **/ -EFI_STATUS -EslUdp4VerifyLocalIpAddress ( - IN ESL_PORT * pPort, - IN EFI_UDP4_CONFIG_DATA * pConfigData - ) -{ - UINTN DataSize; - EFI_IP4_CONFIG2_INTERFACE_INFO * pIfInfo; - EFI_IP4_CONFIG2_PROTOCOL * pIpConfig2Protocol; - ESL_SERVICE * pService; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Use break instead of goto - // - pIfInfo = NULL; - for ( ; ; ) { - // - // Determine if the IP address is specified - // - DEBUG (( DEBUG_BIND, - "UseDefaultAddress: %s\r\n", - pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" )); - DEBUG (( DEBUG_BIND, - "Requested IP address: %d.%d.%d.%d\r\n", - pConfigData->StationAddress.Addr [ 0 ], - pConfigData->StationAddress.Addr [ 1 ], - pConfigData->StationAddress.Addr [ 2 ], - pConfigData->StationAddress.Addr [ 3 ])); - if ( pConfigData->UseDefaultAddress - || (( 0 == pConfigData->StationAddress.Addr [ 0 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 1 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 2 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 3 ]))) - { - Status = EFI_SUCCESS; - break; - } - - // - // Open the configuration protocol - // - pService = pPort->pService; - Status = gBS->OpenProtocol ( - pService->Controller, - &gEfiIp4Config2ProtocolGuid, - (VOID **)&pIpConfig2Protocol, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR, - "ERROR - IP Configuration Protocol not available, Status: %r\r\n", - Status )); - break; - } - - // - // Get the interface information size - // - DataSize = 0; - Status = pIpConfig2Protocol->GetData ( - pIpConfig2Protocol, - Ip4Config2DataTypeInterfaceInfo, - &DataSize, - NULL - ); - if ( EFI_BUFFER_TOO_SMALL != Status ) { - DEBUG (( DEBUG_ERROR, - "ERROR - Failed to get the interface information size, Status: %r\r\n", - Status )); - break; - } - - // - // Allocate the interface information buffer - // - pIfInfo = AllocatePool ( DataSize ); - if ( NULL == pIfInfo ) { - DEBUG (( DEBUG_ERROR, - "ERROR - Not enough memory to allocate the interface information buffer!\r\n" )); - Status = EFI_OUT_OF_RESOURCES; - break; - } - - // - // Get the interface info. - // - Status = pIpConfig2Protocol->GetData ( - pIpConfig2Protocol, - Ip4Config2DataTypeInterfaceInfo, - &DataSize, - pIfInfo - ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR, - "ERROR - Failed to return the interface info, Status: %r\r\n", - Status )); - break; - } - - // - // Display the current configuration - // - DEBUG (( DEBUG_BIND, - "Actual adapter IP address: %d.%d.%d.%d\r\n", - pIfInfo->StationAddress.Addr [ 0 ], - pIfInfo->StationAddress.Addr [ 1 ], - pIfInfo->StationAddress.Addr [ 2 ], - pIfInfo->StationAddress.Addr [ 3 ])); - - // - // Assume the port is not configured - // - Status = EFI_SUCCESS; - if (( pConfigData->StationAddress.Addr [ 0 ] == pIfInfo->StationAddress.Addr [ 0 ]) - && ( pConfigData->StationAddress.Addr [ 1 ] == pIfInfo->StationAddress.Addr [ 1 ]) - && ( pConfigData->StationAddress.Addr [ 2 ] == pIfInfo->StationAddress.Addr [ 2 ]) - && ( pConfigData->StationAddress.Addr [ 3 ] == pIfInfo->StationAddress.Addr [ 3 ])) { - break; - } - - // - // The IP address did not match - // - Status = EFI_NOT_STARTED; - break; - } - - // - // Free the buffer if necessary - // - if ( NULL != pIfInfo ) { - FreePool ( pIfInfo ); - } - - // - // Return the IP address status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Interface between the socket layer and the network specific - code that supports SOCK_DGRAM sockets over UDPv4. -**/ -CONST ESL_PROTOCOL_API cEslUdp4Api = { - "UDPv4", - IPPROTO_UDP, - OFFSET_OF ( ESL_PORT, Context.Udp4.ConfigData ), - OFFSET_OF ( ESL_LAYER, pUdp4List ), - OFFSET_OF ( struct sockaddr_in, sin_zero ), - sizeof ( struct sockaddr_in ), - AF_INET, - sizeof (((ESL_PACKET *)0 )->Op.Udp4Rx ), - sizeof (((ESL_PACKET *)0 )->Op.Udp4Rx ), - OFFSET_OF ( ESL_IO_MGMT, Token.Udp4Rx.Packet.RxData ), - FALSE, - EADDRINUSE, - NULL, // Accept - NULL, // ConnectPoll - NULL, // ConnectStart - EslUdp4SocketIsConfigured, - EslUdp4LocalAddressGet, - EslUdp4LocalAddressSet, - NULL, // Listen - NULL, // OptionGet - NULL, // OptionSet - EslUdp4PacketFree, - EslUdp4PortAllocate, - NULL, // PortClose, - NULL, // PortCloseOp - TRUE, - EslUdp4Receive, - EslUdp4RemoteAddressGet, - EslUdp4RemoteAddressSet, - EslUdp4RxComplete, - NULL, // RxStart - EslUdp4TxBuffer, - EslUdp4TxComplete, - NULL, // TxOobComplete - (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslUdp4VerifyLocalIpAddress -}; diff --git a/StdLib/EfiSocketLib/Udp6.c b/StdLib/EfiSocketLib/Udp6.c deleted file mode 100644 index 34df064941..0000000000 --- a/StdLib/EfiSocketLib/Udp6.c +++ /dev/null @@ -1,1379 +0,0 @@ -/** @file - Implement the UDP4 driver support for the socket layer. - - Copyright (c) 2011, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "Socket.h" - - -/** - Get the local socket address - - This routine returns the IPv6 address and UDP port number associated - with the local socket. - - This routine is called by ::EslSocketGetLocalAddress to determine the - network address for the SOCK_DGRAM socket. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [out] pSockAddr Network address to receive the local system address - -**/ -VOID -EslUdp6LocalAddressGet ( - IN ESL_PORT * pPort, - OUT struct sockaddr * pSockAddr - ) -{ - struct sockaddr_in6 * pLocalAddress; - ESL_UDP6_CONTEXT * pUdp6; - - DBG_ENTER ( ); - - // - // Return the local address - // - pUdp6 = &pPort->Context.Udp6; - pLocalAddress = (struct sockaddr_in6 *)pSockAddr; - pLocalAddress->sin6_family = AF_INET6; - pLocalAddress->sin6_port = SwapBytes16 ( pUdp6->ConfigData.StationPort ); - CopyMem ( &pLocalAddress->sin6_addr, - &pUdp6->ConfigData.StationAddress.Addr[0], - sizeof ( pLocalAddress->sin6_addr )); - - DBG_EXIT ( ); -} - - -/** - Set the local port address. - - This routine sets the local port address. - - This support routine is called by ::EslSocketPortAllocate. - - @param [in] pPort Address of an ESL_PORT structure - @param [in] pSockAddr Address of a sockaddr structure that contains the - connection point on the local machine. An IPv6 address - of INADDR_ANY specifies that the connection is made to - all of the network stacks on the platform. Specifying a - specific IPv6 address restricts the connection to the - network stack supporting that address. Specifying zero - for the port causes the network layer to assign a port - number from the dynamic range. Specifying a specific - port number causes the network layer to use that port. - - @param [in] bBindTest TRUE = run bind testing - - @retval EFI_SUCCESS The operation was successful - - **/ -EFI_STATUS -EslUdp6LocalAddressSet ( - IN ESL_PORT * pPort, - IN CONST struct sockaddr * pSockAddr, - IN BOOLEAN bBindTest - ) -{ - EFI_UDP6_CONFIG_DATA * pConfig; - CONST struct sockaddr_in6 * pIpAddress; - CONST UINT8 * pIPv6Address; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Set the local address - // - pIpAddress = (struct sockaddr_in6 *)pSockAddr; - pIPv6Address = (UINT8 *)&pIpAddress->sin6_addr; - pConfig = &pPort->Context.Udp6.ConfigData; - CopyMem ( &pConfig->StationAddress, - pIPv6Address, - sizeof ( pConfig->StationAddress )); - - // - // Validate the IP address - // - pConfig->StationPort = 0; - Status = bBindTest ? EslSocketBindTest ( pPort, EADDRNOTAVAIL ) - : EFI_SUCCESS; - if ( !EFI_ERROR ( Status )) { - // - // Set the port number - // - pConfig->StationPort = SwapBytes16 ( pIpAddress->sin6_port ); - pPort->pSocket->bAddressSet = TRUE; - - // - // Display the local address - // - DEBUG (( DEBUG_BIND, - "0x%08x: Port, Local UDP6 Address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", - pPort, - pConfig->StationAddress.Addr[0], - pConfig->StationAddress.Addr[1], - pConfig->StationAddress.Addr[2], - pConfig->StationAddress.Addr[3], - pConfig->StationAddress.Addr[4], - pConfig->StationAddress.Addr[5], - pConfig->StationAddress.Addr[6], - pConfig->StationAddress.Addr[7], - pConfig->StationAddress.Addr[8], - pConfig->StationAddress.Addr[9], - pConfig->StationAddress.Addr[10], - pConfig->StationAddress.Addr[11], - pConfig->StationAddress.Addr[12], - pConfig->StationAddress.Addr[13], - pConfig->StationAddress.Addr[14], - pConfig->StationAddress.Addr[15], - pConfig->StationPort )); - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Free a receive packet - - This routine performs the network specific operations necessary - to free a receive packet. - - This routine is called by ::EslSocketPortCloseTxDone to free a - receive packet. - - @param [in] pPacket Address of an ::ESL_PACKET structure. - @param [in, out] pRxBytes Address of the count of RX bytes - -**/ -VOID -EslUdp6PacketFree ( - IN ESL_PACKET * pPacket, - IN OUT size_t * pRxBytes - ) -{ - EFI_UDP6_RECEIVE_DATA * pRxData; - - DBG_ENTER ( ); - - // - // Account for the receive bytes - // - pRxData = pPacket->Op.Udp6Rx.pRxData; - *pRxBytes -= pRxData->DataLength; - - // - // Disconnect the buffer from the packet - // - pPacket->Op.Udp6Rx.pRxData = NULL; - - // - // Return the buffer to the UDP6 driver - // - gBS->SignalEvent ( pRxData->RecycleSignal ); - DBG_EXIT ( ); -} - - -/** - Initialize the network specific portions of an ::ESL_PORT structure. - - This routine initializes the network specific portions of an - ::ESL_PORT structure for use by the socket. - - This support routine is called by ::EslSocketPortAllocate - to connect the socket with the underlying network adapter - running the UDPv4 protocol. - - @param [in] pPort Address of an ESL_PORT structure - @param [in] DebugFlags Flags for debug messages - - @retval EFI_SUCCESS - Socket successfully created - - **/ -EFI_STATUS -EslUdp6PortAllocate ( - IN ESL_PORT * pPort, - IN UINTN DebugFlags - ) -{ - EFI_UDP6_CONFIG_DATA * pConfig; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Initialize the port - // - pSocket = pPort->pSocket; - pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Udp6Tx.TxData ); - pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Udp6Tx.Event ); - pSocket->TxTokenOffset = OFFSET_OF ( EFI_UDP6_COMPLETION_TOKEN, Packet.TxData ); - - // - // Save the cancel, receive and transmit addresses - // - pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.UDPv6->Configure; - pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.UDPv6->Cancel; - pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.UDPv6->Poll; - pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.UDPv6->Receive; - pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.UDPv6->Transmit; - - // - // Do not drop packets - // - pConfig = &pPort->Context.Udp6.ConfigData; - pConfig->ReceiveTimeout = 0; - pConfig->ReceiveTimeout = pConfig->ReceiveTimeout; - - // - // Set the configuration flags - // - pConfig->AllowDuplicatePort = TRUE; - pConfig->AcceptAnyPort = FALSE; - pConfig->AcceptPromiscuous = FALSE; - pConfig->HopLimit = 255; - pConfig->TrafficClass = 0; - - Status = EFI_SUCCESS; - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Receive data from a network connection. - - This routine attempts to return buffered data to the caller. The - data is removed from the urgent queue if the message flag MSG_OOB - is specified, otherwise data is removed from the normal queue. - See the \ref ReceiveEngine section. - - This routine is called by ::EslSocketReceive to handle the network - specific receive operation to support SOCK_DGRAM sockets. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [in] pPacket Address of an ::ESL_PACKET structure. - - @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @param [out] pAddress Network address to receive the remote system address - - @param [out] pSkipBytes Address to receive the number of bytes skipped - - @return Returns the address of the next free byte in the buffer. - - **/ -UINT8 * -EslUdp6Receive ( - IN ESL_PORT * pPort, - IN ESL_PACKET * pPacket, - IN BOOLEAN * pbConsumePacket, - IN size_t BufferLength, - IN UINT8 * pBuffer, - OUT size_t * pDataLength, - OUT struct sockaddr * pAddress, - OUT size_t * pSkipBytes - ) -{ - size_t DataBytes; - struct sockaddr_in6 * pRemoteAddress; - EFI_UDP6_RECEIVE_DATA * pRxData; - - DBG_ENTER ( ); - - pRxData = pPacket->Op.Udp6Rx.pRxData; - // - // Return the remote system address if requested - // - if ( NULL != pAddress ) { - // - // Build the remote address - // - DEBUG (( DEBUG_RX, - "Getting packet remote address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", - pRxData->UdpSession.SourceAddress.Addr[0], - pRxData->UdpSession.SourceAddress.Addr[1], - pRxData->UdpSession.SourceAddress.Addr[2], - pRxData->UdpSession.SourceAddress.Addr[3], - pRxData->UdpSession.SourceAddress.Addr[4], - pRxData->UdpSession.SourceAddress.Addr[5], - pRxData->UdpSession.SourceAddress.Addr[6], - pRxData->UdpSession.SourceAddress.Addr[7], - pRxData->UdpSession.SourceAddress.Addr[8], - pRxData->UdpSession.SourceAddress.Addr[9], - pRxData->UdpSession.SourceAddress.Addr[10], - pRxData->UdpSession.SourceAddress.Addr[11], - pRxData->UdpSession.SourceAddress.Addr[12], - pRxData->UdpSession.SourceAddress.Addr[13], - pRxData->UdpSession.SourceAddress.Addr[14], - pRxData->UdpSession.SourceAddress.Addr[15], - pRxData->UdpSession.SourcePort )); - pRemoteAddress = (struct sockaddr_in6 *)pAddress; - CopyMem ( &pRemoteAddress->sin6_addr, - &pRxData->UdpSession.SourceAddress.Addr[0], - sizeof ( pRemoteAddress->sin6_addr )); - pRemoteAddress->sin6_port = SwapBytes16 ( pRxData->UdpSession.SourcePort ); - } - - // - // Copy the received data - // - pBuffer = EslSocketCopyFragmentedBuffer ( pRxData->FragmentCount, - (EFI_IP4_FRAGMENT_DATA *)&pRxData->FragmentTable[0], - BufferLength, - pBuffer, - &DataBytes ); - - // - // Determine if the data is being read - // - if ( *pbConsumePacket ) { - // - // Display for the bytes consumed - // - DEBUG (( DEBUG_RX, - "0x%08x: Port account for 0x%08x bytes\r\n", - pPort, - DataBytes )); - - // - // Account for any discarded data - // - *pSkipBytes = pRxData->DataLength - DataBytes; - } - - // - // Return the data length and the buffer address - // - *pDataLength = DataBytes; - DBG_EXIT_HEX ( pBuffer ); - return pBuffer; -} - - -/** - Get the remote socket address - - This routine returns the address of the remote connection point - associated with the SOCK_DGRAM socket. - - This routine is called by ::EslSocketGetPeerAddress to detemine - the UDPv4 address and port number associated with the network adapter. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [out] pAddress Network address to receive the remote system address - -**/ -VOID -EslUdp6RemoteAddressGet ( - IN ESL_PORT * pPort, - OUT struct sockaddr * pAddress - ) -{ - struct sockaddr_in6 * pRemoteAddress; - ESL_UDP6_CONTEXT * pUdp6; - - DBG_ENTER ( ); - - // - // Return the remote address - // - pUdp6 = &pPort->Context.Udp6; - pRemoteAddress = (struct sockaddr_in6 *)pAddress; - pRemoteAddress->sin6_family = AF_INET6; - pRemoteAddress->sin6_port = SwapBytes16 ( pUdp6->ConfigData.RemotePort ); - CopyMem ( &pRemoteAddress->sin6_addr, - &pUdp6->ConfigData.RemoteAddress.Addr[0], - sizeof ( pRemoteAddress->sin6_addr )); - - DBG_EXIT ( ); -} - - -/** - Set the remote address - - This routine sets the remote address in the port. - - This routine is called by ::EslSocketConnect to specify the - remote network address. - - @param [in] pPort Address of an ::ESL_PORT structure. - - @param [in] pSockAddr Network address of the remote system. - - @param [in] SockAddrLength Length in bytes of the network address. - - @retval EFI_SUCCESS The operation was successful - - **/ -EFI_STATUS -EslUdp6RemoteAddressSet ( - IN ESL_PORT * pPort, - IN CONST struct sockaddr * pSockAddr, - IN socklen_t SockAddrLength - ) -{ - CONST struct sockaddr_in6 * pRemoteAddress; - ESL_UDP6_CONTEXT * pUdp6; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Set the remote address - // - pUdp6 = &pPort->Context.Udp6; - pRemoteAddress = (struct sockaddr_in6 *)pSockAddr; - CopyMem ( &pUdp6->ConfigData.RemoteAddress, - &pRemoteAddress->sin6_addr, - sizeof ( pUdp6->ConfigData.RemoteAddress )); - pUdp6->ConfigData.RemotePort = SwapBytes16 ( pRemoteAddress->sin6_port ); - Status = EFI_SUCCESS; - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the receive completion - - This routine keeps the UDPv4 driver's buffer and queues it in - in FIFO order to the data queue. The UDP6 driver's buffer will - be returned by either ::EslUdp6Receive or ::EslSocketPortCloseTxDone. - See the \ref ReceiveEngine section. - - This routine is called by the UDPv4 driver when data is - received. - - @param [in] Event The receive completion event - - @param [in] pIo Address of an ::ESL_IO_MGMT structure - -**/ -VOID -EslUdp6RxComplete ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ) -{ - size_t LengthInBytes; - ESL_PACKET * pPacket; - EFI_UDP6_RECEIVE_DATA * pRxData; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Get the operation status. - // - Status = pIo->Token.Udp6Rx.Status; - - // - // Get the packet length - // - pRxData = pIo->Token.Udp6Rx.Packet.RxData; - LengthInBytes = pRxData->DataLength; - - // - // +--------------------+ +-----------------------+ - // | ESL_IO_MGMT | | Data Buffer | - // | | | (Driver owned) | - // | +---------------+ +-----------------------+ - // | | Token | ^ - // | | Rx Event | | - // | | | +-----------------------+ - // | | RxData --> | EFI_UDP6_RECEIVE_DATA | - // +----+---------------+ | (Driver owned) | - // +-----------------------+ - // +--------------------+ ^ - // | ESL_PACKET | . - // | | . - // | +---------------+ . - // | | pRxData --> NULL ....... - // +----+---------------+ - // - // - // Save the data in the packet - // - pPacket = pIo->pPacket; - pPacket->Op.Udp6Rx.pRxData = pRxData; - - // - // Complete this request - // - EslSocketRxComplete ( pIo, Status, LengthInBytes, FALSE ); - DBG_EXIT ( ); -} - - -/** - Determine if the socket is configured. - - This routine uses the flag ESL_SOCKET::bConfigured to determine - if the network layer's configuration routine has been called. - This routine calls the bind and configuration routines if they - were not already called. After the port is configured, the - \ref ReceiveEngine is started. - - This routine is called by EslSocketIsConfigured to verify - that the socket is configured. - - @param [in] pSocket Address of an ::ESL_SOCKET structure - - @retval EFI_SUCCESS - The port is connected - @retval EFI_NOT_STARTED - The port is not connected - - **/ - EFI_STATUS - EslUdp6SocketIsConfigured ( - IN ESL_SOCKET * pSocket - ) -{ - EFI_UDP6_CONFIG_DATA * pConfigData; - ESL_PORT * pPort; - ESL_PORT * pNextPort; - ESL_UDP6_CONTEXT * pUdp6; - EFI_UDP6_PROTOCOL * pUdp6Protocol; - EFI_STATUS Status; - struct sockaddr_in6 LocalAddress; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Configure the port if necessary - // - if ( !pSocket->bConfigured ) { - // - // Fill in the port list if necessary - // - pSocket->errno = ENETDOWN; - if ( NULL == pSocket->pPortList ) { - ZeroMem ( &LocalAddress, sizeof ( LocalAddress )); - LocalAddress.sin6_len = sizeof ( LocalAddress ); - LocalAddress.sin6_family = AF_INET6; - Status = EslSocketBind ( &pSocket->SocketProtocol, - (struct sockaddr *)&LocalAddress, - LocalAddress.sin6_len, - &pSocket->errno ); - } - - // - // Walk the port list - // - pPort = pSocket->pPortList; - while ( NULL != pPort ) { - // - // Attempt to configure the port - // - pNextPort = pPort->pLinkSocket; - pUdp6 = &pPort->Context.Udp6; - pUdp6Protocol = pPort->pProtocol.UDPv6; - pConfigData = &pUdp6->ConfigData; - DEBUG (( DEBUG_TX, - "0x%08x: pPort Configuring for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> ", - pPort, - pConfigData->StationAddress.Addr[0], - pConfigData->StationAddress.Addr[1], - pConfigData->StationAddress.Addr[2], - pConfigData->StationAddress.Addr[3], - pConfigData->StationAddress.Addr[4], - pConfigData->StationAddress.Addr[5], - pConfigData->StationAddress.Addr[6], - pConfigData->StationAddress.Addr[7], - pConfigData->StationAddress.Addr[8], - pConfigData->StationAddress.Addr[9], - pConfigData->StationAddress.Addr[10], - pConfigData->StationAddress.Addr[11], - pConfigData->StationAddress.Addr[12], - pConfigData->StationAddress.Addr[13], - pConfigData->StationAddress.Addr[14], - pConfigData->StationAddress.Addr[15], - pConfigData->StationPort )); - DEBUG (( DEBUG_TX, - "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", - pConfigData->RemoteAddress.Addr[0], - pConfigData->RemoteAddress.Addr[1], - pConfigData->RemoteAddress.Addr[2], - pConfigData->RemoteAddress.Addr[3], - pConfigData->RemoteAddress.Addr[4], - pConfigData->RemoteAddress.Addr[5], - pConfigData->RemoteAddress.Addr[6], - pConfigData->RemoteAddress.Addr[7], - pConfigData->RemoteAddress.Addr[8], - pConfigData->RemoteAddress.Addr[9], - pConfigData->RemoteAddress.Addr[10], - pConfigData->RemoteAddress.Addr[11], - pConfigData->RemoteAddress.Addr[12], - pConfigData->RemoteAddress.Addr[13], - pConfigData->RemoteAddress.Addr[14], - pConfigData->RemoteAddress.Addr[15], - pConfigData->RemotePort )); - Status = pUdp6Protocol->Configure ( pUdp6Protocol, - pConfigData ); - if ( !EFI_ERROR ( Status )) { - // - // Update the configuration data - // - Status = pUdp6Protocol->GetModeData ( pUdp6Protocol, - pConfigData, - NULL, - NULL, - NULL ); - } - if ( EFI_ERROR ( Status )) { - if ( !pSocket->bConfigured ) { - DEBUG (( DEBUG_LISTEN, - "ERROR - Failed to configure the Udp6 port, Status: %r\r\n", - Status )); - switch ( Status ) { - case EFI_ACCESS_DENIED: - pSocket->errno = EACCES; - break; - - default: - case EFI_DEVICE_ERROR: - pSocket->errno = EIO; - break; - - case EFI_INVALID_PARAMETER: - pSocket->errno = EADDRNOTAVAIL; - break; - - case EFI_NO_MAPPING: - pSocket->errno = EAFNOSUPPORT; - break; - - case EFI_OUT_OF_RESOURCES: - pSocket->errno = ENOBUFS; - break; - - case EFI_UNSUPPORTED: - pSocket->errno = EOPNOTSUPP; - break; - } - } - } - else { - DEBUG (( DEBUG_TX, - "0x%08x: pPort Configured for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> ", - pPort, - pConfigData->StationAddress.Addr[0], - pConfigData->StationAddress.Addr[1], - pConfigData->StationAddress.Addr[2], - pConfigData->StationAddress.Addr[3], - pConfigData->StationAddress.Addr[4], - pConfigData->StationAddress.Addr[5], - pConfigData->StationAddress.Addr[6], - pConfigData->StationAddress.Addr[7], - pConfigData->StationAddress.Addr[8], - pConfigData->StationAddress.Addr[9], - pConfigData->StationAddress.Addr[10], - pConfigData->StationAddress.Addr[11], - pConfigData->StationAddress.Addr[12], - pConfigData->StationAddress.Addr[13], - pConfigData->StationAddress.Addr[14], - pConfigData->StationAddress.Addr[15], - pConfigData->StationPort )); - DEBUG (( DEBUG_TX, - "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", - pConfigData->RemoteAddress.Addr[0], - pConfigData->RemoteAddress.Addr[1], - pConfigData->RemoteAddress.Addr[2], - pConfigData->RemoteAddress.Addr[3], - pConfigData->RemoteAddress.Addr[4], - pConfigData->RemoteAddress.Addr[5], - pConfigData->RemoteAddress.Addr[6], - pConfigData->RemoteAddress.Addr[7], - pConfigData->RemoteAddress.Addr[8], - pConfigData->RemoteAddress.Addr[9], - pConfigData->RemoteAddress.Addr[10], - pConfigData->RemoteAddress.Addr[11], - pConfigData->RemoteAddress.Addr[12], - pConfigData->RemoteAddress.Addr[13], - pConfigData->RemoteAddress.Addr[14], - pConfigData->RemoteAddress.Addr[15], - pConfigData->RemotePort )); - pPort->bConfigured = TRUE; - pSocket->bConfigured = TRUE; - - // - // Start the first read on the port - // - EslSocketRxStart ( pPort ); - - // - // The socket is connected - // - pSocket->State = SOCKET_STATE_CONNECTED; - pSocket->errno = 0; - } - - // - // Set the next port - // - pPort = pNextPort; - } - } - - // - // Determine the socket configuration status - // - Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED; - - // - // Return the port connected state. - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Buffer data for transmission over a network connection. - - This routine buffers data for the transmit engine in the normal - data queue. When the \ref TransmitEngine has resources, this - routine will start the transmission of the next buffer on the - network connection. - - This routine is called by ::EslSocketTransmit to buffer - data for transmission. The data is copied into a local buffer - freeing the application buffer for reuse upon return. When - necessary, this routine starts the transmit engine that - performs the data transmission on the network connection. The - transmit engine transmits the data a packet at a time over the - network connection. - - Transmission errors are returned during the next transmission or - during the close operation. Only buffering errors are returned - during the current transmission attempt. - - @param [in] pSocket Address of an ::ESL_SOCKET structure - - @param [in] Flags Message control flags - - @param [in] BufferLength Length of the the buffer - - @param [in] pBuffer Address of a buffer to receive the data. - - @param [in] pDataLength Number of received data bytes in the buffer. - - @param [in] pAddress Network address of the remote system address - - @param [in] AddressLength Length of the remote network address structure - - @retval EFI_SUCCESS - Socket data successfully buffered - -**/ -EFI_STATUS -EslUdp6TxBuffer ( - IN ESL_SOCKET * pSocket, - IN int Flags, - IN size_t BufferLength, - IN CONST UINT8 * pBuffer, - OUT size_t * pDataLength, - IN const struct sockaddr * pAddress, - IN socklen_t AddressLength - ) -{ - ESL_PACKET * pPacket; - ESL_PACKET * pPreviousPacket; - ESL_PORT * pPort; - const struct sockaddr_in6 * pRemoteAddress; - ESL_UDP6_CONTEXT * pUdp6; - size_t * pTxBytes; - ESL_UDP6_TX_DATA * pTxData; - EFI_STATUS Status; - EFI_TPL TplPrevious; - - DBG_ENTER ( ); - - // - // Assume failure - // - Status = EFI_UNSUPPORTED; - pSocket->errno = ENOTCONN; - *pDataLength = 0; - - // - // Verify that the socket is connected - // - if ( SOCKET_STATE_CONNECTED == pSocket->State ) { - // - // Verify that there is enough room to buffer another - // transmit operation - // - pTxBytes = &pSocket->TxBytes; - if ( pSocket->MaxTxBuf > *pTxBytes ) { - // - // Locate the port - // - pPort = pSocket->pPortList; - while ( NULL != pPort ) { - // - // Determine the queue head - // - pUdp6 = &pPort->Context.Udp6; - - // - // Attempt to allocate the packet - // - Status = EslSocketPacketAllocate ( &pPacket, - sizeof ( pPacket->Op.Udp6Tx ) - - sizeof ( pPacket->Op.Udp6Tx.Buffer ) - + BufferLength, - 0, - DEBUG_TX ); - if ( !EFI_ERROR ( Status )) { - // - // Initialize the transmit operation - // - pTxData = &pPacket->Op.Udp6Tx; - pTxData->TxData.UdpSessionData = NULL; - pTxData->TxData.DataLength = (UINT32) BufferLength; - pTxData->TxData.FragmentCount = 1; - pTxData->TxData.FragmentTable[0].FragmentLength = (UINT32) BufferLength; - pTxData->TxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Udp6Tx.Buffer[0]; - - // - // Set the remote system address if necessary - // - pTxData->TxData.UdpSessionData = NULL; - if ( NULL != pAddress ) { - pRemoteAddress = (const struct sockaddr_in6 *)pAddress; - CopyMem ( &pTxData->Session.SourceAddress, - &pUdp6->ConfigData.StationAddress, - sizeof ( pTxData->Session.SourceAddress )); - pTxData->Session.SourcePort = 0; - CopyMem ( &pTxData->Session.DestinationAddress, - &pRemoteAddress->sin6_addr, - sizeof ( pTxData->Session.DestinationAddress )); - pTxData->Session.DestinationPort = SwapBytes16 ( pRemoteAddress->sin6_port ); - - // - // Use the remote system address when sending this packet - // - pTxData->TxData.UdpSessionData = &pTxData->Session; - } - - // - // Copy the data into the buffer - // - CopyMem ( &pPacket->Op.Udp6Tx.Buffer[0], - pBuffer, - BufferLength ); - - // - // Synchronize with the socket layer - // - RAISE_TPL ( TplPrevious, TPL_SOCKETS ); - - // - // Display the request - // - DEBUG (( DEBUG_TX, - "Send %d bytes from 0x%08x to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", - BufferLength, - pBuffer, - pTxData->Session.DestinationAddress.Addr[0], - pTxData->Session.DestinationAddress.Addr[1], - pTxData->Session.DestinationAddress.Addr[2], - pTxData->Session.DestinationAddress.Addr[3], - pTxData->Session.DestinationAddress.Addr[4], - pTxData->Session.DestinationAddress.Addr[5], - pTxData->Session.DestinationAddress.Addr[6], - pTxData->Session.DestinationAddress.Addr[7], - pTxData->Session.DestinationAddress.Addr[8], - pTxData->Session.DestinationAddress.Addr[9], - pTxData->Session.DestinationAddress.Addr[10], - pTxData->Session.DestinationAddress.Addr[11], - pTxData->Session.DestinationAddress.Addr[12], - pTxData->Session.DestinationAddress.Addr[13], - pTxData->Session.DestinationAddress.Addr[14], - pTxData->Session.DestinationAddress.Addr[15], - pTxData->Session.DestinationPort )); - - // - // Queue the data for transmission - // - pPacket->pNext = NULL; - pPreviousPacket = pSocket->pTxPacketListTail; - if ( NULL == pPreviousPacket ) { - pSocket->pTxPacketListHead = pPacket; - } - else { - pPreviousPacket->pNext = pPacket; - } - pSocket->pTxPacketListTail = pPacket; - DEBUG (( DEBUG_TX, - "0x%08x: Packet on transmit list\r\n", - pPacket )); - - // - // Account for the buffered data - // - *pTxBytes += BufferLength; - *pDataLength = BufferLength; - - // - // Start the transmit engine if it is idle - // - if ( NULL != pPort->pTxFree ) { - EslSocketTxStart ( pPort, - &pSocket->pTxPacketListHead, - &pSocket->pTxPacketListTail, - &pPort->pTxActive, - &pPort->pTxFree ); - - // - // Ignore any transmit error - // - if ( EFI_ERROR ( pSocket->TxError )) { - DEBUG (( DEBUG_TX, - "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n", - pPort, - pPacket, - pSocket->TxError )); - } - pSocket->TxError = EFI_SUCCESS; - } - - // - // Release the socket layer synchronization - // - RESTORE_TPL ( TplPrevious ); - } - else { - // - // Packet allocation failed - // - pSocket->errno = ENOMEM; - break; - } - - // - // Set the next port - // - pPort = pPort->pLinkSocket; - } - } - else { - // - // Not enough buffer space available - // - pSocket->errno = EAGAIN; - Status = EFI_NOT_READY; - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Process the transmit completion - - This routine use ::EslSocketTxComplete to perform the transmit - completion processing for data packets. - - This routine is called by the UDPv4 network layer when a data - transmit request completes. - - @param [in] Event The normal transmit completion event - - @param [in] pIo Address of an ::ESL_IO_MGMT structure - -**/ -VOID -EslUdp6TxComplete ( - IN EFI_EVENT Event, - IN ESL_IO_MGMT * pIo - ) -{ - UINT32 LengthInBytes; - ESL_PORT * pPort; - ESL_PACKET * pPacket; - ESL_SOCKET * pSocket; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Locate the active transmit packet - // - pPacket = pIo->pPacket; - pPort = pIo->pPort; - pSocket = pPort->pSocket; - - // - // Get the transmit length and status - // - LengthInBytes = pPacket->Op.Udp6Tx.TxData.DataLength; - pSocket->TxBytes -= LengthInBytes; - Status = pIo->Token.Udp6Tx.Status; - - // - // Ignore the transmit error - // - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_TX, - "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n", - pPort, - pPacket, - Status )); - Status = EFI_SUCCESS; - } - - // - // Complete the transmit operation - // - EslSocketTxComplete ( pIo, - LengthInBytes, - Status, - "UDP ", - &pSocket->pTxPacketListHead, - &pSocket->pTxPacketListTail, - &pPort->pTxActive, - &pPort->pTxFree ); - DBG_EXIT ( ); -} - - -/** - Verify the adapter's IP address - - This support routine is called by EslSocketBindTest. - - @param [in] pPort Address of an ::ESL_PORT structure. - @param [in] pConfigData Address of the configuration data - - @retval EFI_SUCCESS - The IP address is valid - @retval EFI_NOT_STARTED - The IP address is invalid - - **/ -EFI_STATUS -EslUdp6VerifyLocalIpAddress ( - IN ESL_PORT * pPort, - IN EFI_UDP6_CONFIG_DATA * pConfigData - ) -{ - UINTN AddressCount; - EFI_IP6_ADDRESS_INFO * pAddressInfo; - UINTN DataSize; - EFI_IP6_CONFIG_INTERFACE_INFO * pIpConfigData; - EFI_IP6_CONFIG_PROTOCOL * pIpConfigProtocol; - ESL_SERVICE * pService; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Use break instead of goto - // - pIpConfigData = NULL; - for ( ; ; ) { - // - // Determine if the IP address is specified - // - DEBUG (( DEBUG_BIND, - "Requested IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n", - pConfigData->StationAddress.Addr[0], - pConfigData->StationAddress.Addr[1], - pConfigData->StationAddress.Addr[2], - pConfigData->StationAddress.Addr[3], - pConfigData->StationAddress.Addr[4], - pConfigData->StationAddress.Addr[5], - pConfigData->StationAddress.Addr[6], - pConfigData->StationAddress.Addr[7], - pConfigData->StationAddress.Addr[8], - pConfigData->StationAddress.Addr[9], - pConfigData->StationAddress.Addr[10], - pConfigData->StationAddress.Addr[11], - pConfigData->StationAddress.Addr[12], - pConfigData->StationAddress.Addr[13], - pConfigData->StationAddress.Addr[14], - pConfigData->StationAddress.Addr[15])); - if (( 0 == pConfigData->StationAddress.Addr [ 0 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 1 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 2 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 3 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 4 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 5 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 6 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 7 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 8 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 9 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 10 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 11 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 12 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 13 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 14 ]) - && ( 0 == pConfigData->StationAddress.Addr [ 15 ])) - { - Status = EFI_SUCCESS; - break; - } - - // - // Open the configuration protocol - // - pService = pPort->pService; - Status = gBS->OpenProtocol ( pService->Controller, - &gEfiIp6ConfigProtocolGuid, - (VOID **)&pIpConfigProtocol, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR, - "ERROR - IP Configuration Protocol not available, Status: %r\r\n", - Status )); - break; - } - - // - // Get the IP configuration data size - // - DataSize = 0; - Status = pIpConfigProtocol->GetData ( pIpConfigProtocol, - Ip6ConfigDataTypeInterfaceInfo, - &DataSize, - NULL ); - if ( EFI_BUFFER_TOO_SMALL != Status ) { - DEBUG (( DEBUG_ERROR, - "ERROR - Failed to get IP Configuration data size, Status: %r\r\n", - Status )); - break; - } - - // - // Allocate the configuration data buffer - // - pIpConfigData = AllocatePool ( DataSize ); - if ( NULL == pIpConfigData ) { - DEBUG (( DEBUG_ERROR, - "ERROR - Not enough memory to allocate IP Configuration data!\r\n" )); - Status = EFI_OUT_OF_RESOURCES; - break; - } - - // - // Get the IP configuration - // - Status = pIpConfigProtocol->GetData ( pIpConfigProtocol, - Ip6ConfigDataTypeInterfaceInfo, - &DataSize, - pIpConfigData ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR, - "ERROR - Failed to return IP Configuration data, Status: %r\r\n", - Status )); - break; - } - - // - // Display the current configuration - // - DEBUG (( DEBUG_BIND, - "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n", - pIpConfigData->HwAddress.Addr [ 0 ], - pIpConfigData->HwAddress.Addr [ 1 ], - pIpConfigData->HwAddress.Addr [ 2 ], - pIpConfigData->HwAddress.Addr [ 3 ], - pIpConfigData->HwAddress.Addr [ 4 ], - pIpConfigData->HwAddress.Addr [ 5 ], - pIpConfigData->HwAddress.Addr [ 6 ], - pIpConfigData->HwAddress.Addr [ 7 ], - pIpConfigData->HwAddress.Addr [ 8 ], - pIpConfigData->HwAddress.Addr [ 9 ], - pIpConfigData->HwAddress.Addr [ 10 ], - pIpConfigData->HwAddress.Addr [ 11 ], - pIpConfigData->HwAddress.Addr [ 12 ], - pIpConfigData->HwAddress.Addr [ 13 ], - pIpConfigData->HwAddress.Addr [ 14 ], - pIpConfigData->HwAddress.Addr [ 15 ])); - - // - // Validate the hardware address - // - Status = EFI_SUCCESS; - if (( 16 == pIpConfigData->HwAddressSize ) - && ( pConfigData->StationAddress.Addr [ 0 ] == pIpConfigData->HwAddress.Addr [ 0 ]) - && ( pConfigData->StationAddress.Addr [ 1 ] == pIpConfigData->HwAddress.Addr [ 1 ]) - && ( pConfigData->StationAddress.Addr [ 2 ] == pIpConfigData->HwAddress.Addr [ 2 ]) - && ( pConfigData->StationAddress.Addr [ 3 ] == pIpConfigData->HwAddress.Addr [ 3 ]) - && ( pConfigData->StationAddress.Addr [ 4 ] == pIpConfigData->HwAddress.Addr [ 4 ]) - && ( pConfigData->StationAddress.Addr [ 5 ] == pIpConfigData->HwAddress.Addr [ 5 ]) - && ( pConfigData->StationAddress.Addr [ 6 ] == pIpConfigData->HwAddress.Addr [ 6 ]) - && ( pConfigData->StationAddress.Addr [ 7 ] == pIpConfigData->HwAddress.Addr [ 7 ]) - && ( pConfigData->StationAddress.Addr [ 8 ] == pIpConfigData->HwAddress.Addr [ 8 ]) - && ( pConfigData->StationAddress.Addr [ 9 ] == pIpConfigData->HwAddress.Addr [ 9 ]) - && ( pConfigData->StationAddress.Addr [ 10 ] == pIpConfigData->HwAddress.Addr [ 10 ]) - && ( pConfigData->StationAddress.Addr [ 11 ] == pIpConfigData->HwAddress.Addr [ 11 ]) - && ( pConfigData->StationAddress.Addr [ 12 ] == pIpConfigData->HwAddress.Addr [ 12 ]) - && ( pConfigData->StationAddress.Addr [ 13 ] == pIpConfigData->HwAddress.Addr [ 13 ]) - && ( pConfigData->StationAddress.Addr [ 14 ] == pIpConfigData->HwAddress.Addr [ 14 ]) - && ( pConfigData->StationAddress.Addr [ 15 ] == pIpConfigData->HwAddress.Addr [ 15 ])) { - break; - } - - // - // Walk the list of other IP addresses assigned to this adapter - // - for ( AddressCount = 0; pIpConfigData->AddressInfoCount > AddressCount; AddressCount += 1 ) { - pAddressInfo = &pIpConfigData->AddressInfo [ AddressCount ]; - - // - // Display the IP address - // - DEBUG (( DEBUG_BIND, - "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n", - pAddressInfo->Address.Addr [ 0 ], - pAddressInfo->Address.Addr [ 1 ], - pAddressInfo->Address.Addr [ 2 ], - pAddressInfo->Address.Addr [ 3 ], - pAddressInfo->Address.Addr [ 4 ], - pAddressInfo->Address.Addr [ 5 ], - pAddressInfo->Address.Addr [ 6 ], - pAddressInfo->Address.Addr [ 7 ], - pAddressInfo->Address.Addr [ 8 ], - pAddressInfo->Address.Addr [ 9 ], - pAddressInfo->Address.Addr [ 10 ], - pAddressInfo->Address.Addr [ 11 ], - pAddressInfo->Address.Addr [ 12 ], - pAddressInfo->Address.Addr [ 13 ], - pAddressInfo->Address.Addr [ 14 ], - pAddressInfo->Address.Addr [ 15 ])); - - // - // Validate the IP address - // - if (( pConfigData->StationAddress.Addr [ 0 ] == pAddressInfo->Address.Addr [ 0 ]) - && ( pConfigData->StationAddress.Addr [ 1 ] == pAddressInfo->Address.Addr [ 1 ]) - && ( pConfigData->StationAddress.Addr [ 2 ] == pAddressInfo->Address.Addr [ 2 ]) - && ( pConfigData->StationAddress.Addr [ 3 ] == pAddressInfo->Address.Addr [ 3 ]) - && ( pConfigData->StationAddress.Addr [ 4 ] == pAddressInfo->Address.Addr [ 4 ]) - && ( pConfigData->StationAddress.Addr [ 5 ] == pAddressInfo->Address.Addr [ 5 ]) - && ( pConfigData->StationAddress.Addr [ 6 ] == pAddressInfo->Address.Addr [ 6 ]) - && ( pConfigData->StationAddress.Addr [ 7 ] == pAddressInfo->Address.Addr [ 7 ]) - && ( pConfigData->StationAddress.Addr [ 8 ] == pAddressInfo->Address.Addr [ 8 ]) - && ( pConfigData->StationAddress.Addr [ 9 ] == pAddressInfo->Address.Addr [ 9 ]) - && ( pConfigData->StationAddress.Addr [ 10 ] == pAddressInfo->Address.Addr [ 10 ]) - && ( pConfigData->StationAddress.Addr [ 11 ] == pAddressInfo->Address.Addr [ 11 ]) - && ( pConfigData->StationAddress.Addr [ 12 ] == pAddressInfo->Address.Addr [ 12 ]) - && ( pConfigData->StationAddress.Addr [ 13 ] == pAddressInfo->Address.Addr [ 13 ]) - && ( pConfigData->StationAddress.Addr [ 14 ] == pAddressInfo->Address.Addr [ 14 ]) - && ( pConfigData->StationAddress.Addr [ 15 ] == pAddressInfo->Address.Addr [ 15 ])) { - break; - } - } - if ( pIpConfigData->AddressInfoCount > AddressCount ) { - break; - } - - // - // The IP address did not match - // - Status = EFI_NOT_STARTED; - break; - } - - // - // Free the buffer if necessary - // - if ( NULL != pIpConfigData ) { - FreePool ( pIpConfigData ); - } - - // - // Return the IP address status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Interface between the socket layer and the network specific - code that supports SOCK_DGRAM sockets over UDPv4. -**/ -CONST ESL_PROTOCOL_API cEslUdp6Api = { - "UDPv6", - IPPROTO_UDP, - OFFSET_OF ( ESL_PORT, Context.Udp6.ConfigData ), - OFFSET_OF ( ESL_LAYER, pUdp6List ), - sizeof ( struct sockaddr_in6 ), - sizeof ( struct sockaddr_in6 ), - AF_INET6, - sizeof (((ESL_PACKET *)0 )->Op.Udp6Rx ), - sizeof (((ESL_PACKET *)0 )->Op.Udp6Rx ), - OFFSET_OF ( ESL_IO_MGMT, Token.Udp6Rx.Packet.RxData ), - FALSE, - EADDRINUSE, - NULL, // Accept - NULL, // ConnectPoll - NULL, // ConnectStart - EslUdp6SocketIsConfigured, - EslUdp6LocalAddressGet, - EslUdp6LocalAddressSet, - NULL, // Listen - NULL, // OptionGet - NULL, // OptionSet - EslUdp6PacketFree, - EslUdp6PortAllocate, - NULL, // PortClose, - NULL, // PortCloseOp - TRUE, - EslUdp6Receive, - EslUdp6RemoteAddressGet, - EslUdp6RemoteAddressSet, - EslUdp6RxComplete, - NULL, // RxStart - EslUdp6TxBuffer, - EslUdp6TxComplete, - NULL, // TxOobComplete - (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslUdp6VerifyLocalIpAddress -}; diff --git a/StdLib/EfiSocketLib/UseEfiSocketLib.c b/StdLib/EfiSocketLib/UseEfiSocketLib.c deleted file mode 100644 index 060598af31..0000000000 --- a/StdLib/EfiSocketLib/UseEfiSocketLib.c +++ /dev/null @@ -1,376 +0,0 @@ -/** @file - Implement the connection to the EFI socket library - - Copyright (c) 2011, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "Socket.h" - - -/** - The following GUID values are only used when an application links - against EfiSocketLib. An alternative set of values exists in - SocketDxe\EntryUnload.c which the SocketDxe driver uses to coexist - with socket applications. - - Tag GUID - IPv4 in use by an application using EfiSocketLib -**/ -CONST EFI_GUID mEslIp4ServiceGuid __attribute__((weak)) = { - 0x9c756011, 0x5d44, 0x4ee0, { 0xbc, 0xe7, 0xc3, 0x82, 0x18, 0xfe, 0x39, 0x8d } -}; - - -/** - Tag GUID - IPv6 in use by an application using EfiSocketLib -**/ -CONST EFI_GUID mEslIp6ServiceGuid __attribute__((weak)) = { - 0xc51b2761, 0xc476, 0x45fe, { 0xbe, 0x61, 0xba, 0x4b, 0xcc, 0x32, 0xf2, 0x34 } -}; - - -/** - Tag GUID - TCPv4 in use by an application using EfiSocketLib -**/ -CONST EFI_GUID mEslTcp4ServiceGuid __attribute__((weak)) = { - 0xffc659c2, 0x4ef2, 0x4532, { 0xb8, 0x75, 0xcd, 0x9a, 0xa4, 0x27, 0x4c, 0xde } -}; - - -/** - Tag GUID - TCPv6 in use by an application using EfiSocketLib -**/ -CONST EFI_GUID mEslTcp6ServiceGuid __attribute__((weak)) = { - 0x279858a4, 0x4e9e, 0x4e53, { 0x93, 0x22, 0xf2, 0x54, 0xe0, 0x7e, 0xef, 0xd4 } -}; - - -/** - Tag GUID - UDPv4 in use by an application using EfiSocketLib -**/ -CONST EFI_GUID mEslUdp4ServiceGuid __attribute__((weak)) = { - 0x44e03a55, 0x8d97, 0x4511, { 0xbf, 0xef, 0xa, 0x8b, 0xc6, 0x2c, 0x25, 0xae } -}; - - -/** - Tag GUID - UDPv6 in use by an application using EfiSocketLib -**/ -CONST EFI_GUID mEslUdp6ServiceGuid __attribute__((weak)) = { - 0xaa4af677, 0x6efe, 0x477c, { 0x96, 0x68, 0xe8, 0x13, 0x9d, 0x2, 0xfd, 0x9b } -}; - - -/** - Free the socket resources - - This releases the socket resources allocated by calling - EslServiceGetProtocol. - - This routine is called from the ::close routine in BsdSocketLib - to release the socket resources. - - @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL - structure - - @return Value for ::errno, zero (0) indicates success. - - **/ -int -EslServiceFreeProtocol ( - IN EFI_SOCKET_PROTOCOL * pSocketProtocol - ) -{ - int RetVal; - - // - // Release the socket resources - // - EslSocketFree ( pSocketProtocol, &RetVal ); - - // - // Return the operation status - // - return RetVal; -} - - -/** - Connect to the EFI socket library - - This routine creates the ::ESL_SOCKET structure and returns - the API (::EFI_SOCKET_PROTOCOL address) to the socket file - system layer in BsdSocketLib. - - This routine is called from the ::socket routine in BsdSocketLib - to create the data structure and initialize the API for a socket. - Note that this implementation is only used by socket applications - that link directly to EslSocketLib. - - @param [in] ppSocketProtocol Address to receive the ::EFI_SOCKET_PROTOCOL - structure address - - @return Value for ::errno, zero (0) indicates success. - - **/ -int -EslServiceGetProtocol ( - IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol - ) -{ - EFI_HANDLE ChildHandle; - ESL_SOCKET * pSocket; - int RetVal; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Assume success - // - RetVal = 0; - - // - // Locate the socket protocol - // - ChildHandle = NULL; - Status = EslSocketAllocate ( &ChildHandle, - DEBUG_SOCKET, - &pSocket ); - if ( !EFI_ERROR ( Status )) { - *ppSocketProtocol = &pSocket->SocketProtocol; - } - else { - // - // No resources - // - RetVal = ENOMEM; - } - - // - // Return the operation status - // - DBG_EXIT_DEC ( RetVal ); - return RetVal; -} - - -/** - Connect to the network layer - - This routine is the constructor for the EfiSocketLib when the - library is linked directly to an application. This routine - walks the ::cEslSocketBinding table to create ::ESL_SERVICE - structures, associated with the network adapters, which this - routine links to the ::ESL_LAYER structure. - - This routine is called from ::EslConstructor as a result of the - constructor redirection in ::mpfnEslConstructor at the end of this - file. - - @retval EFI_SUCCESS Successfully connected to the network layer - - **/ -EFI_STATUS -EslServiceNetworkConnect ( - VOID - ) -{ - BOOLEAN bSomethingFound; - UINTN HandleCount; - UINTN Index; - CONST ESL_SOCKET_BINDING * pEnd; - EFI_HANDLE * pHandles; - CONST ESL_SOCKET_BINDING * pSocketBinding; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Initialize the socket layer - // - Status = EFI_SUCCESS; - bSomethingFound = FALSE; - EslServiceLoad ( gImageHandle ); - - // - // Connect the network devices - // - pSocketBinding = &cEslSocketBinding[0]; - pEnd = &pSocketBinding[ cEslSocketBindingEntries ]; - while ( pEnd > pSocketBinding ) { - // - // Attempt to locate the network adapters - // - HandleCount = 0; - pHandles = NULL; - Status = gBS->LocateHandleBuffer ( ByProtocol, - pSocketBinding->pNetworkBinding, - NULL, - &HandleCount, - &pHandles ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR, - "ERROR with %s layer, Status: %r\r\n", - pSocketBinding->pName, - Status )); - } - else { - if ( NULL != pHandles ) { - // - // Attempt to connect to this network adapter - // - for ( Index = 0; HandleCount > Index; Index++ ) { - Status = EslServiceConnect ( gImageHandle, - pHandles[ Index ]); - if ( !EFI_ERROR ( Status )) { - bSomethingFound = TRUE; - } - else { - if ( EFI_OUT_OF_RESOURCES == Status ) { - // - // Pointless to continue without memory - // - break; - } - } - } - - // - // Done with the handles - // - gBS->FreePool ( pHandles ); - } - } - - // - // Set the next network protocol - // - pSocketBinding += 1; - } - - // - // Return the network connection status - // - if ( bSomethingFound ) { - Status = EFI_SUCCESS; - } - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Disconnect from the network layer - - Destructor for the EfiSocketLib when the library is linked - directly to an application. This routine walks the - ::cEslSocketBinding table to remove the ::ESL_SERVICE - structures (network connections) from the ::ESL_LAYER structure. - - This routine is called from ::EslDestructor as a result of the - destructor redirection in ::mpfnEslDestructor at the end of this - file. - - @retval EFI_SUCCESS Successfully disconnected from the network layer - - **/ -EFI_STATUS -EslServiceNetworkDisconnect ( - VOID - ) -{ - UINTN HandleCount; - UINTN Index; - CONST ESL_SOCKET_BINDING * pEnd; - EFI_HANDLE * pHandles; - CONST ESL_SOCKET_BINDING * pSocketBinding; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Disconnect the network devices - // - pSocketBinding = &cEslSocketBinding[0]; - pEnd = &pSocketBinding[ cEslSocketBindingEntries ]; - while ( pEnd > pSocketBinding ) { - // - // Attempt to locate the network adapters - // - HandleCount = 0; - pHandles = NULL; - Status = gBS->LocateHandleBuffer ( ByProtocol, - pSocketBinding->pNetworkBinding, - NULL, - &HandleCount, - &pHandles ); - if (( !EFI_ERROR ( Status )) - && ( NULL != pHandles )) { - // - // Attempt to disconnect from this network adapter - // - for ( Index = 0; HandleCount > Index; Index++ ) { - Status = EslServiceDisconnect ( gImageHandle, - pHandles[ Index ]); - if ( EFI_ERROR ( Status )) { - break; - } - } - - // - // Done with the handles - // - gBS->FreePool ( pHandles ); - } - - // - // Set the next network protocol - // - pSocketBinding += 1; - Status = EFI_SUCCESS; - } - - // - // Finish the disconnect operation - // - if ( !EFI_ERROR ( Status )) { - EslServiceUnload ( ); - } - - // - // Return the network connection status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Socket layer's service binding protocol delcaration. -**/ -CONST EFI_SERVICE_BINDING_PROTOCOL mEfiServiceBinding __attribute__((weak)) = { - NULL, - NULL -}; - - -/** - The following entries redirect the constructor and destructor - for any socket application that links against the EfiSocketLib. - Note that the SocketDxe driver uses different redirection. -**/ -PFN_ESL_xSTRUCTOR mpfnEslConstructor __attribute__((weak)) = EslServiceNetworkConnect; ///< Constructor for EfiSocketLib -PFN_ESL_xSTRUCTOR mpfnEslDestructor __attribute__((weak)) = EslServiceNetworkDisconnect; ///< Destructor for EfiSocketLib -- cgit v1.2.3