]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.c
MdeModulePkg: Delete useless case code
[mirror_edk2.git] / MdeModulePkg / Library / DxeTcpIoLib / DxeTcpIoLib.c
CommitLineData
4bad9ada 1/** @file\r
2 This library is used to share code between UEFI network stack modules.\r
3 It provides the helper routines to access TCP service.\r
4\r
8322eb77 5Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
4bad9ada 6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at<BR>\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include <Uefi.h>\r
17\r
18#include <Library/TcpIoLib.h>\r
19#include <Library/BaseLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/UefiBootServicesTableLib.h>\r
22#include <Library/MemoryAllocationLib.h>\r
23#include <Library/BaseMemoryLib.h>\r
24\r
4b738c76 25/**\r
4bad9ada 26 The common notify function associated with various TcpIo events. \r
4b738c76
HT
27\r
28 @param[in] Event The event signaled.\r
29 @param[in] Context The context.\r
30\r
31**/\r
32VOID\r
33EFIAPI\r
4bad9ada 34TcpIoCommonNotify (\r
4b738c76
HT
35 IN EFI_EVENT Event,\r
36 IN VOID *Context\r
37 )\r
4bad9ada 38{\r
39 if ((Event == NULL) || (Context == NULL)) {\r
40 return ;\r
41 }\r
42\r
4b738c76 43 *((BOOLEAN *) Context) = TRUE;\r
4bad9ada 44}\r
45\r
4b738c76 46/**\r
4bad9ada 47 The internal function for delay configuring TCP6 when IP6 driver is still in DAD.\r
4b738c76
HT
48\r
49 @param[in] Tcp6 The EFI_TCP6_PROTOCOL protocol instance.\r
50 @param[in] Tcp6ConfigData The Tcp6 configuration data.\r
51\r
52 @retval EFI_SUCCESS The operational settings successfully\r
53 completed.\r
4bad9ada 54 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
55 @retval Others Failed to finish the operation.\r
56\r
4b738c76
HT
57**/\r
58EFI_STATUS\r
4bad9ada 59TcpIoGetMapping (\r
4b738c76
HT
60 IN EFI_TCP6_PROTOCOL *Tcp6,\r
61 IN EFI_TCP6_CONFIG_DATA *Tcp6ConfigData\r
62 )\r
63{\r
64 EFI_STATUS Status;\r
65 EFI_EVENT Event;\r
4bad9ada 66\r
67 if ((Tcp6 == NULL) || (Tcp6ConfigData == NULL)) {\r
68 return EFI_INVALID_PARAMETER;\r
69 }\r
70\r
4b738c76
HT
71 Event = NULL;\r
72 Status = gBS->CreateEvent (\r
73 EVT_TIMER,\r
74 TPL_CALLBACK,\r
75 NULL,\r
76 NULL,\r
77 &Event\r
78 );\r
79 if (EFI_ERROR (Status)) {\r
80 goto ON_EXIT;\r
81 }\r
82\r
83 Status = gBS->SetTimer (\r
84 Event,\r
85 TimerRelative,\r
4bad9ada 86 TCP_GET_MAPPING_TIMEOUT\r
4b738c76
HT
87 );\r
88\r
89 if (EFI_ERROR (Status)) {\r
90 goto ON_EXIT;\r
91 }\r
92\r
93 while (EFI_ERROR (gBS->CheckEvent (Event))) {\r
94\r
95 Tcp6->Poll (Tcp6);\r
96\r
97 Status = Tcp6->Configure (Tcp6, Tcp6ConfigData);\r
98\r
99 if (!EFI_ERROR (Status)) {\r
100 break;\r
101 }\r
102 }\r
103\r
104ON_EXIT:\r
105\r
106 if (Event != NULL) {\r
107 gBS->CloseEvent (Event);\r
108 }\r
109\r
110 return Status;\r
4bad9ada 111}\r
112\r
113/**\r
114 Create a TCP socket with the specified configuration data. \r
115\r
116 @param[in] Image The handle of the driver image.\r
117 @param[in] Controller The handle of the controller.\r
118 @param[in] TcpVersion The version of Tcp, TCP_VERSION_4 or TCP_VERSION_6.\r
119 @param[in] ConfigData The Tcp configuration data.\r
120 @param[out] TcpIo The TcpIo.\r
121 \r
122 @retval EFI_SUCCESS The TCP socket is created and configured.\r
123 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
4b738c76 124 @retval EFI_UNSUPPORTED One or more of the control options are not\r
4bad9ada 125 supported in the implementation.\r
8322eb77 126 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
4bad9ada 127 @retval Others Failed to create the TCP socket or configure it.\r
128\r
129**/\r
130EFI_STATUS\r
131EFIAPI\r
132TcpIoCreateSocket (\r
133 IN EFI_HANDLE Image,\r
134 IN EFI_HANDLE Controller,\r
135 IN UINT8 TcpVersion,\r
136 IN TCP_IO_CONFIG_DATA *ConfigData,\r
137 OUT TCP_IO *TcpIo\r
138 )\r
139{\r
140 EFI_STATUS Status;\r
141 EFI_EVENT Event;\r
142 EFI_GUID *ServiceBindingGuid;\r
143 EFI_GUID *ProtocolGuid;\r
144 VOID **Interface;\r
145 EFI_TCP4_OPTION ControlOption;\r
146 EFI_TCP4_CONFIG_DATA Tcp4ConfigData;\r
147 EFI_TCP4_ACCESS_POINT *AccessPoint4;\r
148 EFI_TCP4_PROTOCOL *Tcp4;\r
149 EFI_TCP6_CONFIG_DATA Tcp6ConfigData;\r
150 EFI_TCP6_ACCESS_POINT *AccessPoint6;\r
151 EFI_TCP6_PROTOCOL *Tcp6;\r
8322eb77 152 EFI_TCP4_RECEIVE_DATA *RxData;\r
4bad9ada 153\r
154 if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (TcpIo == NULL)) {\r
155 return EFI_INVALID_PARAMETER;\r
156 }\r
157\r
158 Tcp4 = NULL;\r
159 Tcp6 = NULL;\r
160\r
161 ZeroMem (TcpIo, sizeof (TCP_IO));\r
162\r
163 if (TcpVersion == TCP_VERSION_4) {\r
164 ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
165 ProtocolGuid = &gEfiTcp4ProtocolGuid;\r
166 Interface = (VOID **) (&TcpIo->Tcp.Tcp4);\r
167 } else if (TcpVersion == TCP_VERSION_6) {\r
168 ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
169 ProtocolGuid = &gEfiTcp6ProtocolGuid;\r
170 Interface = (VOID **) (&TcpIo->Tcp.Tcp6);\r
171 } else {\r
172 return EFI_UNSUPPORTED;\r
173 }\r
174\r
175 TcpIo->TcpVersion = TcpVersion;\r
176\r
177 //\r
178 // Create the TCP child instance and get the TCP protocol.\r
179 // \r
4b738c76
HT
180 Status = NetLibCreateServiceChild (\r
181 Controller,\r
182 Image,\r
4bad9ada 183 ServiceBindingGuid,\r
184 &TcpIo->Handle\r
4b738c76
HT
185 );\r
186 if (EFI_ERROR (Status)) {\r
187 return Status;\r
188 }\r
189\r
190 Status = gBS->OpenProtocol (\r
4bad9ada 191 TcpIo->Handle,\r
192 ProtocolGuid,\r
193 Interface,\r
4b738c76
HT
194 Image,\r
195 Controller,\r
196 EFI_OPEN_PROTOCOL_BY_DRIVER\r
197 );\r
4bad9ada 198 if (EFI_ERROR (Status) || (*Interface == NULL)) {\r
4b738c76 199 goto ON_ERROR;\r
4bad9ada 200 }\r
201\r
202 if (TcpVersion == TCP_VERSION_4) {\r
203 Tcp4 = TcpIo->Tcp.Tcp4;\r
204 } else {\r
205 Tcp6 = TcpIo->Tcp.Tcp6;\r
206 }\r
4b738c76 207\r
4bad9ada 208 TcpIo->Image = Image;\r
209 TcpIo->Controller = Controller;\r
4b738c76
HT
210\r
211 //\r
212 // Set the configuration parameters.\r
213 //\r
214 ControlOption.ReceiveBufferSize = 0x200000;\r
215 ControlOption.SendBufferSize = 0x200000;\r
216 ControlOption.MaxSynBackLog = 0;\r
217 ControlOption.ConnectionTimeout = 0;\r
218 ControlOption.DataRetries = 6;\r
219 ControlOption.FinTimeout = 0;\r
220 ControlOption.TimeWaitTimeout = 0;\r
221 ControlOption.KeepAliveProbes = 4;\r
222 ControlOption.KeepAliveTime = 0;\r
223 ControlOption.KeepAliveInterval = 0;\r
224 ControlOption.EnableNagle = FALSE;\r
225 ControlOption.EnableTimeStamp = FALSE;\r
226 ControlOption.EnableWindowScaling = TRUE;\r
227 ControlOption.EnableSelectiveAck = FALSE;\r
228 ControlOption.EnablePathMtuDiscovery = FALSE;\r
4bad9ada 229\r
230 if (TcpVersion == TCP_VERSION_4) {\r
231 Tcp4ConfigData.TypeOfService = 8;\r
232 Tcp4ConfigData.TimeToLive = 255;\r
233 Tcp4ConfigData.ControlOption = &ControlOption;\r
234\r
235 AccessPoint4 = &Tcp4ConfigData.AccessPoint;\r
236\r
237 ZeroMem (AccessPoint4, sizeof (EFI_TCP4_ACCESS_POINT));\r
238 AccessPoint4->StationPort = ConfigData->Tcp4IoConfigData.StationPort;\r
239 AccessPoint4->RemotePort = ConfigData->Tcp4IoConfigData.RemotePort;\r
240 AccessPoint4->ActiveFlag = ConfigData->Tcp4IoConfigData.ActiveFlag;\r
241\r
242 CopyMem (\r
243 &AccessPoint4->StationAddress,\r
244 &ConfigData->Tcp4IoConfigData.LocalIp,\r
245 sizeof (EFI_IPv4_ADDRESS)\r
246 );\r
247 CopyMem (\r
248 &AccessPoint4->SubnetMask,\r
249 &ConfigData->Tcp4IoConfigData.SubnetMask,\r
250 sizeof (EFI_IPv4_ADDRESS)\r
251 );\r
252 CopyMem (\r
253 &AccessPoint4->RemoteAddress,\r
254 &ConfigData->Tcp4IoConfigData.RemoteIp,\r
255 sizeof (EFI_IPv4_ADDRESS)\r
256 );\r
257\r
258 ASSERT (Tcp4 != NULL);\r
259\r
260 //\r
261 // Configure the TCP4 protocol.\r
262 //\r
263 Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData);\r
264 if (EFI_ERROR (Status)) {\r
265 goto ON_ERROR;\r
266 }\r
267\r
268 if (!EFI_IP4_EQUAL (&ConfigData->Tcp4IoConfigData.Gateway, &mZeroIp4Addr)) {\r
269 //\r
270 // The gateway is not zero. Add the default route manually.\r
271 //\r
272 Status = Tcp4->Routes (\r
273 Tcp4,\r
274 FALSE,\r
275 &mZeroIp4Addr,\r
276 &mZeroIp4Addr,\r
277 &ConfigData->Tcp4IoConfigData.Gateway\r
278 );\r
279 if (EFI_ERROR (Status)) {\r
280 goto ON_ERROR;\r
281 }\r
282 }\r
283 } else {\r
284 Tcp6ConfigData.TrafficClass = 0;\r
285 Tcp6ConfigData.HopLimit = 255;\r
286 Tcp6ConfigData.ControlOption = (EFI_TCP6_OPTION *) &ControlOption;\r
287\r
288 AccessPoint6 = &Tcp6ConfigData.AccessPoint;\r
289\r
290 ZeroMem (AccessPoint6, sizeof (EFI_TCP6_ACCESS_POINT));\r
291 AccessPoint6->StationPort = ConfigData->Tcp6IoConfigData.StationPort;\r
292 AccessPoint6->RemotePort = ConfigData->Tcp6IoConfigData.RemotePort;\r
293 AccessPoint6->ActiveFlag = ConfigData->Tcp6IoConfigData.ActiveFlag;\r
294\r
295 IP6_COPY_ADDRESS (&AccessPoint6->RemoteAddress, &ConfigData->Tcp6IoConfigData.RemoteIp);\r
296\r
297\r
298 ASSERT (Tcp6 != NULL);\r
299 //\r
300 // Configure the TCP6 protocol.\r
301 //\r
302 Status = Tcp6->Configure (Tcp6, &Tcp6ConfigData);\r
303 if (Status == EFI_NO_MAPPING) {\r
304 Status = TcpIoGetMapping (Tcp6, &Tcp6ConfigData);\r
305 }\r
306\r
307 if (EFI_ERROR (Status)) {\r
308 goto ON_ERROR;\r
309 }\r
310 }\r
311\r
4b738c76
HT
312 //\r
313 // Create events for variuos asynchronous operations.\r
4bad9ada 314 //\r
315 Status = gBS->CreateEvent (\r
4b738c76
HT
316 EVT_NOTIFY_SIGNAL,\r
317 TPL_NOTIFY,\r
4bad9ada 318 TcpIoCommonNotify,\r
319 &TcpIo->IsConnDone,\r
320 &Event\r
4b738c76
HT
321 );\r
322 if (EFI_ERROR (Status)) {\r
323 goto ON_ERROR;\r
4bad9ada 324 }\r
325\r
326 TcpIo->ConnToken.Tcp4Token.CompletionToken.Event = Event;\r
327\r
4b738c76
HT
328 Status = gBS->CreateEvent (\r
329 EVT_NOTIFY_SIGNAL,\r
330 TPL_NOTIFY,\r
4bad9ada 331 TcpIoCommonNotify,\r
332 &TcpIo->IsListenDone,\r
333 &Event\r
4b738c76
HT
334 );\r
335 if (EFI_ERROR (Status)) {\r
336 goto ON_ERROR;\r
4bad9ada 337 }\r
338\r
339 TcpIo->ListenToken.Tcp4Token.CompletionToken.Event = Event;\r
340\r
4b738c76
HT
341 Status = gBS->CreateEvent (\r
342 EVT_NOTIFY_SIGNAL,\r
343 TPL_NOTIFY,\r
4bad9ada 344 TcpIoCommonNotify,\r
345 &TcpIo->IsTxDone,\r
346 &Event\r
4b738c76
HT
347 );\r
348 if (EFI_ERROR (Status)) {\r
349 goto ON_ERROR;\r
350 }\r
4bad9ada 351\r
352 TcpIo->TxToken.Tcp4Token.CompletionToken.Event = Event;\r
353\r
354\r
4b738c76
HT
355 Status = gBS->CreateEvent (\r
356 EVT_NOTIFY_SIGNAL,\r
357 TPL_NOTIFY,\r
4bad9ada 358 TcpIoCommonNotify,\r
359 &TcpIo->IsRxDone,\r
360 &Event\r
4b738c76
HT
361 );\r
362 if (EFI_ERROR (Status)) {\r
363 goto ON_ERROR;\r
364 }\r
4bad9ada 365\r
366 TcpIo->RxToken.Tcp4Token.CompletionToken.Event = Event;\r
367\r
8322eb77 368 RxData = (EFI_TCP4_RECEIVE_DATA *) AllocateZeroPool (sizeof (EFI_TCP4_RECEIVE_DATA));\r
369 if (RxData == NULL) {\r
370 Status = EFI_OUT_OF_RESOURCES;\r
371 goto ON_ERROR;\r
372 }\r
373\r
374 TcpIo->RxToken.Tcp4Token.Packet.RxData = RxData;\r
375\r
4b738c76
HT
376 Status = gBS->CreateEvent (\r
377 EVT_NOTIFY_SIGNAL,\r
378 TPL_NOTIFY,\r
4bad9ada 379 TcpIoCommonNotify,\r
380 &TcpIo->IsCloseDone,\r
381 &Event\r
4b738c76
HT
382 );\r
383 if (EFI_ERROR (Status)) {\r
384 goto ON_ERROR;\r
385 }\r
4bad9ada 386\r
387 TcpIo->CloseToken.Tcp4Token.CompletionToken.Event = Event;\r
388\r
389\r
390 return EFI_SUCCESS;\r
4b738c76
HT
391\r
392ON_ERROR:\r
4bad9ada 393\r
394 TcpIoDestroySocket (TcpIo);\r
4b738c76 395\r
4bad9ada 396 return Status;\r
397}\r
398 \r
399/**\r
400 Destroy the socket. \r
401\r
402 @param[in] TcpIo The TcpIo which wraps the socket to be destroyed.\r
403\r
404**/\r
405VOID\r
406EFIAPI\r
407TcpIoDestroySocket (\r
408 IN TCP_IO *TcpIo\r
409 )\r
410{\r
411 EFI_EVENT Event;\r
412 EFI_TCP4_PROTOCOL *Tcp4;\r
413 EFI_TCP6_PROTOCOL *Tcp6;\r
414 UINT8 TcpVersion;\r
415 EFI_GUID *ServiceBindingGuid;\r
416 EFI_GUID *ProtocolGuid;\r
417 EFI_HANDLE ChildHandle;\r
418\r
419 if (TcpIo == NULL) {\r
420 return ;\r
421 }\r
422\r
423 TcpVersion = TcpIo->TcpVersion;\r
424\r
425 if ((TcpVersion != TCP_VERSION_4) && (TcpVersion != TCP_VERSION_6)) {\r
426 return ;\r
427 }\r
428\r
429 Event = TcpIo->ConnToken.Tcp4Token.CompletionToken.Event;\r
430\r
431 if (Event != NULL) {\r
432 gBS->CloseEvent (Event);\r
433 }\r
434\r
435 Event = TcpIo->ListenToken.Tcp4Token.CompletionToken.Event;\r
436\r
437 if (Event != NULL) {\r
438 gBS->CloseEvent (Event);\r
439 }\r
440\r
441 Event = TcpIo->TxToken.Tcp4Token.CompletionToken.Event;\r
442\r
443 if (Event != NULL) {\r
444 gBS->CloseEvent (Event);\r
445 }\r
446\r
447 Event = TcpIo->RxToken.Tcp4Token.CompletionToken.Event;\r
448\r
449 if (Event != NULL) {\r
450 gBS->CloseEvent (Event);\r
451 }\r
452\r
453 Event = TcpIo->CloseToken.Tcp4Token.CompletionToken.Event;\r
454\r
455 if (Event != NULL) {\r
456 gBS->CloseEvent (Event);\r
457 }\r
458\r
8322eb77 459 if (TcpIo->RxToken.Tcp4Token.Packet.RxData != NULL) {\r
460 FreePool (TcpIo->RxToken.Tcp4Token.Packet.RxData);\r
461 }\r
462\r
4bad9ada 463 Tcp4 = NULL;\r
464 Tcp6 = NULL;\r
465\r
466\r
467 if (TcpVersion == TCP_VERSION_4) {\r
468 ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
469 ProtocolGuid = &gEfiTcp4ProtocolGuid;\r
470 Tcp4 = TcpIo->Tcp.Tcp4;\r
471 if (Tcp4 != NULL) {\r
472 Tcp4->Configure (Tcp4, NULL);\r
473 }\r
474 } else {\r
475 ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
476 ProtocolGuid = &gEfiTcp6ProtocolGuid;\r
477 Tcp6 = TcpIo->Tcp.Tcp6;\r
478 if (Tcp6 != NULL) {\r
479 Tcp6->Configure (Tcp6, NULL);\r
480 }\r
481 }\r
482\r
483 if ((Tcp4 != NULL) || (Tcp6 != NULL)) {\r
484\r
4b738c76 485 gBS->CloseProtocol (\r
4bad9ada 486 TcpIo->Handle,\r
487 ProtocolGuid,\r
488 TcpIo->Image,\r
489 TcpIo->Controller\r
490 );\r
491 }\r
492\r
493 ChildHandle = NULL;\r
494\r
495 if (TcpIo->IsListenDone) {\r
496 if (TcpVersion == TCP_VERSION_4) {\r
497 Tcp4 = TcpIo->NewTcp.Tcp4;\r
498 if (Tcp4 != NULL) {\r
499 Tcp4->Configure (Tcp4, NULL);\r
500 ChildHandle = TcpIo->ListenToken.Tcp4Token.NewChildHandle;\r
501 }\r
502 } else {\r
503 Tcp6 = TcpIo->NewTcp.Tcp6;\r
504 if (Tcp6 != NULL) {\r
505 Tcp6->Configure (Tcp6, NULL);\r
506 ChildHandle = TcpIo->ListenToken.Tcp6Token.NewChildHandle;\r
507 }\r
508 }\r
509\r
510 if (ChildHandle != NULL) {\r
511\r
512 gBS->CloseProtocol (\r
513 ChildHandle,\r
514 ProtocolGuid,\r
515 TcpIo->Image,\r
516 TcpIo->Controller\r
517 );\r
518 }\r
519 }\r
520\r
4b738c76 521 NetLibDestroyServiceChild (\r
4bad9ada 522 TcpIo->Controller,\r
523 TcpIo->Image,\r
524 ServiceBindingGuid,\r
525 TcpIo->Handle\r
526 );\r
527}\r
528\r
529/**\r
530 Connect to the other endpoint of the TCP socket.\r
531\r
532 @param[in, out] TcpIo The TcpIo wrapping the TCP socket.\r
533 @param[in] Timeout The time to wait for connection done.\r
534 \r
535 @retval EFI_SUCCESS Connect to the other endpoint of the TCP socket\r
536 successfully.\r
537 @retval EFI_TIMEOUT Failed to connect to the other endpoint of the\r
538 TCP socket in the specified time period.\r
539 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
540 @retval EFI_UNSUPPORTED One or more of the control options are not\r
541 supported in the implementation.\r
542 @retval Others Other errors as indicated.\r
543\r
544**/\r
545EFI_STATUS\r
546EFIAPI\r
547TcpIoConnect (\r
548 IN OUT TCP_IO *TcpIo,\r
549 IN EFI_EVENT Timeout\r
550 )\r
551{\r
552 EFI_TCP4_PROTOCOL *Tcp4;\r
553 EFI_TCP6_PROTOCOL *Tcp6;\r
554 EFI_STATUS Status;\r
555\r
556 if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)) {\r
557 return EFI_INVALID_PARAMETER;\r
558 }\r
559\r
560 TcpIo->IsConnDone = FALSE;\r
561\r
562 Tcp4 = NULL;\r
563 Tcp6 = NULL;\r
564\r
565 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
566 Tcp4 = TcpIo->Tcp.Tcp4;\r
567 Status = Tcp4->Connect (Tcp4, &TcpIo->ConnToken.Tcp4Token);\r
568 } else if (TcpIo->TcpVersion == TCP_VERSION_6) {\r
569 Tcp6 = TcpIo->Tcp.Tcp6;\r
570 Status = Tcp6->Connect (Tcp6, &TcpIo->ConnToken.Tcp6Token);\r
571 } else {\r
572 return EFI_UNSUPPORTED;\r
573 }\r
574\r
4b738c76
HT
575 if (EFI_ERROR (Status)) {\r
576 return Status;\r
577 }\r
578\r
4bad9ada 579 while (!TcpIo->IsConnDone && EFI_ERROR (gBS->CheckEvent (Timeout))) {\r
580 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
581 Tcp4->Poll (Tcp4);\r
582 } else {\r
583 Tcp6->Poll (Tcp6);\r
584 }\r
4b738c76
HT
585 }\r
586\r
4bad9ada 587 if (!TcpIo->IsConnDone) {\r
4b738c76 588 Status = EFI_TIMEOUT;\r
4bad9ada 589 } else {\r
590 Status = TcpIo->ConnToken.Tcp4Token.CompletionToken.Status;\r
591 }\r
4b738c76 592\r
4bad9ada 593 return Status;\r
594}\r
595\r
596/**\r
597 Accept the incomding request from the other endpoint of the TCP socket.\r
598\r
599 @param[in, out] TcpIo The TcpIo wrapping the TCP socket.\r
600 @param[in] Timeout The time to wait for connection done.\r
601\r
602 \r
603 @retval EFI_SUCCESS Connect to the other endpoint of the TCP socket\r
604 successfully.\r
605 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
606 @retval EFI_UNSUPPORTED One or more of the control options are not\r
607 supported in the implementation.\r
608\r
609 @retval EFI_TIMEOUT Failed to connect to the other endpoint of the\r
610 TCP socket in the specified time period. \r
611 @retval Others Other errors as indicated.\r
612\r
613**/\r
614EFI_STATUS\r
615EFIAPI\r
616TcpIoAccept (\r
617 IN OUT TCP_IO *TcpIo,\r
618 IN EFI_EVENT Timeout\r
619 )\r
620{\r
621 EFI_STATUS Status;\r
622 EFI_GUID *ProtocolGuid;\r
623 EFI_TCP4_PROTOCOL *Tcp4;\r
624 EFI_TCP6_PROTOCOL *Tcp6;\r
625\r
626 if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)) {\r
627 return EFI_INVALID_PARAMETER;\r
628 }\r
629\r
630 TcpIo->IsListenDone = FALSE;\r
631\r
632 Tcp4 = NULL;\r
633 Tcp6 = NULL;\r
634\r
635 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
636 Tcp4 = TcpIo->Tcp.Tcp4;\r
637 Status = Tcp4->Accept (Tcp4, &TcpIo->ListenToken.Tcp4Token);\r
638 } else if (TcpIo->TcpVersion == TCP_VERSION_6) {\r
639 Tcp6 = TcpIo->Tcp.Tcp6;\r
640 Status = Tcp6->Accept (Tcp6, &TcpIo->ListenToken.Tcp6Token);\r
641 } else {\r
642 return EFI_UNSUPPORTED;\r
643 }\r
644\r
4b738c76
HT
645 if (EFI_ERROR (Status)) {\r
646 return Status;\r
4bad9ada 647 }\r
648\r
649 while (!TcpIo->IsListenDone && EFI_ERROR (gBS->CheckEvent (Timeout))) {\r
650 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
651 Tcp4->Poll (Tcp4);\r
652 } else {\r
653 Tcp6->Poll (Tcp6);\r
654 }\r
4b738c76 655 }\r
4bad9ada 656\r
657 if (!TcpIo->IsListenDone) {\r
4b738c76 658 Status = EFI_TIMEOUT;\r
4bad9ada 659 } else {\r
660 Status = TcpIo->ListenToken.Tcp4Token.CompletionToken.Status;\r
661 }\r
662\r
4b738c76
HT
663 //\r
664 // The new TCP instance handle created for the established connection is \r
665 // in ListenToken.\r
666 //\r
4bad9ada 667 if (!EFI_ERROR (Status)) {\r
668 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
669 ProtocolGuid = &gEfiTcp4ProtocolGuid;\r
670 } else {\r
671 ProtocolGuid = &gEfiTcp6ProtocolGuid;\r
672 }\r
673 \r
4b738c76 674 Status = gBS->OpenProtocol (\r
4bad9ada 675 TcpIo->ListenToken.Tcp4Token.NewChildHandle,\r
676 ProtocolGuid,\r
677 (VOID **) (&TcpIo->NewTcp.Tcp4),\r
678 TcpIo->Image,\r
679 TcpIo->Controller,\r
4b738c76
HT
680 EFI_OPEN_PROTOCOL_BY_DRIVER\r
681 );\r
682\r
683 }\r
4bad9ada 684\r
685 return Status;\r
686}\r
687\r
688/**\r
689 Reset the socket.\r
690\r
691 @param[in, out] TcpIo The TcpIo wrapping the TCP socket.\r
692\r
693**/\r
694VOID\r
695EFIAPI\r
696TcpIoReset (\r
697 IN OUT TCP_IO *TcpIo\r
698 )\r
699{\r
700 EFI_TCP4_PROTOCOL *Tcp4;\r
701 EFI_TCP6_PROTOCOL *Tcp6;\r
702 EFI_STATUS Status;\r
703\r
704 if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)) {\r
705 return ;\r
706 }\r
707\r
708 TcpIo->IsCloseDone = FALSE;\r
709 Tcp4 = NULL;\r
710 Tcp6 = NULL;\r
711\r
712 if (TcpIo->TcpVersion == TCP_VERSION_4) { \r
713 TcpIo->CloseToken.Tcp4Token.AbortOnClose = TRUE;\r
714 Tcp4 = TcpIo->Tcp.Tcp4;\r
715 Status = Tcp4->Close (Tcp4, &TcpIo->CloseToken.Tcp4Token);\r
716 } else if (TcpIo->TcpVersion == TCP_VERSION_6) {\r
717 TcpIo->CloseToken.Tcp6Token.AbortOnClose = TRUE;\r
718 Tcp6 = TcpIo->Tcp.Tcp6;\r
719 Status = Tcp6->Close (Tcp6, &TcpIo->CloseToken.Tcp6Token);\r
720 } else {\r
721 return ;\r
722 }\r
723\r
4b738c76
HT
724 if (EFI_ERROR (Status)) {\r
725 return ;\r
726 }\r
727\r
4bad9ada 728 while (!TcpIo->IsCloseDone) {\r
729 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
730 Tcp4->Poll (Tcp4);\r
731 } else {\r
732 Tcp6->Poll (Tcp6);\r
733 }\r
734 }\r
735}\r
736\r
737 \r
738/**\r
739 Transmit the Packet to the other endpoint of the socket.\r
740\r
741 @param[in] TcpIo The TcpIo wrapping the TCP socket.\r
742 @param[in] Packet The packet to transmit.\r
743 \r
744 @retval EFI_SUCCESS The packet is trasmitted.\r
745 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
746 @retval EFI_UNSUPPORTED One or more of the control options are not\r
747 supported in the implementation.\r
748 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
749 @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.\r
750 @retval Others Other errors as indicated.\r
751\r
752**/\r
753EFI_STATUS\r
754EFIAPI\r
755TcpIoTransmit (\r
756 IN TCP_IO *TcpIo,\r
757 IN NET_BUF *Packet\r
758 )\r
759{\r
760 EFI_STATUS Status;\r
761 VOID *Data;\r
762 EFI_TCP4_PROTOCOL *Tcp4;\r
763 EFI_TCP6_PROTOCOL *Tcp6;\r
764 UINTN Size;\r
765\r
766 if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)|| (Packet == NULL)) {\r
767 return EFI_INVALID_PARAMETER;\r
768 }\r
769\r
770 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
771\r
772 Size = sizeof (EFI_TCP4_TRANSMIT_DATA) + \r
773 (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA);\r
774 } else if (TcpIo->TcpVersion == TCP_VERSION_6) {\r
775 Size = sizeof (EFI_TCP6_TRANSMIT_DATA) +\r
776 (Packet->BlockOpNum - 1) * sizeof (EFI_TCP6_FRAGMENT_DATA);\r
777 } else {\r
778 return EFI_UNSUPPORTED;\r
779 }\r
780\r
781 Data = AllocatePool (Size);\r
782 if (Data == NULL) {\r
4b738c76 783 return EFI_OUT_OF_RESOURCES;\r
4bad9ada 784 }\r
785\r
786 ((EFI_TCP4_TRANSMIT_DATA *) Data)->Push = TRUE;\r
787 ((EFI_TCP4_TRANSMIT_DATA *) Data)->Urgent = FALSE;\r
788 ((EFI_TCP4_TRANSMIT_DATA *) Data)->DataLength = Packet->TotalSize;\r
789\r
4b738c76
HT
790 //\r
791 // Build the fragment table.\r
792 //\r
4bad9ada 793 ((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount = Packet->BlockOpNum;\r
794\r
795 NetbufBuildExt (\r
796 Packet,\r
797 (NET_FRAGMENT *) &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentTable[0],\r
798 &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount\r
799 );\r
800\r
801 Tcp4 = NULL;\r
802 Tcp6 = NULL;\r
803 Status = EFI_DEVICE_ERROR;\r
804\r
4b738c76
HT
805 //\r
806 // Trasnmit the packet.\r
4bad9ada 807 //\r
808 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
809 TcpIo->TxToken.Tcp4Token.Packet.TxData = (EFI_TCP4_TRANSMIT_DATA *) Data;\r
810 Tcp4 = TcpIo->Tcp.Tcp4;\r
811 if (TcpIo->IsListenDone) {\r
812 Tcp4 = TcpIo->NewTcp.Tcp4;\r
813 }\r
814\r
815 if (Tcp4 == NULL) {\r
816 goto ON_EXIT;\r
817 }\r
818 \r
819 Status = Tcp4->Transmit (Tcp4, &TcpIo->TxToken.Tcp4Token);\r
820 } else {\r
821 TcpIo->TxToken.Tcp6Token.Packet.TxData = (EFI_TCP6_TRANSMIT_DATA *) Data;\r
822 Tcp6 = TcpIo->Tcp.Tcp6;\r
823 if (TcpIo->IsListenDone) {\r
824 Tcp6 = TcpIo->NewTcp.Tcp6;\r
825 }\r
826\r
827 if (Tcp6 == NULL) {\r
828 goto ON_EXIT;\r
829 }\r
830\r
831 Status = Tcp6->Transmit (Tcp6, &TcpIo->TxToken.Tcp6Token);\r
832 }\r
833\r
4b738c76
HT
834 if (EFI_ERROR (Status)) {\r
835 goto ON_EXIT;\r
836 }\r
837\r
4bad9ada 838 while (!TcpIo->IsTxDone) {\r
839 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
840 Tcp4->Poll (Tcp4);\r
841 } else {\r
842 Tcp6->Poll (Tcp6);\r
843 }\r
4b738c76
HT
844 }\r
845\r
4bad9ada 846 TcpIo->IsTxDone = FALSE;\r
847 Status = TcpIo->TxToken.Tcp4Token.CompletionToken.Status;\r
848\r
4b738c76
HT
849ON_EXIT:\r
850\r
4bad9ada 851 FreePool (Data);\r
4b738c76 852\r
4bad9ada 853 return Status;\r
854}\r
855\r
856/**\r
857 Receive data from the socket.\r
858\r
859 @param[in, out] TcpIo The TcpIo which wraps the socket to be destroyed.\r
860 @param[in] Packet The buffer to hold the data copy from the socket rx buffer.\r
861 @param[in] AsyncMode Is this receive asyncronous or not.\r
862 @param[in] Timeout The time to wait for receiving the amount of data the Packet\r
863 can hold.\r
864\r
865 @retval EFI_SUCCESS The required amount of data is received from the socket.\r
866 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
867 @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.\r
868 @retval EFI_OUT_OF_RESOURCES Failed to allocate momery.\r
869 @retval EFI_TIMEOUT Failed to receive the required amount of data in the\r
870 specified time period.\r
871 @retval Others Other errors as indicated.\r
872\r
873**/\r
874EFI_STATUS\r
875EFIAPI\r
876TcpIoReceive (\r
877 IN OUT TCP_IO *TcpIo,\r
878 IN NET_BUF *Packet,\r
879 IN BOOLEAN AsyncMode,\r
880 IN EFI_EVENT Timeout\r
881 )\r
882{\r
883 EFI_TCP4_PROTOCOL *Tcp4;\r
884 EFI_TCP6_PROTOCOL *Tcp6;\r
8322eb77 885 EFI_TCP4_RECEIVE_DATA *RxData;\r
4bad9ada 886 EFI_STATUS Status;\r
887 NET_FRAGMENT *Fragment;\r
888 UINT32 FragmentCount;\r
889 UINT32 CurrentFragment;\r
890\r
891 if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)|| (Packet == NULL)) {\r
892 return EFI_INVALID_PARAMETER;\r
893 }\r
894\r
8322eb77 895 RxData = TcpIo->RxToken.Tcp4Token.Packet.RxData;\r
896 if (RxData == NULL) {\r
897 return EFI_INVALID_PARAMETER;\r
898 }\r
899\r
4bad9ada 900 Tcp4 = NULL;\r
901 Tcp6 = NULL;\r
902\r
903 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
4bad9ada 904 Tcp4 = TcpIo->Tcp.Tcp4;\r
905\r
906 if (TcpIo->IsListenDone) {\r
907 Tcp4 = TcpIo->NewTcp.Tcp4;\r
908 }\r
909\r
910 if (Tcp4 == NULL) {\r
911 return EFI_DEVICE_ERROR;\r
912 }\r
913\r
914 } else if (TcpIo->TcpVersion == TCP_VERSION_6) {\r
4bad9ada 915 Tcp6 = TcpIo->Tcp.Tcp6;\r
916\r
917 if (TcpIo->IsListenDone) {\r
918 Tcp6 = TcpIo->NewTcp.Tcp6;\r
919 }\r
920\r
921 if (Tcp6 == NULL) {\r
922 return EFI_DEVICE_ERROR; \r
923 }\r
924\r
925 } else {\r
926 return EFI_UNSUPPORTED;\r
927 }\r
928\r
4b738c76
HT
929 FragmentCount = Packet->BlockOpNum;\r
930 Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));\r
ec50ecf2
ED
931 if (Fragment == NULL) {\r
932 Status = EFI_OUT_OF_RESOURCES;\r
933 goto ON_EXIT;\r
4b738c76
HT
934 }\r
935 //\r
936 // Build the fragment table.\r
937 //\r
938 NetbufBuildExt (Packet, Fragment, &FragmentCount);\r
4bad9ada 939\r
8322eb77 940 RxData->FragmentCount = 1;\r
4bad9ada 941 CurrentFragment = 0;\r
4b738c76
HT
942 Status = EFI_SUCCESS;\r
943\r
944 while (CurrentFragment < FragmentCount) {\r
8322eb77 945 RxData->DataLength = Fragment[CurrentFragment].Len;\r
946 RxData->FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len;\r
947 RxData->FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk;\r
4bad9ada 948\r
949 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
950 Status = Tcp4->Receive (Tcp4, &TcpIo->RxToken.Tcp4Token);\r
951 } else {\r
952 Status = Tcp6->Receive (Tcp6, &TcpIo->RxToken.Tcp6Token);\r
953 }\r
954 \r
4b738c76
HT
955 if (EFI_ERROR (Status)) {\r
956 goto ON_EXIT;\r
957 }\r
4bad9ada 958 \r
959 while (!TcpIo->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
960 //\r
961 // Poll until some data is received or an error occurs.\r
962 //\r
963 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
964 Tcp4->Poll (Tcp4);\r
965 } else {\r
966 Tcp6->Poll (Tcp6);\r
967 }\r
968 }\r
4b738c76 969\r
4bad9ada 970 if (!TcpIo->IsRxDone) {\r
4b738c76
HT
971 //\r
972 // Timeout occurs, cancel the receive request.\r
973 //\r
4bad9ada 974 if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
975 Tcp4->Cancel (Tcp4, &TcpIo->RxToken.Tcp4Token.CompletionToken);\r
976 } else {\r
977 Tcp6->Cancel (Tcp6, &TcpIo->RxToken.Tcp6Token.CompletionToken);\r
978 }\r
4b738c76
HT
979\r
980 Status = EFI_TIMEOUT;\r
981 goto ON_EXIT;\r
982 } else {\r
4bad9ada 983 TcpIo->IsRxDone = FALSE;\r
984 }\r
985\r
986 Status = TcpIo->RxToken.Tcp4Token.CompletionToken.Status;\r
987\r
988 if (EFI_ERROR (Status)) {\r
4b738c76
HT
989 goto ON_EXIT;\r
990 }\r
991\r
8322eb77 992 Fragment[CurrentFragment].Len -= RxData->FragmentTable[0].FragmentLength;\r
4b738c76
HT
993 if (Fragment[CurrentFragment].Len == 0) {\r
994 CurrentFragment++;\r
995 } else {\r
8322eb77 996 Fragment[CurrentFragment].Bulk += RxData->FragmentTable[0].FragmentLength;\r
4b738c76
HT
997 }\r
998 }\r
999\r
1000ON_EXIT:\r
4bad9ada 1001\r
ec50ecf2
ED
1002 if (Fragment != NULL) {\r
1003 FreePool (Fragment);\r
1004 }\r
4b738c76 1005\r
4bad9ada 1006 return Status;\r
1007}\r