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