]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/IScsiDxe/IScsiTcp4Io.c
Use Mde library and definition instead of some native definitions in NetLib, to simpl...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiTcp4Io.c
1 /*++
2
3 Copyright (c) 2004 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 IScsiTcp4Io.c
15
16 Abstract:
17
18 --*/
19
20 #include "IScsiImpl.h"
21
22 VOID
23 EFIAPI
24 Tcp4IoCommonNotify (
25 IN EFI_EVENT Event,
26 IN VOID *Context
27 )
28 /*++
29
30 Routine Description:
31
32 The common notify function associated with various Tcp4Io events.
33
34 Arguments:
35
36 Event - The event signaled.
37 Contect - The context.
38
39 Returns:
40
41 None.
42
43 --*/
44 {
45 *((BOOLEAN *) Context) = TRUE;
46 }
47
48 EFI_STATUS
49 Tcp4IoCreateSocket (
50 IN EFI_HANDLE Image,
51 IN EFI_HANDLE Controller,
52 IN TCP4_IO_CONFIG_DATA *ConfigData,
53 IN TCP4_IO *Tcp4Io
54 )
55 /*++
56
57 Routine Description:
58
59 Create a TCP socket with the specified configuration data.
60
61 Arguments:
62
63 Image - The handle of the driver image.
64 Controller - The handle of the controller.
65 ConfigData - The Tcp4 configuration data.
66 Tcp4Io - The Tcp4Io.
67
68 Returns:
69
70 EFI_SUCCESS - The TCP socket is created and configured.
71 other - Failed to create the TCP socket or configure it.
72
73 --*/
74 {
75 EFI_STATUS Status;
76 EFI_TCP4_PROTOCOL *Tcp4;
77 EFI_TCP4_CONFIG_DATA Tcp4ConfigData;
78 EFI_TCP4_OPTION ControlOption;
79 EFI_TCP4_ACCESS_POINT *AccessPoint;
80
81 Tcp4Io->Handle = NULL;
82 Tcp4Io->ConnToken.CompletionToken.Event = NULL;
83 Tcp4Io->TxToken.CompletionToken.Event = NULL;
84 Tcp4Io->RxToken.CompletionToken.Event = NULL;
85 Tcp4Io->CloseToken.CompletionToken.Event = NULL;
86 Tcp4 = NULL;
87
88 //
89 // Create the TCP4 child instance and get the TCP4 protocol.
90 //
91 Status = NetLibCreateServiceChild (
92 Controller,
93 Image,
94 &gEfiTcp4ServiceBindingProtocolGuid,
95 &Tcp4Io->Handle
96 );
97 if (EFI_ERROR (Status)) {
98 return Status;
99 }
100
101 Status = gBS->OpenProtocol (
102 Tcp4Io->Handle,
103 &gEfiTcp4ProtocolGuid,
104 (VOID **)&Tcp4Io->Tcp4,
105 Image,
106 Controller,
107 EFI_OPEN_PROTOCOL_BY_DRIVER
108 );
109 if (EFI_ERROR (Status)) {
110 goto ON_ERROR;
111 }
112
113 Tcp4Io->Image = Image;
114 Tcp4Io->Controller = Controller;
115 Tcp4 = Tcp4Io->Tcp4;
116
117 //
118 // Set the configuration parameters.
119 //
120 ControlOption.ReceiveBufferSize = 0x200000;
121 ControlOption.SendBufferSize = 0x200000;
122 ControlOption.MaxSynBackLog = 0;
123 ControlOption.ConnectionTimeout = 0;
124 ControlOption.DataRetries = 6;
125 ControlOption.FinTimeout = 0;
126 ControlOption.TimeWaitTimeout = 0;
127 ControlOption.KeepAliveProbes = 4;
128 ControlOption.KeepAliveTime = 0;
129 ControlOption.KeepAliveInterval = 0;
130 ControlOption.EnableNagle = FALSE;
131 ControlOption.EnableTimeStamp = FALSE;
132 ControlOption.EnableWindowScaling = TRUE;
133 ControlOption.EnableSelectiveAck = FALSE;
134 ControlOption.EnablePathMtuDiscovery = FALSE;
135
136 Tcp4ConfigData.TypeOfService = 8;
137 Tcp4ConfigData.TimeToLive = 255;
138 Tcp4ConfigData.ControlOption = &ControlOption;
139
140 AccessPoint = &Tcp4ConfigData.AccessPoint;
141
142 AccessPoint->UseDefaultAddress = FALSE;
143 AccessPoint->StationPort = 0;
144 AccessPoint->RemotePort = ConfigData->RemotePort;
145 AccessPoint->ActiveFlag = TRUE;
146
147 CopyMem (&AccessPoint->StationAddress, &ConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));
148 CopyMem (&AccessPoint->SubnetMask, &ConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
149 CopyMem (&AccessPoint->RemoteAddress, &ConfigData->RemoteIp, sizeof (EFI_IPv4_ADDRESS));
150
151 //
152 // Configure the TCP4 protocol.
153 //
154 Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData);
155 if (EFI_ERROR (Status)) {
156 goto ON_ERROR;
157 }
158
159 if (!EFI_IP4_EQUAL (&ConfigData->Gateway, &mZeroIp4Addr)) {
160 //
161 // the gateway is not zero, add the default route by hand
162 //
163 Status = Tcp4->Routes (Tcp4, FALSE, &mZeroIp4Addr, &mZeroIp4Addr, &ConfigData->Gateway);
164 if (EFI_ERROR (Status)) {
165 goto ON_ERROR;
166 }
167 }
168 //
169 // Create events for variuos asynchronous operations.
170 //
171 Status = gBS->CreateEvent (
172 EFI_EVENT_NOTIFY_SIGNAL,
173 TPL_NOTIFY,
174 Tcp4IoCommonNotify,
175 &Tcp4Io->IsConnDone,
176 &Tcp4Io->ConnToken.CompletionToken.Event
177 );
178 if (EFI_ERROR (Status)) {
179 goto ON_ERROR;
180 }
181
182 Status = gBS->CreateEvent (
183 EFI_EVENT_NOTIFY_SIGNAL,
184 TPL_NOTIFY,
185 Tcp4IoCommonNotify,
186 &Tcp4Io->IsTxDone,
187 &Tcp4Io->TxToken.CompletionToken.Event
188 );
189 if (EFI_ERROR (Status)) {
190 goto ON_ERROR;
191 }
192
193 Status = gBS->CreateEvent (
194 EFI_EVENT_NOTIFY_SIGNAL,
195 TPL_NOTIFY,
196 Tcp4IoCommonNotify,
197 &Tcp4Io->IsRxDone,
198 &Tcp4Io->RxToken.CompletionToken.Event
199 );
200 if (EFI_ERROR (Status)) {
201 goto ON_ERROR;
202 }
203
204 Status = gBS->CreateEvent (
205 EFI_EVENT_NOTIFY_SIGNAL,
206 TPL_NOTIFY,
207 Tcp4IoCommonNotify,
208 &Tcp4Io->IsCloseDone,
209 &Tcp4Io->CloseToken.CompletionToken.Event
210 );
211 if (EFI_ERROR (Status)) {
212 goto ON_ERROR;
213 }
214
215 Tcp4Io->IsTxDone = FALSE;
216 Tcp4Io->IsRxDone = FALSE;
217
218 return EFI_SUCCESS;
219
220 ON_ERROR:
221
222 if (Tcp4Io->RxToken.CompletionToken.Event != NULL) {
223 gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);
224 }
225
226 if (Tcp4Io->TxToken.CompletionToken.Event != NULL) {
227 gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);
228 }
229
230 if (Tcp4Io->ConnToken.CompletionToken.Event != NULL) {
231 gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);
232 }
233
234 if (Tcp4 != NULL) {
235 Tcp4->Configure (Tcp4, NULL);
236
237 gBS->CloseProtocol (
238 Tcp4Io->Handle,
239 &gEfiTcp4ProtocolGuid,
240 Image,
241 Controller
242 );
243 }
244
245 NetLibDestroyServiceChild (
246 Controller,
247 Image,
248 &gEfiTcp4ServiceBindingProtocolGuid,
249 Tcp4Io->Handle
250 );
251
252 return Status;
253 }
254
255 VOID
256 Tcp4IoDestroySocket (
257 IN TCP4_IO *Tcp4Io
258 )
259 /*++
260
261 Routine Description:
262
263 Destroy the socket.
264
265 Arguments:
266
267 Tcp4Io - The Tcp4Io which wraps the socket to be destroyeds.
268
269 Returns:
270
271 None.
272
273 --*/
274 {
275 EFI_TCP4_PROTOCOL *Tcp4;
276
277 Tcp4 = Tcp4Io->Tcp4;
278
279 Tcp4->Configure (Tcp4, NULL);
280
281 gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);
282 gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);
283 gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);
284
285 gBS->CloseProtocol (
286 Tcp4Io->Handle,
287 &gEfiTcp4ProtocolGuid,
288 Tcp4Io->Image,
289 Tcp4Io->Controller
290 );
291
292 NetLibDestroyServiceChild (
293 Tcp4Io->Controller,
294 Tcp4Io->Image,
295 &gEfiTcp4ServiceBindingProtocolGuid,
296 Tcp4Io->Handle
297 );
298 }
299
300 EFI_STATUS
301 Tcp4IoConnect (
302 IN TCP4_IO *Tcp4Io,
303 IN EFI_EVENT Timeout
304 )
305 /*++
306
307 Routine Description:
308
309 Connect to the other endpoint of the TCP socket.
310
311 Arguments:
312
313 Tcp4Io - The Tcp4Io wrapping the TCP socket.
314 Timeout - The time to wait for connection done.
315
316 Returns:
317
318 None.
319
320 --*/
321 {
322 EFI_TCP4_PROTOCOL *Tcp4;
323 EFI_STATUS Status;
324
325 Tcp4Io->IsConnDone = FALSE;
326 Tcp4 = Tcp4Io->Tcp4;
327 Status = Tcp4->Connect (Tcp4, &Tcp4Io->ConnToken);
328 if (EFI_ERROR (Status)) {
329 return Status;
330 }
331
332 while (!Tcp4Io->IsConnDone && EFI_ERROR (gBS->CheckEvent (Timeout))) {
333 Tcp4->Poll (Tcp4);
334 }
335
336 if (!Tcp4Io->IsConnDone) {
337 Status = EFI_TIMEOUT;
338 } else {
339 Status = Tcp4Io->ConnToken.CompletionToken.Status;
340 }
341
342 return Status;
343 }
344
345 VOID
346 Tcp4IoReset (
347 IN TCP4_IO *Tcp4Io
348 )
349 /*++
350
351 Routine Description:
352
353 Reset the socket.
354
355 Arguments:
356
357 Tcp4Io - The Tcp4Io wrapping the TCP socket.
358
359 Returns:
360
361 None.
362
363 --*/
364 {
365 EFI_STATUS Status;
366 EFI_TCP4_PROTOCOL *Tcp4;
367
368 Tcp4Io->CloseToken.AbortOnClose = TRUE;
369 Tcp4Io->IsCloseDone = FALSE;
370
371 Tcp4 = Tcp4Io->Tcp4;
372 Status = Tcp4->Close (Tcp4, &Tcp4Io->CloseToken);
373 if (EFI_ERROR (Status)) {
374 return ;
375 }
376
377 while (!Tcp4Io->IsCloseDone) {
378 Tcp4->Poll (Tcp4);
379 }
380 }
381
382 EFI_STATUS
383 Tcp4IoTransmit (
384 IN TCP4_IO *Tcp4Io,
385 IN NET_BUF *Packet
386 )
387 /*++
388
389 Routine Description:
390
391 Transmit the Packet to the other endpoint of the socket.
392
393 Arguments:
394
395 Tcp4Io - The Tcp4Io wrapping the TCP socket.
396 Packet - The packet to transmit
397
398 Returns:
399
400 EFI_SUCCESS - The packet is trasmitted.
401 EFI_OUT_OF_RESOURCES - Failed to allocate memory.
402
403 --*/
404 {
405 EFI_TCP4_TRANSMIT_DATA *TxData;
406 EFI_TCP4_PROTOCOL *Tcp4;
407 EFI_STATUS Status;
408
409 TxData = AllocatePool (sizeof (EFI_TCP4_TRANSMIT_DATA) + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA));
410 if (TxData == NULL) {
411 return EFI_OUT_OF_RESOURCES;
412 }
413
414 TxData->Push = TRUE;
415 TxData->Urgent = FALSE;
416 TxData->DataLength = Packet->TotalSize;
417
418 //
419 // Build the fragment table.
420 //
421 TxData->FragmentCount = Packet->BlockOpNum;
422 NetbufBuildExt (Packet, (NET_FRAGMENT *) &TxData->FragmentTable[0], &TxData->FragmentCount);
423
424 Tcp4Io->TxToken.Packet.TxData = TxData;
425
426 //
427 // Trasnmit the packet.
428 //
429 Tcp4 = Tcp4Io->Tcp4;
430 Status = Tcp4->Transmit (Tcp4, &Tcp4Io->TxToken);
431 if (EFI_ERROR (Status)) {
432 goto ON_EXIT;
433 }
434
435 while (!Tcp4Io->IsTxDone) {
436 Tcp4->Poll (Tcp4);
437 }
438
439 Tcp4Io->IsTxDone = FALSE;
440
441 Status = Tcp4Io->TxToken.CompletionToken.Status;
442
443 ON_EXIT:
444
445 gBS->FreePool (TxData);
446
447 return Status;
448 }
449
450 EFI_STATUS
451 Tcp4IoReceive (
452 IN TCP4_IO *Tcp4Io,
453 IN NET_BUF *Packet,
454 IN BOOLEAN AsyncMode,
455 IN EFI_EVENT Timeout
456 )
457 /*++
458
459 Routine Description:
460
461 Receive data from the socket.
462
463 Arguments:
464
465 Tcp4Io - The Tcp4Io which wraps the socket to be destroyeds.
466 Packet - The buffer to hold the data copy from the soket rx buffer.
467 AsyncMode - Is this receive asyncronous or not.
468 Timeout - The time to wait for receiving the amount of data the Packet
469 can hold.
470
471 Returns:
472
473 EFI_SUCCESS - The required amount of data is received from the socket.
474 EFI_OUT_OF_RESOURCES - Failed to allocate momery.
475 EFI_TIMEOUT - Failed to receive the required amount of data in the
476 specified time period.
477
478 --*/
479 {
480 EFI_TCP4_PROTOCOL *Tcp4;
481 EFI_TCP4_RECEIVE_DATA RxData;
482 EFI_STATUS Status;
483 NET_FRAGMENT *Fragment;
484 UINT32 FragmentCount;
485 UINT32 CurrentFragment;
486
487 FragmentCount = Packet->BlockOpNum;
488 Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));
489 if (Fragment == NULL) {
490 return EFI_OUT_OF_RESOURCES;
491 }
492 //
493 // Build the fragment table.
494 //
495 NetbufBuildExt (Packet, Fragment, &FragmentCount);
496
497 RxData.FragmentCount = 1;
498 Tcp4Io->RxToken.Packet.RxData = &RxData;
499 CurrentFragment = 0;
500 Tcp4 = Tcp4Io->Tcp4;
501 Status = EFI_SUCCESS;
502
503 while (CurrentFragment < FragmentCount) {
504 RxData.DataLength = Fragment[CurrentFragment].Len;
505 RxData.FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len;
506 RxData.FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk;
507
508 Status = Tcp4->Receive (Tcp4, &Tcp4Io->RxToken);
509 if (EFI_ERROR (Status)) {
510 goto ON_EXIT;
511 }
512
513 while (!Tcp4Io->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
514 //
515 // Poll until some data is received or something error happens.
516 //
517 Tcp4->Poll (Tcp4);
518 }
519
520 if (!Tcp4Io->IsRxDone) {
521 //
522 // Timeout occurs, cancel the receive request.
523 //
524 Tcp4->Cancel (Tcp4, &Tcp4Io->RxToken.CompletionToken);
525
526 Status = EFI_TIMEOUT;
527 goto ON_EXIT;
528 } else {
529 Tcp4Io->IsRxDone = FALSE;
530 }
531
532 if (EFI_ERROR (Tcp4Io->RxToken.CompletionToken.Status)) {
533 Status = Tcp4Io->RxToken.CompletionToken.Status;
534 goto ON_EXIT;
535 }
536
537 Fragment[CurrentFragment].Len -= RxData.FragmentTable[0].FragmentLength;
538 if (Fragment[CurrentFragment].Len == 0) {
539 CurrentFragment++;
540 } else {
541 Fragment[CurrentFragment].Bulk += RxData.FragmentTable[0].FragmentLength;
542 }
543 }
544
545 ON_EXIT:
546
547 gBS->FreePool (Fragment);
548
549 return Status;
550 }