diff options
author | tye1 <tye1@6f19259b-4bc3-4df7-8a09-765794883524> | 2010-12-14 03:19:21 +0000 |
---|---|---|
committer | tye1 <tye1@6f19259b-4bc3-4df7-8a09-765794883524> | 2010-12-14 03:19:21 +0000 |
commit | 4bad9adabc25c7d011a4da90a77f985d19c441e2 (patch) | |
tree | 2db70adedc7d07e1686191514fce45883afc790c | |
parent | 4e36d6f52689c3173635847921da0d8a497a0870 (diff) | |
download | edk2-4bad9adabc25c7d011a4da90a77f985d19c441e2.tar.gz edk2-4bad9adabc25c7d011a4da90a77f985d19c441e2.tar.bz2 edk2-4bad9adabc25c7d011a4da90a77f985d19c441e2.zip |
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
-rw-r--r-- | MdeModulePkg/Include/Library/TcpIoLib.h | 252 | ||||
-rw-r--r-- | MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.c | 993 | ||||
-rw-r--r-- | MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf | 53 | ||||
-rw-r--r-- | MdeModulePkg/MdeModulePkg.dec | 4 | ||||
-rw-r--r-- | MdeModulePkg/MdeModulePkg.dsc | 1 |
5 files changed, 1303 insertions, 0 deletions
diff --git a/MdeModulePkg/Include/Library/TcpIoLib.h b/MdeModulePkg/Include/Library/TcpIoLib.h new file mode 100644 index 0000000000..050f14b28f --- /dev/null +++ b/MdeModulePkg/Include/Library/TcpIoLib.h @@ -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
+
diff --git a/MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.c b/MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.c new file mode 100644 index 0000000000..48120b4353 --- /dev/null +++ b/MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.c @@ -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;
+}
diff --git a/MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf b/MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf new file mode 100644 index 0000000000..808b98bed5 --- /dev/null +++ b/MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf @@ -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
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 0530f91180..8cf4b75309 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -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
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index d8a3826ef7..86ad3f521e 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -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
|