2 The wrap of TCP/IP Socket interface
4 Copyright (c) 2004 - 2007, Intel Corporation
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.
18 The wrap of TCP/IP Socket interface
22 #include "IScsiImpl.h"
25 The common notify function associated with various Tcp4Io events.
27 @param Event[in] The event signaled.
29 @param Contect[in] The context.
41 *((BOOLEAN
*) Context
) = TRUE
;
45 Create a TCP socket with the specified configuration data.
47 @param Image[in] The handle of the driver image.
49 @param Controller[in] The handle of the controller.
51 @param ConfigData[in] The Tcp4 configuration data.
53 @param Tcp4Io[in] The Tcp4Io.
55 @retval EFI_SUCCESS The TCP socket is created and configured.
57 @retval Other Failed to create the TCP socket or configure it.
63 IN EFI_HANDLE Controller
,
64 IN TCP4_IO_CONFIG_DATA
*ConfigData
,
69 EFI_TCP4_PROTOCOL
*Tcp4
;
70 EFI_TCP4_CONFIG_DATA Tcp4ConfigData
;
71 EFI_TCP4_OPTION ControlOption
;
72 EFI_TCP4_ACCESS_POINT
*AccessPoint
;
74 Tcp4Io
->Handle
= NULL
;
75 Tcp4Io
->ConnToken
.CompletionToken
.Event
= NULL
;
76 Tcp4Io
->TxToken
.CompletionToken
.Event
= NULL
;
77 Tcp4Io
->RxToken
.CompletionToken
.Event
= NULL
;
78 Tcp4Io
->CloseToken
.CompletionToken
.Event
= NULL
;
82 // Create the TCP4 child instance and get the TCP4 protocol.
84 Status
= NetLibCreateServiceChild (
87 &gEfiTcp4ServiceBindingProtocolGuid
,
90 if (EFI_ERROR (Status
)) {
94 Status
= gBS
->OpenProtocol (
96 &gEfiTcp4ProtocolGuid
,
97 (VOID
**)&Tcp4Io
->Tcp4
,
100 EFI_OPEN_PROTOCOL_BY_DRIVER
102 if (EFI_ERROR (Status
)) {
106 Tcp4Io
->Image
= Image
;
107 Tcp4Io
->Controller
= Controller
;
111 // Set the configuration parameters.
113 ControlOption
.ReceiveBufferSize
= 0x200000;
114 ControlOption
.SendBufferSize
= 0x200000;
115 ControlOption
.MaxSynBackLog
= 0;
116 ControlOption
.ConnectionTimeout
= 0;
117 ControlOption
.DataRetries
= 6;
118 ControlOption
.FinTimeout
= 0;
119 ControlOption
.TimeWaitTimeout
= 0;
120 ControlOption
.KeepAliveProbes
= 4;
121 ControlOption
.KeepAliveTime
= 0;
122 ControlOption
.KeepAliveInterval
= 0;
123 ControlOption
.EnableNagle
= FALSE
;
124 ControlOption
.EnableTimeStamp
= FALSE
;
125 ControlOption
.EnableWindowScaling
= TRUE
;
126 ControlOption
.EnableSelectiveAck
= FALSE
;
127 ControlOption
.EnablePathMtuDiscovery
= FALSE
;
129 Tcp4ConfigData
.TypeOfService
= 8;
130 Tcp4ConfigData
.TimeToLive
= 255;
131 Tcp4ConfigData
.ControlOption
= &ControlOption
;
133 AccessPoint
= &Tcp4ConfigData
.AccessPoint
;
135 AccessPoint
->UseDefaultAddress
= FALSE
;
136 AccessPoint
->StationPort
= 0;
137 AccessPoint
->RemotePort
= ConfigData
->RemotePort
;
138 AccessPoint
->ActiveFlag
= TRUE
;
140 CopyMem (&AccessPoint
->StationAddress
, &ConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
141 CopyMem (&AccessPoint
->SubnetMask
, &ConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
142 CopyMem (&AccessPoint
->RemoteAddress
, &ConfigData
->RemoteIp
, sizeof (EFI_IPv4_ADDRESS
));
145 // Configure the TCP4 protocol.
147 Status
= Tcp4
->Configure (Tcp4
, &Tcp4ConfigData
);
148 if (EFI_ERROR (Status
)) {
152 if (!EFI_IP4_EQUAL (&ConfigData
->Gateway
, &mZeroIp4Addr
)) {
154 // the gateway is not zero, add the default route by hand
156 Status
= Tcp4
->Routes (Tcp4
, FALSE
, &mZeroIp4Addr
, &mZeroIp4Addr
, &ConfigData
->Gateway
);
157 if (EFI_ERROR (Status
)) {
162 // Create events for variuos asynchronous operations.
164 Status
= gBS
->CreateEvent (
169 &Tcp4Io
->ConnToken
.CompletionToken
.Event
171 if (EFI_ERROR (Status
)) {
175 Status
= gBS
->CreateEvent (
180 &Tcp4Io
->TxToken
.CompletionToken
.Event
182 if (EFI_ERROR (Status
)) {
186 Status
= gBS
->CreateEvent (
191 &Tcp4Io
->RxToken
.CompletionToken
.Event
193 if (EFI_ERROR (Status
)) {
197 Status
= gBS
->CreateEvent (
201 &Tcp4Io
->IsCloseDone
,
202 &Tcp4Io
->CloseToken
.CompletionToken
.Event
204 if (EFI_ERROR (Status
)) {
208 Tcp4Io
->IsTxDone
= FALSE
;
209 Tcp4Io
->IsRxDone
= FALSE
;
215 if (Tcp4Io
->RxToken
.CompletionToken
.Event
!= NULL
) {
216 gBS
->CloseEvent (Tcp4Io
->RxToken
.CompletionToken
.Event
);
219 if (Tcp4Io
->TxToken
.CompletionToken
.Event
!= NULL
) {
220 gBS
->CloseEvent (Tcp4Io
->TxToken
.CompletionToken
.Event
);
223 if (Tcp4Io
->ConnToken
.CompletionToken
.Event
!= NULL
) {
224 gBS
->CloseEvent (Tcp4Io
->ConnToken
.CompletionToken
.Event
);
228 Tcp4
->Configure (Tcp4
, NULL
);
232 &gEfiTcp4ProtocolGuid
,
238 NetLibDestroyServiceChild (
241 &gEfiTcp4ServiceBindingProtocolGuid
,
251 @param[in] Tcp4Io The Tcp4Io which wraps the socket to be destroyeds.
257 Tcp4IoDestroySocket (
261 EFI_TCP4_PROTOCOL
*Tcp4
;
265 Tcp4
->Configure (Tcp4
, NULL
);
267 gBS
->CloseEvent (Tcp4Io
->TxToken
.CompletionToken
.Event
);
268 gBS
->CloseEvent (Tcp4Io
->RxToken
.CompletionToken
.Event
);
269 gBS
->CloseEvent (Tcp4Io
->ConnToken
.CompletionToken
.Event
);
273 &gEfiTcp4ProtocolGuid
,
278 NetLibDestroyServiceChild (
281 &gEfiTcp4ServiceBindingProtocolGuid
,
287 Connect to the other endpoint of the TCP socket.
289 @param Tcp4Io[in] The Tcp4Io wrapping the TCP socket.
291 @param Timeout[in] The time to wait for connection done.
302 EFI_TCP4_PROTOCOL
*Tcp4
;
305 Tcp4Io
->IsConnDone
= FALSE
;
307 Status
= Tcp4
->Connect (Tcp4
, &Tcp4Io
->ConnToken
);
308 if (EFI_ERROR (Status
)) {
312 while (!Tcp4Io
->IsConnDone
&& EFI_ERROR (gBS
->CheckEvent (Timeout
))) {
316 if (!Tcp4Io
->IsConnDone
) {
317 Status
= EFI_TIMEOUT
;
319 Status
= Tcp4Io
->ConnToken
.CompletionToken
.Status
;
328 @param Tcp4Io[in] The Tcp4Io wrapping the TCP socket.
339 EFI_TCP4_PROTOCOL
*Tcp4
;
341 Tcp4Io
->CloseToken
.AbortOnClose
= TRUE
;
342 Tcp4Io
->IsCloseDone
= FALSE
;
345 Status
= Tcp4
->Close (Tcp4
, &Tcp4Io
->CloseToken
);
346 if (EFI_ERROR (Status
)) {
350 while (!Tcp4Io
->IsCloseDone
) {
356 Transmit the Packet to the other endpoint of the socket.
358 @param Tcp4Io[in] The Tcp4Io wrapping the TCP socket.
360 @param Packet[in] The packet to transmit
362 @retval EFI_SUCCESS The packet is trasmitted.
364 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
373 EFI_TCP4_TRANSMIT_DATA
*TxData
;
374 EFI_TCP4_PROTOCOL
*Tcp4
;
377 TxData
= AllocatePool (sizeof (EFI_TCP4_TRANSMIT_DATA
) + (Packet
->BlockOpNum
- 1) * sizeof (EFI_TCP4_FRAGMENT_DATA
));
378 if (TxData
== NULL
) {
379 return EFI_OUT_OF_RESOURCES
;
383 TxData
->Urgent
= FALSE
;
384 TxData
->DataLength
= Packet
->TotalSize
;
387 // Build the fragment table.
389 TxData
->FragmentCount
= Packet
->BlockOpNum
;
390 NetbufBuildExt (Packet
, (NET_FRAGMENT
*) &TxData
->FragmentTable
[0], &TxData
->FragmentCount
);
392 Tcp4Io
->TxToken
.Packet
.TxData
= TxData
;
395 // Trasnmit the packet.
398 Status
= Tcp4
->Transmit (Tcp4
, &Tcp4Io
->TxToken
);
399 if (EFI_ERROR (Status
)) {
403 while (!Tcp4Io
->IsTxDone
) {
407 Tcp4Io
->IsTxDone
= FALSE
;
409 Status
= Tcp4Io
->TxToken
.CompletionToken
.Status
;
413 gBS
->FreePool (TxData
);
419 Receive data from the socket.
421 @param Tcp4Io[in] The Tcp4Io which wraps the socket to be destroyeds.
423 @param Packet[in] The buffer to hold the data copy from the soket rx buffer.
425 @param AsyncMode[in] Is this receive asyncronous or not.
427 @param Timeout[in] The time to wait for receiving the amount of data the Packet
430 @retval EFI_SUCCESS The required amount of data is received from the socket.
432 @retval EFI_OUT_OF_RESOURCES Failed to allocate momery.
434 @retval EFI_TIMEOUT Failed to receive the required amount of data in the
435 specified time period.
442 IN BOOLEAN AsyncMode
,
446 EFI_TCP4_PROTOCOL
*Tcp4
;
447 EFI_TCP4_RECEIVE_DATA RxData
;
449 NET_FRAGMENT
*Fragment
;
450 UINT32 FragmentCount
;
451 UINT32 CurrentFragment
;
453 FragmentCount
= Packet
->BlockOpNum
;
454 Fragment
= AllocatePool (FragmentCount
* sizeof (NET_FRAGMENT
));
455 if (Fragment
== NULL
) {
456 return EFI_OUT_OF_RESOURCES
;
459 // Build the fragment table.
461 NetbufBuildExt (Packet
, Fragment
, &FragmentCount
);
463 RxData
.FragmentCount
= 1;
464 Tcp4Io
->RxToken
.Packet
.RxData
= &RxData
;
467 Status
= EFI_SUCCESS
;
469 while (CurrentFragment
< FragmentCount
) {
470 RxData
.DataLength
= Fragment
[CurrentFragment
].Len
;
471 RxData
.FragmentTable
[0].FragmentLength
= Fragment
[CurrentFragment
].Len
;
472 RxData
.FragmentTable
[0].FragmentBuffer
= Fragment
[CurrentFragment
].Bulk
;
474 Status
= Tcp4
->Receive (Tcp4
, &Tcp4Io
->RxToken
);
475 if (EFI_ERROR (Status
)) {
479 while (!Tcp4Io
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
481 // Poll until some data is received or something error happens.
486 if (!Tcp4Io
->IsRxDone
) {
488 // Timeout occurs, cancel the receive request.
490 Tcp4
->Cancel (Tcp4
, &Tcp4Io
->RxToken
.CompletionToken
);
492 Status
= EFI_TIMEOUT
;
495 Tcp4Io
->IsRxDone
= FALSE
;
498 if (EFI_ERROR (Tcp4Io
->RxToken
.CompletionToken
.Status
)) {
499 Status
= Tcp4Io
->RxToken
.CompletionToken
.Status
;
503 Fragment
[CurrentFragment
].Len
-= RxData
.FragmentTable
[0].FragmentLength
;
504 if (Fragment
[CurrentFragment
].Len
== 0) {
507 Fragment
[CurrentFragment
].Bulk
+= RxData
.FragmentTable
[0].FragmentLength
;
513 gBS
->FreePool (Fragment
);