2 The wrap of TCP/IP Socket interface.
4 Copyright (c) 2004 - 2009, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "IScsiImpl.h"
18 The common notify function associated with various Tcp4Io events.
20 @param[in] Event The event signaled.
21 @param[in] Context The context.
30 *((BOOLEAN
*) Context
) = TRUE
;
34 Create a TCP socket with the specified configuration data.
36 @param[in] Image The handle of the driver image.
37 @param[in] Controller The handle of the controller.
38 @param[in] ConfigData The Tcp4 configuration data.
39 @param[in] Tcp4Io The Tcp4Io.
41 @retval EFI_SUCCESS The TCP socket is created and configured.
42 @retval Others Failed to create the TCP socket or configure it.
47 IN EFI_HANDLE Controller
,
48 IN TCP4_IO_CONFIG_DATA
*ConfigData
,
53 EFI_TCP4_PROTOCOL
*Tcp4
;
54 EFI_TCP4_CONFIG_DATA Tcp4ConfigData
;
55 EFI_TCP4_OPTION ControlOption
;
56 EFI_TCP4_ACCESS_POINT
*AccessPoint
;
58 Tcp4Io
->Handle
= NULL
;
59 Tcp4Io
->ConnToken
.CompletionToken
.Event
= NULL
;
60 Tcp4Io
->TxToken
.CompletionToken
.Event
= NULL
;
61 Tcp4Io
->RxToken
.CompletionToken
.Event
= NULL
;
62 Tcp4Io
->CloseToken
.CompletionToken
.Event
= NULL
;
66 // Create the TCP4 child instance and get the TCP4 protocol.
68 Status
= NetLibCreateServiceChild (
71 &gEfiTcp4ServiceBindingProtocolGuid
,
74 if (EFI_ERROR (Status
)) {
78 Status
= gBS
->OpenProtocol (
80 &gEfiTcp4ProtocolGuid
,
81 (VOID
**)&Tcp4Io
->Tcp4
,
84 EFI_OPEN_PROTOCOL_BY_DRIVER
86 if (EFI_ERROR (Status
)) {
90 Tcp4Io
->Image
= Image
;
91 Tcp4Io
->Controller
= Controller
;
95 // Set the configuration parameters.
97 ControlOption
.ReceiveBufferSize
= 0x200000;
98 ControlOption
.SendBufferSize
= 0x200000;
99 ControlOption
.MaxSynBackLog
= 0;
100 ControlOption
.ConnectionTimeout
= 0;
101 ControlOption
.DataRetries
= 6;
102 ControlOption
.FinTimeout
= 0;
103 ControlOption
.TimeWaitTimeout
= 0;
104 ControlOption
.KeepAliveProbes
= 4;
105 ControlOption
.KeepAliveTime
= 0;
106 ControlOption
.KeepAliveInterval
= 0;
107 ControlOption
.EnableNagle
= FALSE
;
108 ControlOption
.EnableTimeStamp
= FALSE
;
109 ControlOption
.EnableWindowScaling
= TRUE
;
110 ControlOption
.EnableSelectiveAck
= FALSE
;
111 ControlOption
.EnablePathMtuDiscovery
= FALSE
;
113 Tcp4ConfigData
.TypeOfService
= 8;
114 Tcp4ConfigData
.TimeToLive
= 255;
115 Tcp4ConfigData
.ControlOption
= &ControlOption
;
117 AccessPoint
= &Tcp4ConfigData
.AccessPoint
;
119 AccessPoint
->UseDefaultAddress
= FALSE
;
120 AccessPoint
->StationPort
= 0;
121 AccessPoint
->RemotePort
= ConfigData
->RemotePort
;
122 AccessPoint
->ActiveFlag
= TRUE
;
124 CopyMem (&AccessPoint
->StationAddress
, &ConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
125 CopyMem (&AccessPoint
->SubnetMask
, &ConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
126 CopyMem (&AccessPoint
->RemoteAddress
, &ConfigData
->RemoteIp
, sizeof (EFI_IPv4_ADDRESS
));
129 // Configure the TCP4 protocol.
131 Status
= Tcp4
->Configure (Tcp4
, &Tcp4ConfigData
);
132 if (EFI_ERROR (Status
)) {
136 if (!EFI_IP4_EQUAL (&ConfigData
->Gateway
, &mZeroIp4Addr
)) {
138 // the gateway is not zero, add the default route by hand
140 Status
= Tcp4
->Routes (Tcp4
, FALSE
, &mZeroIp4Addr
, &mZeroIp4Addr
, &ConfigData
->Gateway
);
141 if (EFI_ERROR (Status
)) {
146 // Create events for variuos asynchronous operations.
148 Status
= gBS
->CreateEvent (
153 &Tcp4Io
->ConnToken
.CompletionToken
.Event
155 if (EFI_ERROR (Status
)) {
159 Status
= gBS
->CreateEvent (
164 &Tcp4Io
->TxToken
.CompletionToken
.Event
166 if (EFI_ERROR (Status
)) {
170 Status
= gBS
->CreateEvent (
175 &Tcp4Io
->RxToken
.CompletionToken
.Event
177 if (EFI_ERROR (Status
)) {
181 Status
= gBS
->CreateEvent (
185 &Tcp4Io
->IsCloseDone
,
186 &Tcp4Io
->CloseToken
.CompletionToken
.Event
188 if (EFI_ERROR (Status
)) {
192 Tcp4Io
->IsTxDone
= FALSE
;
193 Tcp4Io
->IsRxDone
= FALSE
;
199 if (Tcp4Io
->RxToken
.CompletionToken
.Event
!= NULL
) {
200 gBS
->CloseEvent (Tcp4Io
->RxToken
.CompletionToken
.Event
);
203 if (Tcp4Io
->TxToken
.CompletionToken
.Event
!= NULL
) {
204 gBS
->CloseEvent (Tcp4Io
->TxToken
.CompletionToken
.Event
);
207 if (Tcp4Io
->ConnToken
.CompletionToken
.Event
!= NULL
) {
208 gBS
->CloseEvent (Tcp4Io
->ConnToken
.CompletionToken
.Event
);
212 Tcp4
->Configure (Tcp4
, NULL
);
216 &gEfiTcp4ProtocolGuid
,
222 NetLibDestroyServiceChild (
225 &gEfiTcp4ServiceBindingProtocolGuid
,
235 @param[in] Tcp4Io The Tcp4Io which wraps the socket to be destroyeds.
238 Tcp4IoDestroySocket (
242 EFI_TCP4_PROTOCOL
*Tcp4
;
246 Tcp4
->Configure (Tcp4
, NULL
);
248 gBS
->CloseEvent (Tcp4Io
->TxToken
.CompletionToken
.Event
);
249 gBS
->CloseEvent (Tcp4Io
->RxToken
.CompletionToken
.Event
);
250 gBS
->CloseEvent (Tcp4Io
->ConnToken
.CompletionToken
.Event
);
254 &gEfiTcp4ProtocolGuid
,
259 NetLibDestroyServiceChild (
262 &gEfiTcp4ServiceBindingProtocolGuid
,
268 Connect to the other endpoint of the TCP socket.
270 @param[in, out] Tcp4Io The Tcp4Io wrapping the TCP socket.
271 @param[in] Timeout The time to wait for connection done.
273 @retval EFI_SUCCESS Connect to the other endpoint of the TCP socket successfully.
274 @retval EFI_TIMEOUT Failed to connect to the other endpoint of the TCP socket in the specified time period.
275 @retval Others Other errors as indicated.
279 IN OUT TCP4_IO
*Tcp4Io
,
283 EFI_TCP4_PROTOCOL
*Tcp4
;
286 Tcp4Io
->IsConnDone
= FALSE
;
288 Status
= Tcp4
->Connect (Tcp4
, &Tcp4Io
->ConnToken
);
289 if (EFI_ERROR (Status
)) {
293 while (!Tcp4Io
->IsConnDone
&& EFI_ERROR (gBS
->CheckEvent (Timeout
))) {
297 if (!Tcp4Io
->IsConnDone
) {
298 Status
= EFI_TIMEOUT
;
300 Status
= Tcp4Io
->ConnToken
.CompletionToken
.Status
;
309 @param[in, out] Tcp4Io The Tcp4Io wrapping the TCP socket.
313 IN OUT TCP4_IO
*Tcp4Io
317 EFI_TCP4_PROTOCOL
*Tcp4
;
319 Tcp4Io
->CloseToken
.AbortOnClose
= TRUE
;
320 Tcp4Io
->IsCloseDone
= FALSE
;
323 Status
= Tcp4
->Close (Tcp4
, &Tcp4Io
->CloseToken
);
324 if (EFI_ERROR (Status
)) {
328 while (!Tcp4Io
->IsCloseDone
) {
334 Transmit the Packet to the other endpoint of the socket.
336 @param[in] Tcp4Io The Tcp4Io wrapping the TCP socket.
337 @param[in] Packet The packet to transmit.
339 @retval EFI_SUCCESS The packet is trasmitted.
340 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
341 @retval Others Other errors as indicated.
349 EFI_TCP4_TRANSMIT_DATA
*TxData
;
350 EFI_TCP4_PROTOCOL
*Tcp4
;
353 TxData
= AllocatePool (sizeof (EFI_TCP4_TRANSMIT_DATA
) + (Packet
->BlockOpNum
- 1) * sizeof (EFI_TCP4_FRAGMENT_DATA
));
354 if (TxData
== NULL
) {
355 return EFI_OUT_OF_RESOURCES
;
359 TxData
->Urgent
= FALSE
;
360 TxData
->DataLength
= Packet
->TotalSize
;
363 // Build the fragment table.
365 TxData
->FragmentCount
= Packet
->BlockOpNum
;
366 NetbufBuildExt (Packet
, (NET_FRAGMENT
*) &TxData
->FragmentTable
[0], &TxData
->FragmentCount
);
368 Tcp4Io
->TxToken
.Packet
.TxData
= TxData
;
371 // Trasnmit the packet.
374 Status
= Tcp4
->Transmit (Tcp4
, &Tcp4Io
->TxToken
);
375 if (EFI_ERROR (Status
)) {
379 while (!Tcp4Io
->IsTxDone
) {
383 Tcp4Io
->IsTxDone
= FALSE
;
385 Status
= Tcp4Io
->TxToken
.CompletionToken
.Status
;
395 Receive data from the socket.
397 @param[in] Tcp4Io The Tcp4Io which wraps the socket to be destroyed.
398 @param[in] Packet The buffer to hold the data copy from the soket rx buffer.
399 @param[in] AsyncMode Is this receive asyncronous or not.
400 @param[in] Timeout The time to wait for receiving the amount of data the Packet
403 @retval EFI_SUCCESS The required amount of data is received from the socket.
404 @retval EFI_OUT_OF_RESOURCES Failed to allocate momery.
405 @retval EFI_TIMEOUT Failed to receive the required amount of data in the
406 specified time period.
407 @retval Others Other errors as indicated.
413 IN BOOLEAN AsyncMode
,
417 EFI_TCP4_PROTOCOL
*Tcp4
;
418 EFI_TCP4_RECEIVE_DATA RxData
;
420 NET_FRAGMENT
*Fragment
;
421 UINT32 FragmentCount
;
422 UINT32 CurrentFragment
;
424 FragmentCount
= Packet
->BlockOpNum
;
425 Fragment
= AllocatePool (FragmentCount
* sizeof (NET_FRAGMENT
));
426 if (Fragment
== NULL
) {
427 return EFI_OUT_OF_RESOURCES
;
430 // Build the fragment table.
432 NetbufBuildExt (Packet
, Fragment
, &FragmentCount
);
434 RxData
.FragmentCount
= 1;
435 Tcp4Io
->RxToken
.Packet
.RxData
= &RxData
;
438 Status
= EFI_SUCCESS
;
440 while (CurrentFragment
< FragmentCount
) {
441 RxData
.DataLength
= Fragment
[CurrentFragment
].Len
;
442 RxData
.FragmentTable
[0].FragmentLength
= Fragment
[CurrentFragment
].Len
;
443 RxData
.FragmentTable
[0].FragmentBuffer
= Fragment
[CurrentFragment
].Bulk
;
445 Status
= Tcp4
->Receive (Tcp4
, &Tcp4Io
->RxToken
);
446 if (EFI_ERROR (Status
)) {
450 while (!Tcp4Io
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
452 // Poll until some data is received or something error happens.
457 if (!Tcp4Io
->IsRxDone
) {
459 // Timeout occurs, cancel the receive request.
461 Tcp4
->Cancel (Tcp4
, &Tcp4Io
->RxToken
.CompletionToken
);
463 Status
= EFI_TIMEOUT
;
466 Tcp4Io
->IsRxDone
= FALSE
;
469 if (EFI_ERROR (Tcp4Io
->RxToken
.CompletionToken
.Status
)) {
470 Status
= Tcp4Io
->RxToken
.CompletionToken
.Status
;
474 Fragment
[CurrentFragment
].Len
-= RxData
.FragmentTable
[0].FragmentLength
;
475 if (Fragment
[CurrentFragment
].Len
== 0) {
478 Fragment
[CurrentFragment
].Bulk
+= RxData
.FragmentTable
[0].FragmentLength
;
483 Tcp4Io
->RxToken
.Packet
.RxData
= NULL
;