+++ /dev/null
-/** @file\r
- The wrap of TCP/IP Socket interface.\r
-\r
-Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "IScsiImpl.h"\r
-\r
-/**\r
- The common notify function associated with various Tcp4Io events.\r
-\r
- @param[in] Event The event signaled.\r
- @param[in] Context The context.\r
-**/\r
-VOID\r
-EFIAPI\r
-Tcp4IoCommonNotify (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- *((BOOLEAN *) Context) = TRUE;\r
-}\r
-\r
-/**\r
- Create a TCP socket with the specified configuration data.\r
-\r
- @param[in] Image The handle of the driver image.\r
- @param[in] Controller The handle of the controller.\r
- @param[in] ConfigData The Tcp4 configuration data.\r
- @param[in] Tcp4Io The Tcp4Io.\r
-\r
- @retval EFI_SUCCESS The TCP socket is created and configured.\r
- @retval Others Failed to create the TCP socket or configure it.\r
-**/\r
-EFI_STATUS\r
-Tcp4IoCreateSocket (\r
- IN EFI_HANDLE Image,\r
- IN EFI_HANDLE Controller,\r
- IN TCP4_IO_CONFIG_DATA *ConfigData,\r
- IN TCP4_IO *Tcp4Io\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_TCP4_PROTOCOL *Tcp4;\r
- EFI_TCP4_CONFIG_DATA Tcp4ConfigData;\r
- EFI_TCP4_OPTION ControlOption;\r
- EFI_TCP4_ACCESS_POINT *AccessPoint;\r
-\r
- Tcp4Io->Handle = NULL;\r
- Tcp4Io->ConnToken.CompletionToken.Event = NULL;\r
- Tcp4Io->TxToken.CompletionToken.Event = NULL;\r
- Tcp4Io->RxToken.CompletionToken.Event = NULL;\r
- Tcp4Io->CloseToken.CompletionToken.Event = NULL;\r
- Tcp4 = NULL;\r
-\r
- //\r
- // Create the TCP4 child instance and get the TCP4 protocol.\r
- //\r
- Status = NetLibCreateServiceChild (\r
- Controller,\r
- Image,\r
- &gEfiTcp4ServiceBindingProtocolGuid,\r
- &Tcp4Io->Handle\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = gBS->OpenProtocol (\r
- Tcp4Io->Handle,\r
- &gEfiTcp4ProtocolGuid,\r
- (VOID **)&Tcp4Io->Tcp4,\r
- Image,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- Tcp4Io->Image = Image;\r
- Tcp4Io->Controller = Controller;\r
- Tcp4 = Tcp4Io->Tcp4;\r
-\r
- //\r
- // Set the configuration parameters.\r
- //\r
- ControlOption.ReceiveBufferSize = 0x200000;\r
- ControlOption.SendBufferSize = 0x200000;\r
- ControlOption.MaxSynBackLog = 0;\r
- ControlOption.ConnectionTimeout = 0;\r
- ControlOption.DataRetries = 6;\r
- ControlOption.FinTimeout = 0;\r
- ControlOption.TimeWaitTimeout = 0;\r
- ControlOption.KeepAliveProbes = 4;\r
- ControlOption.KeepAliveTime = 0;\r
- ControlOption.KeepAliveInterval = 0;\r
- ControlOption.EnableNagle = FALSE;\r
- ControlOption.EnableTimeStamp = FALSE;\r
- ControlOption.EnableWindowScaling = TRUE;\r
- ControlOption.EnableSelectiveAck = FALSE;\r
- ControlOption.EnablePathMtuDiscovery = FALSE;\r
-\r
- Tcp4ConfigData.TypeOfService = 8;\r
- Tcp4ConfigData.TimeToLive = 255;\r
- Tcp4ConfigData.ControlOption = &ControlOption;\r
-\r
- AccessPoint = &Tcp4ConfigData.AccessPoint;\r
-\r
- AccessPoint->UseDefaultAddress = FALSE;\r
- AccessPoint->StationPort = 0;\r
- AccessPoint->RemotePort = ConfigData->RemotePort;\r
- AccessPoint->ActiveFlag = TRUE;\r
-\r
- CopyMem (&AccessPoint->StationAddress, &ConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));\r
- CopyMem (&AccessPoint->SubnetMask, &ConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
- CopyMem (&AccessPoint->RemoteAddress, &ConfigData->RemoteIp, sizeof (EFI_IPv4_ADDRESS));\r
-\r
- //\r
- // Configure the TCP4 protocol.\r
- //\r
- Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- if (!EFI_IP4_EQUAL (&ConfigData->Gateway, &mZeroIp4Addr)) {\r
- //\r
- // the gateway is not zero, add the default route by hand\r
- //\r
- Status = Tcp4->Routes (Tcp4, FALSE, &mZeroIp4Addr, &mZeroIp4Addr, &ConfigData->Gateway);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
- }\r
- //\r
- // Create events for variuos asynchronous operations.\r
- //\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- Tcp4IoCommonNotify,\r
- &Tcp4Io->IsConnDone,\r
- &Tcp4Io->ConnToken.CompletionToken.Event\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- Tcp4IoCommonNotify,\r
- &Tcp4Io->IsTxDone,\r
- &Tcp4Io->TxToken.CompletionToken.Event\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- Tcp4IoCommonNotify,\r
- &Tcp4Io->IsRxDone,\r
- &Tcp4Io->RxToken.CompletionToken.Event\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- Tcp4IoCommonNotify,\r
- &Tcp4Io->IsCloseDone,\r
- &Tcp4Io->CloseToken.CompletionToken.Event\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- Tcp4Io->IsTxDone = FALSE;\r
- Tcp4Io->IsRxDone = FALSE;\r
-\r
- return EFI_SUCCESS;\r
-\r
-ON_ERROR:\r
-\r
- if (Tcp4Io->RxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);\r
- }\r
-\r
- if (Tcp4Io->TxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);\r
- }\r
-\r
- if (Tcp4Io->ConnToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);\r
- }\r
-\r
- if (Tcp4 != NULL) {\r
- Tcp4->Configure (Tcp4, NULL);\r
-\r
- gBS->CloseProtocol (\r
- Tcp4Io->Handle,\r
- &gEfiTcp4ProtocolGuid,\r
- Image,\r
- Controller\r
- );\r
- }\r
-\r
- NetLibDestroyServiceChild (\r
- Controller,\r
- Image,\r
- &gEfiTcp4ServiceBindingProtocolGuid,\r
- Tcp4Io->Handle\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Destroy the socket.\r
-\r
- @param[in] Tcp4Io The Tcp4Io which wraps the socket to be destroyeds.\r
-**/\r
-VOID\r
-Tcp4IoDestroySocket (\r
- IN TCP4_IO *Tcp4Io\r
- )\r
-{\r
- EFI_TCP4_PROTOCOL *Tcp4;\r
-\r
- Tcp4 = Tcp4Io->Tcp4;\r
-\r
- Tcp4->Configure (Tcp4, NULL);\r
-\r
- gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);\r
- gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);\r
- gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);\r
-\r
- gBS->CloseProtocol (\r
- Tcp4Io->Handle,\r
- &gEfiTcp4ProtocolGuid,\r
- Tcp4Io->Image,\r
- Tcp4Io->Controller\r
- );\r
-\r
- NetLibDestroyServiceChild (\r
- Tcp4Io->Controller,\r
- Tcp4Io->Image,\r
- &gEfiTcp4ServiceBindingProtocolGuid,\r
- Tcp4Io->Handle\r
- );\r
-}\r
-\r
-/**\r
- Connect to the other endpoint of the TCP socket.\r
-\r
- @param[in, out] Tcp4Io The Tcp4Io wrapping the TCP socket.\r
- @param[in] Timeout The time to wait for connection done.\r
-\r
- @retval EFI_SUCCESS Connect to the other endpoint of the TCP socket successfully.\r
- @retval EFI_TIMEOUT Failed to connect to the other endpoint of the TCP socket in the specified time period.\r
- @retval Others Other errors as indicated.\r
-**/\r
-EFI_STATUS\r
-Tcp4IoConnect (\r
- IN OUT TCP4_IO *Tcp4Io,\r
- IN EFI_EVENT Timeout\r
- )\r
-{\r
- EFI_TCP4_PROTOCOL *Tcp4;\r
- EFI_STATUS Status;\r
-\r
- Tcp4Io->IsConnDone = FALSE;\r
- Tcp4 = Tcp4Io->Tcp4;\r
- Status = Tcp4->Connect (Tcp4, &Tcp4Io->ConnToken);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- while (!Tcp4Io->IsConnDone && EFI_ERROR (gBS->CheckEvent (Timeout))) {\r
- Tcp4->Poll (Tcp4);\r
- }\r
-\r
- if (!Tcp4Io->IsConnDone) {\r
- Status = EFI_TIMEOUT;\r
- } else {\r
- Status = Tcp4Io->ConnToken.CompletionToken.Status;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Reset the socket.\r
-\r
- @param[in, out] Tcp4Io The Tcp4Io wrapping the TCP socket.\r
-**/\r
-VOID\r
-Tcp4IoReset (\r
- IN OUT TCP4_IO *Tcp4Io\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_TCP4_PROTOCOL *Tcp4;\r
-\r
- Tcp4Io->CloseToken.AbortOnClose = TRUE;\r
- Tcp4Io->IsCloseDone = FALSE;\r
-\r
- Tcp4 = Tcp4Io->Tcp4;\r
- Status = Tcp4->Close (Tcp4, &Tcp4Io->CloseToken);\r
- if (EFI_ERROR (Status)) {\r
- return ;\r
- }\r
-\r
- while (!Tcp4Io->IsCloseDone) {\r
- Tcp4->Poll (Tcp4);\r
- }\r
-}\r
-\r
-/**\r
- Transmit the Packet to the other endpoint of the socket.\r
-\r
- @param[in] Tcp4Io The Tcp4Io wrapping the TCP socket.\r
- @param[in] Packet The packet to transmit.\r
-\r
- @retval EFI_SUCCESS The packet is trasmitted.\r
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
- @retval Others Other errors as indicated.\r
-**/\r
-EFI_STATUS\r
-Tcp4IoTransmit (\r
- IN TCP4_IO *Tcp4Io,\r
- IN NET_BUF *Packet\r
- )\r
-{\r
- EFI_TCP4_TRANSMIT_DATA *TxData;\r
- EFI_TCP4_PROTOCOL *Tcp4;\r
- EFI_STATUS Status;\r
-\r
- TxData = AllocatePool (sizeof (EFI_TCP4_TRANSMIT_DATA) + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA));\r
- if (TxData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- TxData->Push = TRUE;\r
- TxData->Urgent = FALSE;\r
- TxData->DataLength = Packet->TotalSize;\r
-\r
- //\r
- // Build the fragment table.\r
- //\r
- TxData->FragmentCount = Packet->BlockOpNum;\r
- NetbufBuildExt (Packet, (NET_FRAGMENT *) &TxData->FragmentTable[0], &TxData->FragmentCount);\r
-\r
- Tcp4Io->TxToken.Packet.TxData = TxData;\r
-\r
- //\r
- // Trasnmit the packet.\r
- //\r
- Tcp4 = Tcp4Io->Tcp4;\r
- Status = Tcp4->Transmit (Tcp4, &Tcp4Io->TxToken);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_EXIT;\r
- }\r
-\r
- while (!Tcp4Io->IsTxDone) {\r
- Tcp4->Poll (Tcp4);\r
- }\r
-\r
- Tcp4Io->IsTxDone = FALSE;\r
-\r
- Status = Tcp4Io->TxToken.CompletionToken.Status;\r
-\r
-ON_EXIT:\r
-\r
- FreePool (TxData);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Receive data from the socket.\r
-\r
- @param[in] Tcp4Io The Tcp4Io which wraps the socket to be destroyed.\r
- @param[in] Packet The buffer to hold the data copy from the soket rx buffer.\r
- @param[in] AsyncMode Is this receive asyncronous or not.\r
- @param[in] Timeout The time to wait for receiving the amount of data the Packet\r
- can hold.\r
-\r
- @retval EFI_SUCCESS The required amount of data is received from the socket.\r
- @retval EFI_OUT_OF_RESOURCES Failed to allocate momery.\r
- @retval EFI_TIMEOUT Failed to receive the required amount of data in the\r
- specified time period.\r
- @retval Others Other errors as indicated.\r
-**/\r
-EFI_STATUS\r
-Tcp4IoReceive (\r
- IN TCP4_IO *Tcp4Io,\r
- IN NET_BUF *Packet,\r
- IN BOOLEAN AsyncMode,\r
- IN EFI_EVENT Timeout\r
- )\r
-{\r
- EFI_TCP4_PROTOCOL *Tcp4;\r
- EFI_TCP4_RECEIVE_DATA RxData;\r
- EFI_STATUS Status;\r
- NET_FRAGMENT *Fragment;\r
- UINT32 FragmentCount;\r
- UINT32 CurrentFragment;\r
-\r
- FragmentCount = Packet->BlockOpNum;\r
- Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));\r
- if (Fragment == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // Build the fragment table.\r
- //\r
- NetbufBuildExt (Packet, Fragment, &FragmentCount);\r
-\r
- RxData.FragmentCount = 1;\r
- Tcp4Io->RxToken.Packet.RxData = &RxData;\r
- CurrentFragment = 0;\r
- Tcp4 = Tcp4Io->Tcp4;\r
- Status = EFI_SUCCESS;\r
-\r
- while (CurrentFragment < FragmentCount) {\r
- RxData.DataLength = Fragment[CurrentFragment].Len;\r
- RxData.FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len;\r
- RxData.FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk;\r
-\r
- Status = Tcp4->Receive (Tcp4, &Tcp4Io->RxToken);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_EXIT;\r
- }\r
-\r
- while (!Tcp4Io->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
- //\r
- // Poll until some data is received or something error happens.\r
- //\r
- Tcp4->Poll (Tcp4);\r
- }\r
-\r
- if (!Tcp4Io->IsRxDone) {\r
- //\r
- // Timeout occurs, cancel the receive request.\r
- //\r
- Tcp4->Cancel (Tcp4, &Tcp4Io->RxToken.CompletionToken);\r
-\r
- Status = EFI_TIMEOUT;\r
- goto ON_EXIT;\r
- } else {\r
- Tcp4Io->IsRxDone = FALSE;\r
- }\r
-\r
- if (EFI_ERROR (Tcp4Io->RxToken.CompletionToken.Status)) {\r
- Status = Tcp4Io->RxToken.CompletionToken.Status;\r
- goto ON_EXIT;\r
- }\r
-\r
- Fragment[CurrentFragment].Len -= RxData.FragmentTable[0].FragmentLength;\r
- if (Fragment[CurrentFragment].Len == 0) {\r
- CurrentFragment++;\r
- } else {\r
- Fragment[CurrentFragment].Bulk += RxData.FragmentTable[0].FragmentLength;\r
- }\r
- }\r
-\r
-ON_EXIT:\r
- Tcp4Io->RxToken.Packet.RxData = NULL;\r
- FreePool (Fragment);\r
-\r
- return Status;\r
-}\r