mirror of https://github.com/acidanthera/audk.git
Add a TcpIo library to facilitate usage of TCP service.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11162 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
4e36d6f526
commit
4bad9adabc
|
@ -0,0 +1,252 @@
|
|||
/** @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, 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<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _TCP_IO_H_
|
||||
#define _TCP_IO_H_
|
||||
|
||||
|
||||
#include <Protocol/Tcp4.h>
|
||||
#include <Protocol/Tcp6.h>
|
||||
|
||||
#include <Library/NetLib.h>
|
||||
|
||||
#define TCP_VERSION_4 IP_VERSION_4
|
||||
#define TCP_VERSION_6 IP_VERSION_6
|
||||
|
||||
///
|
||||
/// 10 seconds
|
||||
///
|
||||
#define TCP_GET_MAPPING_TIMEOUT 100000000U
|
||||
|
||||
|
||||
typedef struct {
|
||||
EFI_IPv4_ADDRESS LocalIp;
|
||||
EFI_IPv4_ADDRESS SubnetMask;
|
||||
EFI_IPv4_ADDRESS Gateway;
|
||||
|
||||
UINT16 StationPort;
|
||||
EFI_IPv4_ADDRESS RemoteIp;
|
||||
UINT16 RemotePort;
|
||||
BOOLEAN ActiveFlag;
|
||||
} TCP4_IO_CONFIG_DATA;
|
||||
|
||||
typedef struct {
|
||||
UINT16 StationPort;
|
||||
EFI_IPv6_ADDRESS RemoteIp;
|
||||
UINT16 RemotePort;
|
||||
BOOLEAN ActiveFlag;
|
||||
} TCP6_IO_CONFIG_DATA;
|
||||
|
||||
typedef union {
|
||||
TCP4_IO_CONFIG_DATA Tcp4IoConfigData;
|
||||
TCP6_IO_CONFIG_DATA Tcp6IoConfigData;
|
||||
} TCP_IO_CONFIG_DATA;
|
||||
|
||||
typedef union {
|
||||
EFI_TCP4_PROTOCOL *Tcp4;
|
||||
EFI_TCP6_PROTOCOL *Tcp6;
|
||||
} TCP_IO_PROTOCOL;
|
||||
|
||||
typedef union {
|
||||
EFI_TCP4_CONNECTION_TOKEN Tcp4Token;
|
||||
EFI_TCP6_CONNECTION_TOKEN Tcp6Token;
|
||||
} TCP_IO_CONNECTION_TOKEN;
|
||||
|
||||
typedef union {
|
||||
EFI_TCP4_IO_TOKEN Tcp4Token;
|
||||
EFI_TCP6_IO_TOKEN Tcp6Token;
|
||||
} TCP_IO_IO_TOKEN;
|
||||
|
||||
typedef union {
|
||||
EFI_TCP4_CLOSE_TOKEN Tcp4Token;
|
||||
EFI_TCP6_CLOSE_TOKEN Tcp6Token;
|
||||
} TCP_IO_CLOSE_TOKEN;
|
||||
|
||||
typedef union {
|
||||
EFI_TCP4_LISTEN_TOKEN Tcp4Token;
|
||||
EFI_TCP6_LISTEN_TOKEN Tcp6Token;
|
||||
} TCP_IO_LISTEN_TOKEN;
|
||||
|
||||
|
||||
typedef struct {
|
||||
UINT8 TcpVersion;
|
||||
EFI_HANDLE Image;
|
||||
EFI_HANDLE Controller;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
TCP_IO_PROTOCOL Tcp;
|
||||
TCP_IO_PROTOCOL NewTcp;
|
||||
TCP_IO_CONNECTION_TOKEN ConnToken;
|
||||
TCP_IO_IO_TOKEN TxToken;
|
||||
TCP_IO_IO_TOKEN RxToken;
|
||||
TCP_IO_CLOSE_TOKEN CloseToken;
|
||||
TCP_IO_LISTEN_TOKEN ListenToken;
|
||||
|
||||
BOOLEAN IsConnDone;
|
||||
BOOLEAN IsTxDone;
|
||||
BOOLEAN IsRxDone;
|
||||
BOOLEAN IsCloseDone;
|
||||
BOOLEAN IsListenDone;
|
||||
} TCP_IO;
|
||||
|
||||
/**
|
||||
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 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
|
||||
);
|
||||
|
||||
/**
|
||||
Destroy the socket.
|
||||
|
||||
@param[in] TcpIo The TcpIo which wraps the socket to be destroyed.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TcpIoDestroySocket (
|
||||
IN TCP_IO *TcpIo
|
||||
);
|
||||
|
||||
/**
|
||||
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.
|
||||
|
||||
@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
|
||||
);
|
||||
|
||||
/**
|
||||
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.
|
||||
|
||||
|
||||
@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
|
||||
);
|
||||
|
||||
/**
|
||||
Reset the socket.
|
||||
|
||||
@param[in, out] TcpIo The TcpIo wrapping the TCP socket.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TcpIoReset (
|
||||
IN OUT TCP_IO *TcpIo
|
||||
);
|
||||
|
||||
/**
|
||||
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 trasmitted.
|
||||
@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
|
||||
);
|
||||
|
||||
/**
|
||||
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 asyncronous or not.
|
||||
@param[in] Timeout The time to wait for receiving the amount of data the Packet
|
||||
can hold.
|
||||
|
||||
@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 momery.
|
||||
@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
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,993 @@
|
|||
/** @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, 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<BR>
|
||||
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 <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 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;
|
||||
|
||||
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 variuos 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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
@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
|
||||
)
|
||||
{
|
||||
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 && EFI_ERROR (gBS->CheckEvent (Timeout))) {
|
||||
if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
||||
Tcp4->Poll (Tcp4);
|
||||
} else {
|
||||
Tcp6->Poll (Tcp6);
|
||||
}
|
||||
}
|
||||
|
||||
if (!TcpIo->IsConnDone) {
|
||||
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.
|
||||
|
||||
|
||||
@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
|
||||
)
|
||||
{
|
||||
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 && EFI_ERROR (gBS->CheckEvent (Timeout))) {
|
||||
if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
||||
Tcp4->Poll (Tcp4);
|
||||
} else {
|
||||
Tcp6->Poll (Tcp6);
|
||||
}
|
||||
}
|
||||
|
||||
if (!TcpIo->IsListenDone) {
|
||||
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 trasmitted.
|
||||
@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;
|
||||
|
||||
//
|
||||
// Trasnmit 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 asyncronous or not.
|
||||
@param[in] Timeout The time to wait for receiving the amount of data the Packet
|
||||
can hold.
|
||||
|
||||
@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 momery.
|
||||
@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
|
||||
)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
Tcp4 = NULL;
|
||||
Tcp6 = NULL;
|
||||
|
||||
if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
||||
TcpIo->RxToken.Tcp4Token.Packet.RxData = &RxData;
|
||||
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) {
|
||||
TcpIo->RxToken.Tcp6Token.Packet.RxData = (EFI_TCP6_RECEIVE_DATA *) &RxData;
|
||||
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) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
//
|
||||
// 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 (TcpIo->TcpVersion == TCP_VERSION_4) {
|
||||
TcpIo->RxToken.Tcp4Token.Packet.RxData = NULL;
|
||||
} else {
|
||||
TcpIo->RxToken.Tcp6Token.Packet.RxData = NULL;
|
||||
}
|
||||
|
||||
FreePool (Fragment);
|
||||
|
||||
return Status;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
## @file
|
||||
# Instance of TcpIoLib.
|
||||
#
|
||||
# This module provides TCP services by consuming EFI TCP Service Binding Protocol and
|
||||
# EFI TCP Protocol.
|
||||
#
|
||||
# Copyright (c) 2010, 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.
|
||||
#
|
||||
##
|
||||
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = DxeTcpIoLib
|
||||
FILE_GUID = D4608509-1AB0-4cc7-827A-AB8E1E7BD3E6
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = TcpIoLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources]
|
||||
DxeTcpIoLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
TcpIoLib
|
||||
BaseLib
|
||||
DebugLib
|
||||
UefiBootServicesTableLib
|
||||
MemoryAllocationLib
|
||||
BaseMemoryLib
|
||||
|
||||
[Protocols]
|
||||
gEfiTcp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiTcp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiTcp6ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiTcp6ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
|
@ -39,6 +39,10 @@
|
|||
# This library is only intended to be used by UEFI network stack modules.
|
||||
UdpIoLib|Include/Library/UdpIoLib.h
|
||||
|
||||
## @libraryclass The helper routines to access TCP service.
|
||||
# This library is only intended to be used by UEFI network stack modules.
|
||||
TcpIoLib|Include/Library/TcpIoLib.h
|
||||
|
||||
## @libraryclass Defines a set of methods to reset whole system.
|
||||
ResetSystemLib|Include/Library/ResetSystemLib.h
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
|
||||
IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf
|
||||
UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
|
||||
TcpIoLib|MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf
|
||||
DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
|
||||
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
|
||||
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
|
||||
|
|
Loading…
Reference in New Issue