REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the NetworkPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
		
			
				
	
	
		
			1003 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1003 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   This library is used to share code between UEFI network stack modules.
 | |
|   It provides the helper routines to access TCP service.
 | |
| 
 | |
| Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <Uefi.h>
 | |
| 
 | |
| #include <Library/TcpIoLib.h>
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/UefiBootServicesTableLib.h>
 | |
| #include <Library/MemoryAllocationLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| 
 | |
| /**
 | |
|   The common notify function associated with various TcpIo events.
 | |
| 
 | |
|   @param[in]  Event   The event signaled.
 | |
|   @param[in]  Context The context.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| TcpIoCommonNotify (
 | |
|   IN EFI_EVENT  Event,
 | |
|   IN VOID       *Context
 | |
|   )
 | |
| {
 | |
|   if ((Event == NULL) || (Context == NULL)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   *((BOOLEAN *)Context) = TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The internal function for delay configuring TCP6 when IP6 driver is still in DAD.
 | |
| 
 | |
|   @param[in]  Tcp6               The EFI_TCP6_PROTOCOL protocol instance.
 | |
|   @param[in]  Tcp6ConfigData     The Tcp6 configuration data.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The operational settings successfully
 | |
|                                  completed.
 | |
|   @retval EFI_INVALID_PARAMETER  One or more parameters are invalid.
 | |
|   @retval Others                 Failed to finish the operation.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| TcpIoGetMapping (
 | |
|   IN EFI_TCP6_PROTOCOL     *Tcp6,
 | |
|   IN EFI_TCP6_CONFIG_DATA  *Tcp6ConfigData
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   EFI_EVENT   Event;
 | |
| 
 | |
|   if ((Tcp6 == NULL) || (Tcp6ConfigData == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Event  = NULL;
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_TIMER,
 | |
|                   TPL_CALLBACK,
 | |
|                   NULL,
 | |
|                   NULL,
 | |
|                   &Event
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto ON_EXIT;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->SetTimer (
 | |
|                   Event,
 | |
|                   TimerRelative,
 | |
|                   TCP_GET_MAPPING_TIMEOUT
 | |
|                   );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto ON_EXIT;
 | |
|   }
 | |
| 
 | |
|   while (EFI_ERROR (gBS->CheckEvent (Event))) {
 | |
|     Tcp6->Poll (Tcp6);
 | |
| 
 | |
|     Status = Tcp6->Configure (Tcp6, Tcp6ConfigData);
 | |
| 
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| ON_EXIT:
 | |
| 
 | |
|   if (Event != NULL) {
 | |
|     gBS->CloseEvent (Event);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create a TCP socket with the specified configuration data.
 | |
| 
 | |
|   @param[in]  Image      The handle of the driver image.
 | |
|   @param[in]  Controller The handle of the controller.
 | |
|   @param[in]  TcpVersion The version of Tcp, TCP_VERSION_4 or TCP_VERSION_6.
 | |
|   @param[in]  ConfigData The Tcp configuration data.
 | |
|   @param[out] TcpIo      The TcpIo.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The TCP socket is created and configured.
 | |
|   @retval EFI_INVALID_PARAMETER  One or more parameters are invalid.
 | |
|   @retval EFI_UNSUPPORTED        One or more of the control options are not
 | |
|                                  supported in the implementation.
 | |
|   @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
 | |
|   @retval Others                 Failed to create the TCP socket or configure it.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TcpIoCreateSocket (
 | |
|   IN EFI_HANDLE          Image,
 | |
|   IN EFI_HANDLE          Controller,
 | |
|   IN UINT8               TcpVersion,
 | |
|   IN TCP_IO_CONFIG_DATA  *ConfigData,
 | |
|   OUT TCP_IO             *TcpIo
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS             Status;
 | |
|   EFI_EVENT              Event;
 | |
|   EFI_GUID               *ServiceBindingGuid;
 | |
|   EFI_GUID               *ProtocolGuid;
 | |
|   VOID                   **Interface;
 | |
|   EFI_TCP4_OPTION        ControlOption;
 | |
|   EFI_TCP4_CONFIG_DATA   Tcp4ConfigData;
 | |
|   EFI_TCP4_ACCESS_POINT  *AccessPoint4;
 | |
|   EFI_TCP4_PROTOCOL      *Tcp4;
 | |
|   EFI_TCP6_CONFIG_DATA   Tcp6ConfigData;
 | |
|   EFI_TCP6_ACCESS_POINT  *AccessPoint6;
 | |
|   EFI_TCP6_PROTOCOL      *Tcp6;
 | |
|   EFI_TCP4_RECEIVE_DATA  *RxData;
 | |
| 
 | |
|   if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (TcpIo == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Tcp4 = NULL;
 | |
|   Tcp6 = NULL;
 | |
| 
 | |
|   ZeroMem (TcpIo, sizeof (TCP_IO));
 | |
| 
 | |
|   if (TcpVersion == TCP_VERSION_4) {
 | |
|     ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
 | |
|     ProtocolGuid       = &gEfiTcp4ProtocolGuid;
 | |
|     Interface          = (VOID **)(&TcpIo->Tcp.Tcp4);
 | |
|   } else if (TcpVersion == TCP_VERSION_6) {
 | |
|     ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
 | |
|     ProtocolGuid       = &gEfiTcp6ProtocolGuid;
 | |
|     Interface          = (VOID **)(&TcpIo->Tcp.Tcp6);
 | |
|   } else {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   TcpIo->TcpVersion = TcpVersion;
 | |
| 
 | |
|   //
 | |
|   // Create the TCP child instance and get the TCP protocol.
 | |
|   //
 | |
|   Status = NetLibCreateServiceChild (
 | |
|              Controller,
 | |
|              Image,
 | |
|              ServiceBindingGuid,
 | |
|              &TcpIo->Handle
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   TcpIo->Handle,
 | |
|                   ProtocolGuid,
 | |
|                   Interface,
 | |
|                   Image,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status) || (*Interface == NULL)) {
 | |
|     goto ON_ERROR;
 | |
|   }
 | |
| 
 | |
|   if (TcpVersion == TCP_VERSION_4) {
 | |
|     Tcp4 = TcpIo->Tcp.Tcp4;
 | |
|   } else {
 | |
|     Tcp6 = TcpIo->Tcp.Tcp6;
 | |
|   }
 | |
| 
 | |
|   TcpIo->Image      = Image;
 | |
|   TcpIo->Controller = Controller;
 | |
| 
 | |
|   //
 | |
|   // Set the configuration parameters.
 | |
|   //
 | |
|   ControlOption.ReceiveBufferSize      = 0x200000;
 | |
|   ControlOption.SendBufferSize         = 0x200000;
 | |
|   ControlOption.MaxSynBackLog          = 0;
 | |
|   ControlOption.ConnectionTimeout      = 0;
 | |
|   ControlOption.DataRetries            = 6;
 | |
|   ControlOption.FinTimeout             = 0;
 | |
|   ControlOption.TimeWaitTimeout        = 0;
 | |
|   ControlOption.KeepAliveProbes        = 4;
 | |
|   ControlOption.KeepAliveTime          = 0;
 | |
|   ControlOption.KeepAliveInterval      = 0;
 | |
|   ControlOption.EnableNagle            = FALSE;
 | |
|   ControlOption.EnableTimeStamp        = FALSE;
 | |
|   ControlOption.EnableWindowScaling    = TRUE;
 | |
|   ControlOption.EnableSelectiveAck     = FALSE;
 | |
|   ControlOption.EnablePathMtuDiscovery = FALSE;
 | |
| 
 | |
|   if (TcpVersion == TCP_VERSION_4) {
 | |
|     Tcp4ConfigData.TypeOfService = 8;
 | |
|     Tcp4ConfigData.TimeToLive    = 255;
 | |
|     Tcp4ConfigData.ControlOption = &ControlOption;
 | |
| 
 | |
|     AccessPoint4 = &Tcp4ConfigData.AccessPoint;
 | |
| 
 | |
|     ZeroMem (AccessPoint4, sizeof (EFI_TCP4_ACCESS_POINT));
 | |
|     AccessPoint4->StationPort = ConfigData->Tcp4IoConfigData.StationPort;
 | |
|     AccessPoint4->RemotePort  = ConfigData->Tcp4IoConfigData.RemotePort;
 | |
|     AccessPoint4->ActiveFlag  = ConfigData->Tcp4IoConfigData.ActiveFlag;
 | |
| 
 | |
|     CopyMem (
 | |
|       &AccessPoint4->StationAddress,
 | |
|       &ConfigData->Tcp4IoConfigData.LocalIp,
 | |
|       sizeof (EFI_IPv4_ADDRESS)
 | |
|       );
 | |
|     CopyMem (
 | |
|       &AccessPoint4->SubnetMask,
 | |
|       &ConfigData->Tcp4IoConfigData.SubnetMask,
 | |
|       sizeof (EFI_IPv4_ADDRESS)
 | |
|       );
 | |
|     CopyMem (
 | |
|       &AccessPoint4->RemoteAddress,
 | |
|       &ConfigData->Tcp4IoConfigData.RemoteIp,
 | |
|       sizeof (EFI_IPv4_ADDRESS)
 | |
|       );
 | |
| 
 | |
|     ASSERT (Tcp4 != NULL);
 | |
| 
 | |
|     //
 | |
|     // Configure the TCP4 protocol.
 | |
|     //
 | |
|     Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto ON_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (!EFI_IP4_EQUAL (&ConfigData->Tcp4IoConfigData.Gateway, &mZeroIp4Addr)) {
 | |
|       //
 | |
|       // The gateway is not zero. Add the default route manually.
 | |
|       //
 | |
|       Status = Tcp4->Routes (
 | |
|                        Tcp4,
 | |
|                        FALSE,
 | |
|                        &mZeroIp4Addr,
 | |
|                        &mZeroIp4Addr,
 | |
|                        &ConfigData->Tcp4IoConfigData.Gateway
 | |
|                        );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         goto ON_ERROR;
 | |
|       }
 | |
|     }
 | |
|   } else {
 | |
|     Tcp6ConfigData.TrafficClass  = 0;
 | |
|     Tcp6ConfigData.HopLimit      = 255;
 | |
|     Tcp6ConfigData.ControlOption = (EFI_TCP6_OPTION *)&ControlOption;
 | |
| 
 | |
|     AccessPoint6 = &Tcp6ConfigData.AccessPoint;
 | |
| 
 | |
|     ZeroMem (AccessPoint6, sizeof (EFI_TCP6_ACCESS_POINT));
 | |
|     AccessPoint6->StationPort = ConfigData->Tcp6IoConfigData.StationPort;
 | |
|     AccessPoint6->RemotePort  = ConfigData->Tcp6IoConfigData.RemotePort;
 | |
|     AccessPoint6->ActiveFlag  = ConfigData->Tcp6IoConfigData.ActiveFlag;
 | |
| 
 | |
|     IP6_COPY_ADDRESS (&AccessPoint6->RemoteAddress, &ConfigData->Tcp6IoConfigData.RemoteIp);
 | |
| 
 | |
|     ASSERT (Tcp6 != NULL);
 | |
|     //
 | |
|     // Configure the TCP6 protocol.
 | |
|     //
 | |
|     Status = Tcp6->Configure (Tcp6, &Tcp6ConfigData);
 | |
|     if (Status == EFI_NO_MAPPING) {
 | |
|       Status = TcpIoGetMapping (Tcp6, &Tcp6ConfigData);
 | |
|     }
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto ON_ERROR;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Create events for various asynchronous operations.
 | |
|   //
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_NOTIFY,
 | |
|                   TcpIoCommonNotify,
 | |
|                   &TcpIo->IsConnDone,
 | |
|                   &Event
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto ON_ERROR;
 | |
|   }
 | |
| 
 | |
|   TcpIo->ConnToken.Tcp4Token.CompletionToken.Event = Event;
 | |
| 
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_NOTIFY,
 | |
|                   TcpIoCommonNotify,
 | |
|                   &TcpIo->IsListenDone,
 | |
|                   &Event
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto ON_ERROR;
 | |
|   }
 | |
| 
 | |
|   TcpIo->ListenToken.Tcp4Token.CompletionToken.Event = Event;
 | |
| 
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_NOTIFY,
 | |
|                   TcpIoCommonNotify,
 | |
|                   &TcpIo->IsTxDone,
 | |
|                   &Event
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto ON_ERROR;
 | |
|   }
 | |
| 
 | |
|   TcpIo->TxToken.Tcp4Token.CompletionToken.Event = Event;
 | |
| 
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_NOTIFY,
 | |
|                   TcpIoCommonNotify,
 | |
|                   &TcpIo->IsRxDone,
 | |
|                   &Event
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto ON_ERROR;
 | |
|   }
 | |
| 
 | |
|   TcpIo->RxToken.Tcp4Token.CompletionToken.Event = Event;
 | |
| 
 | |
|   RxData = (EFI_TCP4_RECEIVE_DATA *)AllocateZeroPool (sizeof (EFI_TCP4_RECEIVE_DATA));
 | |
|   if (RxData == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto ON_ERROR;
 | |
|   }
 | |
| 
 | |
|   TcpIo->RxToken.Tcp4Token.Packet.RxData = RxData;
 | |
| 
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_NOTIFY,
 | |
|                   TcpIoCommonNotify,
 | |
|                   &TcpIo->IsCloseDone,
 | |
|                   &Event
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto ON_ERROR;
 | |
|   }
 | |
| 
 | |
|   TcpIo->CloseToken.Tcp4Token.CompletionToken.Event = Event;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| 
 | |
| ON_ERROR:
 | |
| 
 | |
|   TcpIoDestroySocket (TcpIo);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Destroy the socket.
 | |
| 
 | |
|   @param[in]  TcpIo The TcpIo which wraps the socket to be destroyed.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| TcpIoDestroySocket (
 | |
|   IN TCP_IO  *TcpIo
 | |
|   )
 | |
| {
 | |
|   EFI_EVENT          Event;
 | |
|   EFI_TCP4_PROTOCOL  *Tcp4;
 | |
|   EFI_TCP6_PROTOCOL  *Tcp6;
 | |
|   UINT8              TcpVersion;
 | |
|   EFI_GUID           *ServiceBindingGuid;
 | |
|   EFI_GUID           *ProtocolGuid;
 | |
|   EFI_HANDLE         ChildHandle;
 | |
| 
 | |
|   if (TcpIo == NULL) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   TcpVersion = TcpIo->TcpVersion;
 | |
| 
 | |
|   if ((TcpVersion != TCP_VERSION_4) && (TcpVersion != TCP_VERSION_6)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Event = TcpIo->ConnToken.Tcp4Token.CompletionToken.Event;
 | |
| 
 | |
|   if (Event != NULL) {
 | |
|     gBS->CloseEvent (Event);
 | |
|   }
 | |
| 
 | |
|   Event = TcpIo->ListenToken.Tcp4Token.CompletionToken.Event;
 | |
| 
 | |
|   if (Event != NULL) {
 | |
|     gBS->CloseEvent (Event);
 | |
|   }
 | |
| 
 | |
|   Event = TcpIo->TxToken.Tcp4Token.CompletionToken.Event;
 | |
| 
 | |
|   if (Event != NULL) {
 | |
|     gBS->CloseEvent (Event);
 | |
|   }
 | |
| 
 | |
|   Event = TcpIo->RxToken.Tcp4Token.CompletionToken.Event;
 | |
| 
 | |
|   if (Event != NULL) {
 | |
|     gBS->CloseEvent (Event);
 | |
|   }
 | |
| 
 | |
|   Event = TcpIo->CloseToken.Tcp4Token.CompletionToken.Event;
 | |
| 
 | |
|   if (Event != NULL) {
 | |
|     gBS->CloseEvent (Event);
 | |
|   }
 | |
| 
 | |
|   if (TcpIo->RxToken.Tcp4Token.Packet.RxData != NULL) {
 | |
|     FreePool (TcpIo->RxToken.Tcp4Token.Packet.RxData);
 | |
|   }
 | |
| 
 | |
|   Tcp4 = NULL;
 | |
|   Tcp6 = NULL;
 | |
| 
 | |
|   if (TcpVersion == TCP_VERSION_4) {
 | |
|     ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
 | |
|     ProtocolGuid       = &gEfiTcp4ProtocolGuid;
 | |
|     Tcp4               = TcpIo->Tcp.Tcp4;
 | |
|     if (Tcp4 != NULL) {
 | |
|       Tcp4->Configure (Tcp4, NULL);
 | |
|     }
 | |
|   } else {
 | |
|     ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
 | |
|     ProtocolGuid       = &gEfiTcp6ProtocolGuid;
 | |
|     Tcp6               = TcpIo->Tcp.Tcp6;
 | |
|     if (Tcp6 != NULL) {
 | |
|       Tcp6->Configure (Tcp6, NULL);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if ((Tcp4 != NULL) || (Tcp6 != NULL)) {
 | |
|     gBS->CloseProtocol (
 | |
|            TcpIo->Handle,
 | |
|            ProtocolGuid,
 | |
|            TcpIo->Image,
 | |
|            TcpIo->Controller
 | |
|            );
 | |
|   }
 | |
| 
 | |
|   ChildHandle = NULL;
 | |
| 
 | |
|   if (TcpIo->IsListenDone) {
 | |
|     if (TcpVersion == TCP_VERSION_4) {
 | |
|       Tcp4 = TcpIo->NewTcp.Tcp4;
 | |
|       if (Tcp4 != NULL) {
 | |
|         Tcp4->Configure (Tcp4, NULL);
 | |
|         ChildHandle = TcpIo->ListenToken.Tcp4Token.NewChildHandle;
 | |
|       }
 | |
|     } else {
 | |
|       Tcp6 = TcpIo->NewTcp.Tcp6;
 | |
|       if (Tcp6 != NULL) {
 | |
|         Tcp6->Configure (Tcp6, NULL);
 | |
|         ChildHandle = TcpIo->ListenToken.Tcp6Token.NewChildHandle;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (ChildHandle != NULL) {
 | |
|       gBS->CloseProtocol (
 | |
|              ChildHandle,
 | |
|              ProtocolGuid,
 | |
|              TcpIo->Image,
 | |
|              TcpIo->Controller
 | |
|              );
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   NetLibDestroyServiceChild (
 | |
|     TcpIo->Controller,
 | |
|     TcpIo->Image,
 | |
|     ServiceBindingGuid,
 | |
|     TcpIo->Handle
 | |
|     );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Connect to the other endpoint of the TCP socket.
 | |
| 
 | |
|   @param[in, out]  TcpIo     The TcpIo wrapping the TCP socket.
 | |
|   @param[in]       Timeout   The time to wait for connection done. Set to NULL for infinite wait.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Connect to the other endpoint of the TCP socket
 | |
|                                  successfully.
 | |
|   @retval EFI_TIMEOUT            Failed to connect to the other endpoint of the
 | |
|                                  TCP socket in the specified time period.
 | |
|   @retval EFI_INVALID_PARAMETER  One or more parameters are invalid.
 | |
|   @retval EFI_UNSUPPORTED        One or more of the control options are not
 | |
|                                  supported in the implementation.
 | |
|   @retval Others                 Other errors as indicated.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TcpIoConnect (
 | |
|   IN OUT TCP_IO     *TcpIo,
 | |
|   IN     EFI_EVENT  Timeout        OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_TCP4_PROTOCOL  *Tcp4;
 | |
|   EFI_TCP6_PROTOCOL  *Tcp6;
 | |
|   EFI_STATUS         Status;
 | |
| 
 | |
|   if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   TcpIo->IsConnDone = FALSE;
 | |
| 
 | |
|   Tcp4 = NULL;
 | |
|   Tcp6 = NULL;
 | |
| 
 | |
|   if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|     Tcp4   = TcpIo->Tcp.Tcp4;
 | |
|     Status = Tcp4->Connect (Tcp4, &TcpIo->ConnToken.Tcp4Token);
 | |
|   } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
 | |
|     Tcp6   = TcpIo->Tcp.Tcp6;
 | |
|     Status = Tcp6->Connect (Tcp6, &TcpIo->ConnToken.Tcp6Token);
 | |
|   } else {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   while (!TcpIo->IsConnDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
 | |
|     if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|       Tcp4->Poll (Tcp4);
 | |
|     } else {
 | |
|       Tcp6->Poll (Tcp6);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!TcpIo->IsConnDone) {
 | |
|     if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|       Tcp4->Cancel (Tcp4, &TcpIo->ConnToken.Tcp4Token.CompletionToken);
 | |
|     } else {
 | |
|       Tcp6->Cancel (Tcp6, &TcpIo->ConnToken.Tcp6Token.CompletionToken);
 | |
|     }
 | |
| 
 | |
|     Status = EFI_TIMEOUT;
 | |
|   } else {
 | |
|     Status = TcpIo->ConnToken.Tcp4Token.CompletionToken.Status;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Accept the incomding request from the other endpoint of the TCP socket.
 | |
| 
 | |
|   @param[in, out]  TcpIo     The TcpIo wrapping the TCP socket.
 | |
|   @param[in]       Timeout   The time to wait for connection done. Set to NULL for infinite wait.
 | |
| 
 | |
| 
 | |
|   @retval EFI_SUCCESS            Connect to the other endpoint of the TCP socket
 | |
|                                  successfully.
 | |
|   @retval EFI_INVALID_PARAMETER  One or more parameters are invalid.
 | |
|   @retval EFI_UNSUPPORTED        One or more of the control options are not
 | |
|                                  supported in the implementation.
 | |
| 
 | |
|   @retval EFI_TIMEOUT            Failed to connect to the other endpoint of the
 | |
|                                  TCP socket in the specified time period.
 | |
|   @retval Others                 Other errors as indicated.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TcpIoAccept (
 | |
|   IN OUT TCP_IO     *TcpIo,
 | |
|   IN     EFI_EVENT  Timeout        OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS         Status;
 | |
|   EFI_GUID           *ProtocolGuid;
 | |
|   EFI_TCP4_PROTOCOL  *Tcp4;
 | |
|   EFI_TCP6_PROTOCOL  *Tcp6;
 | |
| 
 | |
|   if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   TcpIo->IsListenDone = FALSE;
 | |
| 
 | |
|   Tcp4 = NULL;
 | |
|   Tcp6 = NULL;
 | |
| 
 | |
|   if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|     Tcp4   = TcpIo->Tcp.Tcp4;
 | |
|     Status = Tcp4->Accept (Tcp4, &TcpIo->ListenToken.Tcp4Token);
 | |
|   } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
 | |
|     Tcp6   = TcpIo->Tcp.Tcp6;
 | |
|     Status = Tcp6->Accept (Tcp6, &TcpIo->ListenToken.Tcp6Token);
 | |
|   } else {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   while (!TcpIo->IsListenDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
 | |
|     if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|       Tcp4->Poll (Tcp4);
 | |
|     } else {
 | |
|       Tcp6->Poll (Tcp6);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!TcpIo->IsListenDone) {
 | |
|     if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|       Tcp4->Cancel (Tcp4, &TcpIo->ListenToken.Tcp4Token.CompletionToken);
 | |
|     } else {
 | |
|       Tcp6->Cancel (Tcp6, &TcpIo->ListenToken.Tcp6Token.CompletionToken);
 | |
|     }
 | |
| 
 | |
|     Status = EFI_TIMEOUT;
 | |
|   } else {
 | |
|     Status = TcpIo->ListenToken.Tcp4Token.CompletionToken.Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // The new TCP instance handle created for the established connection is
 | |
|   // in ListenToken.
 | |
|   //
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|       ProtocolGuid = &gEfiTcp4ProtocolGuid;
 | |
|     } else {
 | |
|       ProtocolGuid = &gEfiTcp6ProtocolGuid;
 | |
|     }
 | |
| 
 | |
|     Status = gBS->OpenProtocol (
 | |
|                     TcpIo->ListenToken.Tcp4Token.NewChildHandle,
 | |
|                     ProtocolGuid,
 | |
|                     (VOID **)(&TcpIo->NewTcp.Tcp4),
 | |
|                     TcpIo->Image,
 | |
|                     TcpIo->Controller,
 | |
|                     EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                     );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Reset the socket.
 | |
| 
 | |
|   @param[in, out]  TcpIo The TcpIo wrapping the TCP socket.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| TcpIoReset (
 | |
|   IN OUT TCP_IO  *TcpIo
 | |
|   )
 | |
| {
 | |
|   EFI_TCP4_PROTOCOL  *Tcp4;
 | |
|   EFI_TCP6_PROTOCOL  *Tcp6;
 | |
|   EFI_STATUS         Status;
 | |
| 
 | |
|   if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   TcpIo->IsCloseDone = FALSE;
 | |
|   Tcp4               = NULL;
 | |
|   Tcp6               = NULL;
 | |
| 
 | |
|   if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|     TcpIo->CloseToken.Tcp4Token.AbortOnClose = TRUE;
 | |
|     Tcp4                                     = TcpIo->Tcp.Tcp4;
 | |
|     Status                                   = Tcp4->Close (Tcp4, &TcpIo->CloseToken.Tcp4Token);
 | |
|   } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
 | |
|     TcpIo->CloseToken.Tcp6Token.AbortOnClose = TRUE;
 | |
|     Tcp6                                     = TcpIo->Tcp.Tcp6;
 | |
|     Status                                   = Tcp6->Close (Tcp6, &TcpIo->CloseToken.Tcp6Token);
 | |
|   } else {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   while (!TcpIo->IsCloseDone) {
 | |
|     if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|       Tcp4->Poll (Tcp4);
 | |
|     } else {
 | |
|       Tcp6->Poll (Tcp6);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Transmit the Packet to the other endpoint of the socket.
 | |
| 
 | |
|   @param[in]   TcpIo           The TcpIo wrapping the TCP socket.
 | |
|   @param[in]   Packet          The packet to transmit.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The packet is transmitted.
 | |
|   @retval EFI_INVALID_PARAMETER  One or more parameters are invalid.
 | |
|   @retval EFI_UNSUPPORTED        One or more of the control options are not
 | |
|                                  supported in the implementation.
 | |
|   @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
 | |
|   @retval EFI_DEVICE_ERROR       An unexpected network or system error occurred.
 | |
|   @retval Others                 Other errors as indicated.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TcpIoTransmit (
 | |
|   IN TCP_IO   *TcpIo,
 | |
|   IN NET_BUF  *Packet
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS         Status;
 | |
|   VOID               *Data;
 | |
|   EFI_TCP4_PROTOCOL  *Tcp4;
 | |
|   EFI_TCP6_PROTOCOL  *Tcp6;
 | |
|   UINTN              Size;
 | |
| 
 | |
|   if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL) || (Packet == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|     Size = sizeof (EFI_TCP4_TRANSMIT_DATA) +
 | |
|            (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA);
 | |
|   } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
 | |
|     Size = sizeof (EFI_TCP6_TRANSMIT_DATA) +
 | |
|            (Packet->BlockOpNum - 1) * sizeof (EFI_TCP6_FRAGMENT_DATA);
 | |
|   } else {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   Data = AllocatePool (Size);
 | |
|   if (Data == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   ((EFI_TCP4_TRANSMIT_DATA *)Data)->Push       = TRUE;
 | |
|   ((EFI_TCP4_TRANSMIT_DATA *)Data)->Urgent     = FALSE;
 | |
|   ((EFI_TCP4_TRANSMIT_DATA *)Data)->DataLength = Packet->TotalSize;
 | |
| 
 | |
|   //
 | |
|   // Build the fragment table.
 | |
|   //
 | |
|   ((EFI_TCP4_TRANSMIT_DATA *)Data)->FragmentCount = Packet->BlockOpNum;
 | |
| 
 | |
|   NetbufBuildExt (
 | |
|     Packet,
 | |
|     (NET_FRAGMENT *)&((EFI_TCP4_TRANSMIT_DATA *)Data)->FragmentTable[0],
 | |
|     &((EFI_TCP4_TRANSMIT_DATA *)Data)->FragmentCount
 | |
|     );
 | |
| 
 | |
|   Tcp4   = NULL;
 | |
|   Tcp6   = NULL;
 | |
|   Status = EFI_DEVICE_ERROR;
 | |
| 
 | |
|   //
 | |
|   // Transmit the packet.
 | |
|   //
 | |
|   if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|     TcpIo->TxToken.Tcp4Token.Packet.TxData = (EFI_TCP4_TRANSMIT_DATA *)Data;
 | |
|     Tcp4                                   = TcpIo->Tcp.Tcp4;
 | |
|     if (TcpIo->IsListenDone) {
 | |
|       Tcp4 = TcpIo->NewTcp.Tcp4;
 | |
|     }
 | |
| 
 | |
|     if (Tcp4 == NULL) {
 | |
|       goto ON_EXIT;
 | |
|     }
 | |
| 
 | |
|     Status = Tcp4->Transmit (Tcp4, &TcpIo->TxToken.Tcp4Token);
 | |
|   } else {
 | |
|     TcpIo->TxToken.Tcp6Token.Packet.TxData = (EFI_TCP6_TRANSMIT_DATA *)Data;
 | |
|     Tcp6                                   = TcpIo->Tcp.Tcp6;
 | |
|     if (TcpIo->IsListenDone) {
 | |
|       Tcp6 = TcpIo->NewTcp.Tcp6;
 | |
|     }
 | |
| 
 | |
|     if (Tcp6 == NULL) {
 | |
|       goto ON_EXIT;
 | |
|     }
 | |
| 
 | |
|     Status = Tcp6->Transmit (Tcp6, &TcpIo->TxToken.Tcp6Token);
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto ON_EXIT;
 | |
|   }
 | |
| 
 | |
|   while (!TcpIo->IsTxDone) {
 | |
|     if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|       Tcp4->Poll (Tcp4);
 | |
|     } else {
 | |
|       Tcp6->Poll (Tcp6);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   TcpIo->IsTxDone = FALSE;
 | |
|   Status          = TcpIo->TxToken.Tcp4Token.CompletionToken.Status;
 | |
| 
 | |
| ON_EXIT:
 | |
| 
 | |
|   FreePool (Data);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Receive data from the socket.
 | |
| 
 | |
|   @param[in, out]  TcpIo       The TcpIo which wraps the socket to be destroyed.
 | |
|   @param[in]       Packet      The buffer to hold the data copy from the socket rx buffer.
 | |
|   @param[in]       AsyncMode   Is this receive asynchronous or not.
 | |
|   @param[in]       Timeout     The time to wait for receiving the amount of data the Packet
 | |
|                                can hold. Set to NULL for infinite wait.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The required amount of data is received from the socket.
 | |
|   @retval EFI_INVALID_PARAMETER  One or more parameters are invalid.
 | |
|   @retval EFI_DEVICE_ERROR       An unexpected network or system error occurred.
 | |
|   @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
 | |
|   @retval EFI_TIMEOUT            Failed to receive the required amount of data in the
 | |
|                                  specified time period.
 | |
|   @retval Others                 Other errors as indicated.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TcpIoReceive (
 | |
|   IN OUT TCP_IO     *TcpIo,
 | |
|   IN     NET_BUF    *Packet,
 | |
|   IN     BOOLEAN    AsyncMode,
 | |
|   IN     EFI_EVENT  Timeout       OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_TCP4_PROTOCOL      *Tcp4;
 | |
|   EFI_TCP6_PROTOCOL      *Tcp6;
 | |
|   EFI_TCP4_RECEIVE_DATA  *RxData;
 | |
|   EFI_STATUS             Status;
 | |
|   NET_FRAGMENT           *Fragment;
 | |
|   UINT32                 FragmentCount;
 | |
|   UINT32                 CurrentFragment;
 | |
| 
 | |
|   if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL) || (Packet == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   RxData = TcpIo->RxToken.Tcp4Token.Packet.RxData;
 | |
|   if (RxData == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Tcp4 = NULL;
 | |
|   Tcp6 = NULL;
 | |
| 
 | |
|   if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|     Tcp4 = TcpIo->Tcp.Tcp4;
 | |
| 
 | |
|     if (TcpIo->IsListenDone) {
 | |
|       Tcp4 = TcpIo->NewTcp.Tcp4;
 | |
|     }
 | |
| 
 | |
|     if (Tcp4 == NULL) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
 | |
|     Tcp6 = TcpIo->Tcp.Tcp6;
 | |
| 
 | |
|     if (TcpIo->IsListenDone) {
 | |
|       Tcp6 = TcpIo->NewTcp.Tcp6;
 | |
|     }
 | |
| 
 | |
|     if (Tcp6 == NULL) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   } else {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   FragmentCount = Packet->BlockOpNum;
 | |
|   Fragment      = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));
 | |
|   if (Fragment == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto ON_EXIT;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Build the fragment table.
 | |
|   //
 | |
|   NetbufBuildExt (Packet, Fragment, &FragmentCount);
 | |
| 
 | |
|   RxData->FragmentCount = 1;
 | |
|   CurrentFragment       = 0;
 | |
|   Status                = EFI_SUCCESS;
 | |
| 
 | |
|   while (CurrentFragment < FragmentCount) {
 | |
|     RxData->DataLength                      = Fragment[CurrentFragment].Len;
 | |
|     RxData->FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len;
 | |
|     RxData->FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk;
 | |
| 
 | |
|     if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|       Status = Tcp4->Receive (Tcp4, &TcpIo->RxToken.Tcp4Token);
 | |
|     } else {
 | |
|       Status = Tcp6->Receive (Tcp6, &TcpIo->RxToken.Tcp6Token);
 | |
|     }
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto ON_EXIT;
 | |
|     }
 | |
| 
 | |
|     while (!TcpIo->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
 | |
|       //
 | |
|       // Poll until some data is received or an error occurs.
 | |
|       //
 | |
|       if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|         Tcp4->Poll (Tcp4);
 | |
|       } else {
 | |
|         Tcp6->Poll (Tcp6);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (!TcpIo->IsRxDone) {
 | |
|       //
 | |
|       // Timeout occurs, cancel the receive request.
 | |
|       //
 | |
|       if (TcpIo->TcpVersion == TCP_VERSION_4) {
 | |
|         Tcp4->Cancel (Tcp4, &TcpIo->RxToken.Tcp4Token.CompletionToken);
 | |
|       } else {
 | |
|         Tcp6->Cancel (Tcp6, &TcpIo->RxToken.Tcp6Token.CompletionToken);
 | |
|       }
 | |
| 
 | |
|       Status = EFI_TIMEOUT;
 | |
|       goto ON_EXIT;
 | |
|     } else {
 | |
|       TcpIo->IsRxDone = FALSE;
 | |
|     }
 | |
| 
 | |
|     Status = TcpIo->RxToken.Tcp4Token.CompletionToken.Status;
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto ON_EXIT;
 | |
|     }
 | |
| 
 | |
|     Fragment[CurrentFragment].Len -= RxData->FragmentTable[0].FragmentLength;
 | |
|     if (Fragment[CurrentFragment].Len == 0) {
 | |
|       CurrentFragment++;
 | |
|     } else {
 | |
|       Fragment[CurrentFragment].Bulk += RxData->FragmentTable[0].FragmentLength;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| ON_EXIT:
 | |
| 
 | |
|   if (Fragment != NULL) {
 | |
|     FreePool (Fragment);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 |