summaryrefslogtreecommitdiff
path: root/StdLib/EfiSocketLib
diff options
context:
space:
mode:
Diffstat (limited to 'StdLib/EfiSocketLib')
-rw-r--r--StdLib/EfiSocketLib/DxeSupport.c228
-rw-r--r--StdLib/EfiSocketLib/EfiSocketLib.inf70
-rw-r--r--StdLib/EfiSocketLib/Init.c117
-rw-r--r--StdLib/EfiSocketLib/Ip4.c1380
-rw-r--r--StdLib/EfiSocketLib/ReleaseNotes.txt34
-rw-r--r--StdLib/EfiSocketLib/Service.c479
-rw-r--r--StdLib/EfiSocketLib/Socket.c5795
-rw-r--r--StdLib/EfiSocketLib/Socket.h1688
-rw-r--r--StdLib/EfiSocketLib/Tcp4.c2432
-rw-r--r--StdLib/EfiSocketLib/Tcp6.c2596
-rw-r--r--StdLib/EfiSocketLib/Udp4.c1232
-rw-r--r--StdLib/EfiSocketLib/Udp6.c1379
-rw-r--r--StdLib/EfiSocketLib/UseEfiSocketLib.c376
13 files changed, 0 insertions, 17806 deletions
diff --git a/StdLib/EfiSocketLib/DxeSupport.c b/StdLib/EfiSocketLib/DxeSupport.c
deleted file mode 100644
index 808b710d27..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 availabe 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:
- <ul>
- <li>StdLib/EfiSocketLib/UseSocketLib.c - Application links against EfiSocketLib</li>
- <li>StdLib/SocketDxe/EntryUnload.c - SocketDxe links against EfiSocketLib</li>
- </ul>
-
- 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:
- <ul>
- <li>StdLib/EfiSocketLib/UseSocketLib.c - Application links against EfiSocketLib</li>
- <li>StdLib/SocketDxe/EntryUnload.c - SocketDxe links against EfiSocketLib</li>
- </ul>
-
- 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.<BR>
- 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.<BR>
- 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
-
- <code><pre>
-
- +---------------+ +-------------+ +-------------+
- 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)
-
- </pre></code>
-
- ::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:
- <ul>
- <li>ESL_SOCKET::pRxPacketListHead - Normal (low) priority receive data</li>
- <li>ESL_SOCKET::pRxOobPacketListHead - High (out-of-band or urgent) priority receive data</li>
- <li>ESL_SOCKET::pTxPacketListHead - Normal (low) priority transmit data</li>
- <li>ESL_SOCKET::pTxOobPacketListHead - High (out-of-band or urgent) priority transmit data</li>
- </ul>
- 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:
-
- <code><pre>
-
- +--------------------------+
- | 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 |
- +--------------------------+
-
- </pre></code>
-
- <ul>
- <li>Arc: ::EslSocketPortCloseStart - Marks the port as closing and
- initiates the port close operation</li>
- <li>State: PORT_STATE_CLOSE_STARTED</li>
- <li>Arc: ::EslSocketPortCloseTxDone - Waits until all of the transmit
- operations to complete. After all of the transmits are complete,
- this routine initiates the network specific close operation by calling
- through ESL_PROTOCOL_API::pfnPortCloseOp. One such routine is
- ::EslTcp4PortCloseOp.
- </li>
- <li>State: PORT_STATE_CLOSE_TX_DONE</li>
- <li>Arc: ::EslSocketPortCloseComplete - Called when the close operation is
- complete. After the transition to PORT_STATE_CLOSE_DONE,
- this routine calls ::EslSocketRxCancel to abort the pending receive operations.
- </li>
- <li>State: PORT_STATE_CLOSE_DONE</li>
- <li>Arc: ::EslSocketPortCloseRxDone - Waits until all of the receive
- operation have been cancelled. After the transition to
- PORT_STATE_CLOSE_RX_DONE, this routine calls ::EslSocketPortClose.
- </li>
- <li>State: PORT_STATE_CLOSE_RX_DONE</li>
- <li>Arc: ::EslSocketPortClose - This routine discards any receive buffers
- using a network specific support routine via ESL_PROTOCOL_API::pfnPacketFree.
- This routine then releases the port resources allocated by ::EslSocketPortAllocate
- and calls the network specific port close routine (e.g. ::EslTcp4PortClose)
- via ESL_PROTOCOL_API::pfnPortClose to release any network specific resources.
- </li>
- </ul>
-
-
- \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.
-
-<code><pre>
-
- +------------------+
- | ::ESL_PORT |
- | |
- +------------------+
- | ::ESL_IO_MGMT |
- +------------------+
- | ESL_IO_MGMT |
- +------------------+
- . .
- . ESL_IO_MGMT .
- . .
- +------------------+
-
-</pre></code>
-
- 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.
-
-<code><pre>
-
- 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
-</pre></code>
-
- 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.
-
-<code><pre>
-
- +------------+ +------------+
- High .----->| ESL_PACKET |-->| ESL_PACKET |--> NULL (pNext)
- Priority | +------------+ +------------+
- |
- | pRxOobPacketListHead
- +------------+
- | ::ESL_SOCKET |
- +------------+
- | pRxPacketListHead
- Low |
- Priority | +------------+ +------------+ +------------+
- `----->| ::ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL
- +------------+ +------------+ +------------+
-
-</pre></code>
-
- ::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.
-
-<code><pre>
-
- 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 |
- +----+---------------+ | |
- | |
- +--------------------------+
-
-</pre></code>
-
- 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.
-
-<code><pre>
-
- *ppQueueHead: pSocket->pRxPacketListHead or pSocket->pRxOobPacketListHead
- |
- V
- +------------+ +------------+ +------------+
- Data | ESL_PACKET |-->| ESL_PACKET |-->| ESL_PACKET |--> NULL
- +------------+ +------------+ +------------+
- ^
- |
- *ppQueueTail: pSocket->pRxPacketListTail or pSocket->pRxOobPacketListTail
-
-</pre></code>
-
- 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.
-
-<code><pre>
-
- +--------------------+ +--------------------+
- | ESL_IO_MGMT | | ESL_PACKET |
- | | | |
- | +---------------+ +----------------+ |
- | | Token | | Buffer Length | |
- | | TxData --> | Buffer Address | |
- | | | +----------------+---+
- | | Event | | Data Buffer |
- +----+---------------+ | |
- +--------------------+
-</pre></code>
-
- 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.
-
-<code><pre>
-
- 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
-
-</pre></code>
-
- 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:
- <ul>
- <li>::EslSocketGetLocalAddress</li>
- <li>::EslSocketGetPeerAddress</li>
- <li>::EslSocketPoll</li>
- <li>::EslSocketReceive</li>
- <li>::EslSocketTransmit</li>
- </ul>
-
- @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:
- <ul>
- <li>::EslSocketBind</li>
- <li>::EslTcp4ListenComplete</li>
- </ul>
- 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:
- <ul>
- <li>::EslSocketPortAllocate - Port initialization failure</li>
- <li>::EslSocketPortCloseRxDone - Last step of close processing</li>
- <li>::EslTcp4ConnectComplete - Connection failure and reducing the port list to a single port</li>
- </ul>
- 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
- <ul>
- <li>::EslSocketPortCloseComplete</li>
- <li>::EslSocketPortCloseTxDone</li>
- <li>::EslSocketRxComplete</li>
- </ul>
- 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:
- <ul>
- <li>::EslIp4RxComplete</li>
- <li>::EslTcp4RxComplete</li>
- <li>::EslUdp4RxComplete</li>
- </ul>
-
- @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:
- <ul>
- <li>::EslIp4Receive to restart the receive engine to release flow control.</li>
- <li>::EslIp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>
- <li>::EslIp4SocketIsConfigured to start the receive engine for the new socket.</li>
- <li>::EslTcp4ListenComplete to start the recevie engine for the new socket.</li>
- <li>::EslTcp4Receive to restart the receive engine to release flow control.</li>
- <li>::EslTcp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>
- <li>::EslUdp4Receive to restart the receive engine to release flow control.</li>
- <li>::EslUdp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>
- <li>::EslUdp4SocketIsConfigured to start the recevie engine for the new socket.</li>
- </ul>
-
- @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:
- <ul>
- <li>::EslIp4TxComplete</li>
- <li>::EslTcp4TxComplete</li>
- <li>::EslTcp4TxOobComplete</li>
- <li>::EslUdp4TxComplete</li>
- </ul>
-
- @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 <Efi/EfiSocketLib.h>
-
-//------------------------------------------------------------------------------
-// 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:
- <ul>
- <li>::EslSocketGetLocalAddress</li>
- <li>::EslSocketGetPeerAddress</li>
- <li>::EslSocketPoll</li>
- <li>::EslSocketReceive</li>
- <li>::EslSocketTransmit</li>
- </ul>
-
- @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:
- <ul>
- <li>::EslIp4PortAllocate - Port initialization failure</li>
- <li>::EslSocketPortCloseRxDone - Last step of close processing</li>
- <li>::EslTcp4ConnectComplete - Connection failure and reducint the port list to a single port</li>
- <li>::EslTcp4PortAllocate - Port initialization failure</li>
- <li>::EslUdp4PortAllocate - Port initialization failure</li>
- </ul>
- 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
- <ul>
- <li>::EslIp4RxComplete</li>
- <li>::EslSocketPortCloseComplete</li>
- <li>::EslSocketPortCloseTxDone</li>
- <li>::EslUdp4RxComplete</li>
- </ul>
- 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:
- <ul>
- <li>::EslIp4RxComplete</li>
- <li>::EslTcp4RxComplete</li>
- <li>::EslUdp4RxComplete</li>
- </ul>
-
- @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:
- <ul>
- <li>::EslIp4Receive to restart the receive engine to release flow control.</li>
- <li>::EslIp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>
- <li>::EslIp4SocketIsConfigured to start the recevie engine for the new socket.</li>
- <li>::EslTcp4ListenComplete to start the recevie engine for the new socket.</li>
- <li>::EslTcp4Receive to restart the receive engine to release flow control.</li>
- <li>::EslTcp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>
- <li>::EslUdp4Receive to restart the receive engine to release flow control.</li>
- <li>::EslUdp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>
- <li>::EslUdp4SocketIsConfigured to start the recevie engine for the new socket.</li>
- </ul>
-
- @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:
- <ul>
- <li>::EslIp4TxComplete</li>
- <li>::EslTcp4TxComplete</li>
- <li>::EslTcp4TxOobComplete</li>
- <li>::EslUdp4TxComplete</li>
- </ul>
-
- @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.<BR>
- 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.<BR>
- 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