TianoCore EDK2 master
Loading...
Searching...
No Matches
DxeTcpIoLib.c
Go to the documentation of this file.
1
10#include <Uefi.h>
11
12#include <Library/TcpIoLib.h>
13#include <Library/BaseLib.h>
14#include <Library/DebugLib.h>
18
26VOID
27EFIAPI
29 IN EFI_EVENT Event,
30 IN VOID *Context
31 )
32{
33 if ((Event == NULL) || (Context == NULL)) {
34 return;
35 }
36
37 *((BOOLEAN *)Context) = TRUE;
38}
39
55 IN EFI_TCP6_CONFIG_DATA *Tcp6ConfigData
56 )
57{
58 EFI_STATUS Status;
59 EFI_EVENT Event;
60
61 if ((Tcp6 == NULL) || (Tcp6ConfigData == NULL)) {
62 return EFI_INVALID_PARAMETER;
63 }
64
65 Event = NULL;
66 Status = gBS->CreateEvent (
67 EVT_TIMER,
68 TPL_CALLBACK,
69 NULL,
70 NULL,
71 &Event
72 );
73 if (EFI_ERROR (Status)) {
74 goto ON_EXIT;
75 }
76
77 Status = gBS->SetTimer (
78 Event,
81 );
82
83 if (EFI_ERROR (Status)) {
84 goto ON_EXIT;
85 }
86
87 while (EFI_ERROR (gBS->CheckEvent (Event))) {
88 Tcp6->Poll (Tcp6);
89
90 Status = Tcp6->Configure (Tcp6, Tcp6ConfigData);
91
92 if (!EFI_ERROR (Status)) {
93 break;
94 }
95 }
96
97ON_EXIT:
98
99 if (Event != NULL) {
100 gBS->CloseEvent (Event);
101 }
102
103 return Status;
104}
105
124EFIAPI
126 IN EFI_HANDLE Image,
127 IN EFI_HANDLE Controller,
128 IN UINT8 TcpVersion,
129 IN TCP_IO_CONFIG_DATA *ConfigData,
130 OUT TCP_IO *TcpIo
131 )
132{
133 EFI_STATUS Status;
134 EFI_EVENT Event;
135 EFI_GUID *ServiceBindingGuid;
136 EFI_GUID *ProtocolGuid;
137 VOID **Interface;
138 EFI_TCP4_OPTION ControlOption;
139 EFI_TCP4_CONFIG_DATA Tcp4ConfigData;
140 EFI_TCP4_ACCESS_POINT *AccessPoint4;
141 EFI_TCP4_PROTOCOL *Tcp4;
142 EFI_TCP6_CONFIG_DATA Tcp6ConfigData;
143 EFI_TCP6_ACCESS_POINT *AccessPoint6;
144 EFI_TCP6_PROTOCOL *Tcp6;
145 EFI_TCP4_RECEIVE_DATA *RxData;
146
147 if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (TcpIo == NULL)) {
148 return EFI_INVALID_PARAMETER;
149 }
150
151 Tcp4 = NULL;
152 Tcp6 = NULL;
153
154 ZeroMem (TcpIo, sizeof (TCP_IO));
155
156 if (TcpVersion == TCP_VERSION_4) {
157 ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
158 ProtocolGuid = &gEfiTcp4ProtocolGuid;
159 Interface = (VOID **)(&TcpIo->Tcp.Tcp4);
160 } else if (TcpVersion == TCP_VERSION_6) {
161 ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
162 ProtocolGuid = &gEfiTcp6ProtocolGuid;
163 Interface = (VOID **)(&TcpIo->Tcp.Tcp6);
164 } else {
165 return EFI_UNSUPPORTED;
166 }
167
168 TcpIo->TcpVersion = TcpVersion;
169
170 //
171 // Create the TCP child instance and get the TCP protocol.
172 //
173 Status = NetLibCreateServiceChild (
174 Controller,
175 Image,
176 ServiceBindingGuid,
177 &TcpIo->Handle
178 );
179 if (EFI_ERROR (Status)) {
180 return Status;
181 }
182
183 Status = gBS->OpenProtocol (
184 TcpIo->Handle,
185 ProtocolGuid,
186 Interface,
187 Image,
188 Controller,
189 EFI_OPEN_PROTOCOL_BY_DRIVER
190 );
191 if (EFI_ERROR (Status) || (*Interface == NULL)) {
192 goto ON_ERROR;
193 }
194
195 if (TcpVersion == TCP_VERSION_4) {
196 Tcp4 = TcpIo->Tcp.Tcp4;
197 } else {
198 Tcp6 = TcpIo->Tcp.Tcp6;
199 }
200
201 TcpIo->Image = Image;
202 TcpIo->Controller = Controller;
203
204 //
205 // Set the configuration parameters.
206 //
207 ControlOption.ReceiveBufferSize = 0x200000;
208 ControlOption.SendBufferSize = 0x200000;
209 ControlOption.MaxSynBackLog = 0;
210 ControlOption.ConnectionTimeout = 0;
211 ControlOption.DataRetries = 6;
212 ControlOption.FinTimeout = 0;
213 ControlOption.TimeWaitTimeout = 0;
214 ControlOption.KeepAliveProbes = 4;
215 ControlOption.KeepAliveTime = 0;
216 ControlOption.KeepAliveInterval = 0;
217 ControlOption.EnableNagle = FALSE;
218 ControlOption.EnableTimeStamp = FALSE;
219 ControlOption.EnableWindowScaling = TRUE;
220 ControlOption.EnableSelectiveAck = FALSE;
221 ControlOption.EnablePathMtuDiscovery = FALSE;
222
223 if (TcpVersion == TCP_VERSION_4) {
224 Tcp4ConfigData.TypeOfService = 8;
225 Tcp4ConfigData.TimeToLive = 255;
226 Tcp4ConfigData.ControlOption = &ControlOption;
227
228 AccessPoint4 = &Tcp4ConfigData.AccessPoint;
229
230 ZeroMem (AccessPoint4, sizeof (EFI_TCP4_ACCESS_POINT));
231 AccessPoint4->StationPort = ConfigData->Tcp4IoConfigData.StationPort;
232 AccessPoint4->RemotePort = ConfigData->Tcp4IoConfigData.RemotePort;
233 AccessPoint4->ActiveFlag = ConfigData->Tcp4IoConfigData.ActiveFlag;
234
235 CopyMem (
236 &AccessPoint4->StationAddress,
237 &ConfigData->Tcp4IoConfigData.LocalIp,
238 sizeof (EFI_IPv4_ADDRESS)
239 );
240 CopyMem (
241 &AccessPoint4->SubnetMask,
242 &ConfigData->Tcp4IoConfigData.SubnetMask,
243 sizeof (EFI_IPv4_ADDRESS)
244 );
245 CopyMem (
246 &AccessPoint4->RemoteAddress,
247 &ConfigData->Tcp4IoConfigData.RemoteIp,
248 sizeof (EFI_IPv4_ADDRESS)
249 );
250
251 ASSERT (Tcp4 != NULL);
252
253 //
254 // Configure the TCP4 protocol.
255 //
256 Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData);
257 if (EFI_ERROR (Status)) {
258 goto ON_ERROR;
259 }
260
261 if (!EFI_IP4_EQUAL (&ConfigData->Tcp4IoConfigData.Gateway, &mZeroIp4Addr)) {
262 //
263 // The gateway is not zero. Add the default route manually.
264 //
265 Status = Tcp4->Routes (
266 Tcp4,
267 FALSE,
268 &mZeroIp4Addr,
269 &mZeroIp4Addr,
270 &ConfigData->Tcp4IoConfigData.Gateway
271 );
272 if (EFI_ERROR (Status)) {
273 goto ON_ERROR;
274 }
275 }
276 } else {
277 Tcp6ConfigData.TrafficClass = 0;
278 Tcp6ConfigData.HopLimit = 255;
279 Tcp6ConfigData.ControlOption = (EFI_TCP6_OPTION *)&ControlOption;
280
281 AccessPoint6 = &Tcp6ConfigData.AccessPoint;
282
283 ZeroMem (AccessPoint6, sizeof (EFI_TCP6_ACCESS_POINT));
284 AccessPoint6->StationPort = ConfigData->Tcp6IoConfigData.StationPort;
285 AccessPoint6->RemotePort = ConfigData->Tcp6IoConfigData.RemotePort;
286 AccessPoint6->ActiveFlag = ConfigData->Tcp6IoConfigData.ActiveFlag;
287
288 IP6_COPY_ADDRESS (&AccessPoint6->RemoteAddress, &ConfigData->Tcp6IoConfigData.RemoteIp);
289
290 ASSERT (Tcp6 != NULL);
291 //
292 // Configure the TCP6 protocol.
293 //
294 Status = Tcp6->Configure (Tcp6, &Tcp6ConfigData);
295 if (Status == EFI_NO_MAPPING) {
296 Status = TcpIoGetMapping (Tcp6, &Tcp6ConfigData);
297 }
298
299 if (EFI_ERROR (Status)) {
300 goto ON_ERROR;
301 }
302 }
303
304 //
305 // Create events for various asynchronous operations.
306 //
307 Status = gBS->CreateEvent (
308 EVT_NOTIFY_SIGNAL,
309 TPL_NOTIFY,
311 &TcpIo->IsConnDone,
312 &Event
313 );
314 if (EFI_ERROR (Status)) {
315 goto ON_ERROR;
316 }
317
318 TcpIo->ConnToken.Tcp4Token.CompletionToken.Event = Event;
319
320 Status = gBS->CreateEvent (
321 EVT_NOTIFY_SIGNAL,
322 TPL_NOTIFY,
324 &TcpIo->IsListenDone,
325 &Event
326 );
327 if (EFI_ERROR (Status)) {
328 goto ON_ERROR;
329 }
330
331 TcpIo->ListenToken.Tcp4Token.CompletionToken.Event = Event;
332
333 Status = gBS->CreateEvent (
334 EVT_NOTIFY_SIGNAL,
335 TPL_NOTIFY,
337 &TcpIo->IsTxDone,
338 &Event
339 );
340 if (EFI_ERROR (Status)) {
341 goto ON_ERROR;
342 }
343
344 TcpIo->TxToken.Tcp4Token.CompletionToken.Event = Event;
345
346 Status = gBS->CreateEvent (
347 EVT_NOTIFY_SIGNAL,
348 TPL_NOTIFY,
350 &TcpIo->IsRxDone,
351 &Event
352 );
353 if (EFI_ERROR (Status)) {
354 goto ON_ERROR;
355 }
356
357 TcpIo->RxToken.Tcp4Token.CompletionToken.Event = Event;
358
360 if (RxData == NULL) {
361 Status = EFI_OUT_OF_RESOURCES;
362 goto ON_ERROR;
363 }
364
365 TcpIo->RxToken.Tcp4Token.Packet.RxData = RxData;
366
367 Status = gBS->CreateEvent (
368 EVT_NOTIFY_SIGNAL,
369 TPL_NOTIFY,
371 &TcpIo->IsCloseDone,
372 &Event
373 );
374 if (EFI_ERROR (Status)) {
375 goto ON_ERROR;
376 }
377
378 TcpIo->CloseToken.Tcp4Token.CompletionToken.Event = Event;
379
380 return EFI_SUCCESS;
381
382ON_ERROR:
383
384 TcpIoDestroySocket (TcpIo);
385
386 return Status;
387}
388
395VOID
396EFIAPI
398 IN TCP_IO *TcpIo
399 )
400{
401 EFI_EVENT Event;
402 EFI_TCP4_PROTOCOL *Tcp4;
403 EFI_TCP6_PROTOCOL *Tcp6;
404 UINT8 TcpVersion;
405 EFI_GUID *ServiceBindingGuid;
406 EFI_GUID *ProtocolGuid;
407 EFI_HANDLE ChildHandle;
408
409 if (TcpIo == NULL) {
410 return;
411 }
412
413 TcpVersion = TcpIo->TcpVersion;
414
415 if ((TcpVersion != TCP_VERSION_4) && (TcpVersion != TCP_VERSION_6)) {
416 return;
417 }
418
419 Event = TcpIo->ConnToken.Tcp4Token.CompletionToken.Event;
420
421 if (Event != NULL) {
422 gBS->CloseEvent (Event);
423 }
424
425 Event = TcpIo->ListenToken.Tcp4Token.CompletionToken.Event;
426
427 if (Event != NULL) {
428 gBS->CloseEvent (Event);
429 }
430
431 Event = TcpIo->TxToken.Tcp4Token.CompletionToken.Event;
432
433 if (Event != NULL) {
434 gBS->CloseEvent (Event);
435 }
436
437 Event = TcpIo->RxToken.Tcp4Token.CompletionToken.Event;
438
439 if (Event != NULL) {
440 gBS->CloseEvent (Event);
441 }
442
443 Event = TcpIo->CloseToken.Tcp4Token.CompletionToken.Event;
444
445 if (Event != NULL) {
446 gBS->CloseEvent (Event);
447 }
448
449 if (TcpIo->RxToken.Tcp4Token.Packet.RxData != NULL) {
450 FreePool (TcpIo->RxToken.Tcp4Token.Packet.RxData);
451 }
452
453 Tcp4 = NULL;
454 Tcp6 = NULL;
455
456 if (TcpVersion == TCP_VERSION_4) {
457 ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
458 ProtocolGuid = &gEfiTcp4ProtocolGuid;
459 Tcp4 = TcpIo->Tcp.Tcp4;
460 if (Tcp4 != NULL) {
461 Tcp4->Configure (Tcp4, NULL);
462 }
463 } else {
464 ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
465 ProtocolGuid = &gEfiTcp6ProtocolGuid;
466 Tcp6 = TcpIo->Tcp.Tcp6;
467 if (Tcp6 != NULL) {
468 Tcp6->Configure (Tcp6, NULL);
469 }
470 }
471
472 if ((Tcp4 != NULL) || (Tcp6 != NULL)) {
473 gBS->CloseProtocol (
474 TcpIo->Handle,
475 ProtocolGuid,
476 TcpIo->Image,
477 TcpIo->Controller
478 );
479 }
480
481 ChildHandle = NULL;
482
483 if (TcpIo->IsListenDone) {
484 if (TcpVersion == TCP_VERSION_4) {
485 Tcp4 = TcpIo->NewTcp.Tcp4;
486 if (Tcp4 != NULL) {
487 Tcp4->Configure (Tcp4, NULL);
488 ChildHandle = TcpIo->ListenToken.Tcp4Token.NewChildHandle;
489 }
490 } else {
491 Tcp6 = TcpIo->NewTcp.Tcp6;
492 if (Tcp6 != NULL) {
493 Tcp6->Configure (Tcp6, NULL);
494 ChildHandle = TcpIo->ListenToken.Tcp6Token.NewChildHandle;
495 }
496 }
497
498 if (ChildHandle != NULL) {
499 gBS->CloseProtocol (
500 ChildHandle,
501 ProtocolGuid,
502 TcpIo->Image,
503 TcpIo->Controller
504 );
505 }
506 }
507
509 TcpIo->Controller,
510 TcpIo->Image,
511 ServiceBindingGuid,
512 TcpIo->Handle
513 );
514}
515
533EFIAPI
535 IN OUT TCP_IO *TcpIo,
536 IN EFI_EVENT Timeout OPTIONAL
537 )
538{
539 EFI_TCP4_PROTOCOL *Tcp4;
540 EFI_TCP6_PROTOCOL *Tcp6;
541 EFI_STATUS Status;
542
543 if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)) {
544 return EFI_INVALID_PARAMETER;
545 }
546
547 TcpIo->IsConnDone = FALSE;
548
549 Tcp4 = NULL;
550 Tcp6 = NULL;
551
552 if (TcpIo->TcpVersion == TCP_VERSION_4) {
553 Tcp4 = TcpIo->Tcp.Tcp4;
554 Status = Tcp4->Connect (Tcp4, &TcpIo->ConnToken.Tcp4Token);
555 } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
556 Tcp6 = TcpIo->Tcp.Tcp6;
557 Status = Tcp6->Connect (Tcp6, &TcpIo->ConnToken.Tcp6Token);
558 } else {
559 return EFI_UNSUPPORTED;
560 }
561
562 if (EFI_ERROR (Status)) {
563 return Status;
564 }
565
566 while (!TcpIo->IsConnDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
567 if (TcpIo->TcpVersion == TCP_VERSION_4) {
568 Tcp4->Poll (Tcp4);
569 } else {
570 Tcp6->Poll (Tcp6);
571 }
572 }
573
574 if (!TcpIo->IsConnDone) {
575 if (TcpIo->TcpVersion == TCP_VERSION_4) {
576 Tcp4->Cancel (Tcp4, &TcpIo->ConnToken.Tcp4Token.CompletionToken);
577 } else {
578 Tcp6->Cancel (Tcp6, &TcpIo->ConnToken.Tcp6Token.CompletionToken);
579 }
580
581 Status = EFI_TIMEOUT;
582 } else {
583 Status = TcpIo->ConnToken.Tcp4Token.CompletionToken.Status;
584 }
585
586 return Status;
587}
588
608EFIAPI
610 IN OUT TCP_IO *TcpIo,
611 IN EFI_EVENT Timeout OPTIONAL
612 )
613{
614 EFI_STATUS Status;
615 EFI_GUID *ProtocolGuid;
616 EFI_TCP4_PROTOCOL *Tcp4;
617 EFI_TCP6_PROTOCOL *Tcp6;
618
619 if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)) {
620 return EFI_INVALID_PARAMETER;
621 }
622
623 TcpIo->IsListenDone = FALSE;
624
625 Tcp4 = NULL;
626 Tcp6 = NULL;
627
628 if (TcpIo->TcpVersion == TCP_VERSION_4) {
629 Tcp4 = TcpIo->Tcp.Tcp4;
630 Status = Tcp4->Accept (Tcp4, &TcpIo->ListenToken.Tcp4Token);
631 } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
632 Tcp6 = TcpIo->Tcp.Tcp6;
633 Status = Tcp6->Accept (Tcp6, &TcpIo->ListenToken.Tcp6Token);
634 } else {
635 return EFI_UNSUPPORTED;
636 }
637
638 if (EFI_ERROR (Status)) {
639 return Status;
640 }
641
642 while (!TcpIo->IsListenDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
643 if (TcpIo->TcpVersion == TCP_VERSION_4) {
644 Tcp4->Poll (Tcp4);
645 } else {
646 Tcp6->Poll (Tcp6);
647 }
648 }
649
650 if (!TcpIo->IsListenDone) {
651 if (TcpIo->TcpVersion == TCP_VERSION_4) {
652 Tcp4->Cancel (Tcp4, &TcpIo->ListenToken.Tcp4Token.CompletionToken);
653 } else {
654 Tcp6->Cancel (Tcp6, &TcpIo->ListenToken.Tcp6Token.CompletionToken);
655 }
656
657 Status = EFI_TIMEOUT;
658 } else {
659 Status = TcpIo->ListenToken.Tcp4Token.CompletionToken.Status;
660 }
661
662 //
663 // The new TCP instance handle created for the established connection is
664 // in ListenToken.
665 //
666 if (!EFI_ERROR (Status)) {
667 if (TcpIo->TcpVersion == TCP_VERSION_4) {
668 ProtocolGuid = &gEfiTcp4ProtocolGuid;
669 } else {
670 ProtocolGuid = &gEfiTcp6ProtocolGuid;
671 }
672
673 Status = gBS->OpenProtocol (
674 TcpIo->ListenToken.Tcp4Token.NewChildHandle,
675 ProtocolGuid,
676 (VOID **)(&TcpIo->NewTcp.Tcp4),
677 TcpIo->Image,
678 TcpIo->Controller,
679 EFI_OPEN_PROTOCOL_BY_DRIVER
680 );
681 }
682
683 return Status;
684}
685
692VOID
693EFIAPI
695 IN OUT TCP_IO *TcpIo
696 )
697{
698 EFI_TCP4_PROTOCOL *Tcp4;
699 EFI_TCP6_PROTOCOL *Tcp6;
700 EFI_STATUS Status;
701
702 if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)) {
703 return;
704 }
705
706 TcpIo->IsCloseDone = FALSE;
707 Tcp4 = NULL;
708 Tcp6 = NULL;
709
710 if (TcpIo->TcpVersion == TCP_VERSION_4) {
711 TcpIo->CloseToken.Tcp4Token.AbortOnClose = TRUE;
712 Tcp4 = TcpIo->Tcp.Tcp4;
713 Status = Tcp4->Close (Tcp4, &TcpIo->CloseToken.Tcp4Token);
714 } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
715 TcpIo->CloseToken.Tcp6Token.AbortOnClose = TRUE;
716 Tcp6 = TcpIo->Tcp.Tcp6;
717 Status = Tcp6->Close (Tcp6, &TcpIo->CloseToken.Tcp6Token);
718 } else {
719 return;
720 }
721
722 if (EFI_ERROR (Status)) {
723 return;
724 }
725
726 while (!TcpIo->IsCloseDone) {
727 if (TcpIo->TcpVersion == TCP_VERSION_4) {
728 Tcp4->Poll (Tcp4);
729 } else {
730 Tcp6->Poll (Tcp6);
731 }
732 }
733}
734
751EFIAPI
753 IN TCP_IO *TcpIo,
754 IN NET_BUF *Packet
755 )
756{
757 EFI_STATUS Status;
758 VOID *Data;
759 EFI_TCP4_PROTOCOL *Tcp4;
760 EFI_TCP6_PROTOCOL *Tcp6;
761 UINTN Size;
762
763 if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL) || (Packet == NULL)) {
764 return EFI_INVALID_PARAMETER;
765 }
766
767 if (TcpIo->TcpVersion == TCP_VERSION_4) {
768 Size = sizeof (EFI_TCP4_TRANSMIT_DATA) +
769 (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA);
770 } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
771 Size = sizeof (EFI_TCP6_TRANSMIT_DATA) +
772 (Packet->BlockOpNum - 1) * sizeof (EFI_TCP6_FRAGMENT_DATA);
773 } else {
774 return EFI_UNSUPPORTED;
775 }
776
777 Data = AllocatePool (Size);
778 if (Data == NULL) {
779 return EFI_OUT_OF_RESOURCES;
780 }
781
782 ((EFI_TCP4_TRANSMIT_DATA *)Data)->Push = TRUE;
783 ((EFI_TCP4_TRANSMIT_DATA *)Data)->Urgent = FALSE;
784 ((EFI_TCP4_TRANSMIT_DATA *)Data)->DataLength = Packet->TotalSize;
785
786 //
787 // Build the fragment table.
788 //
789 ((EFI_TCP4_TRANSMIT_DATA *)Data)->FragmentCount = Packet->BlockOpNum;
790
792 Packet,
793 (NET_FRAGMENT *)&((EFI_TCP4_TRANSMIT_DATA *)Data)->FragmentTable[0],
794 &((EFI_TCP4_TRANSMIT_DATA *)Data)->FragmentCount
795 );
796
797 Tcp4 = NULL;
798 Tcp6 = NULL;
799 Status = EFI_DEVICE_ERROR;
800
801 //
802 // Transmit the packet.
803 //
804 if (TcpIo->TcpVersion == TCP_VERSION_4) {
805 TcpIo->TxToken.Tcp4Token.Packet.TxData = (EFI_TCP4_TRANSMIT_DATA *)Data;
806 Tcp4 = TcpIo->Tcp.Tcp4;
807 if (TcpIo->IsListenDone) {
808 Tcp4 = TcpIo->NewTcp.Tcp4;
809 }
810
811 if (Tcp4 == NULL) {
812 goto ON_EXIT;
813 }
814
815 Status = Tcp4->Transmit (Tcp4, &TcpIo->TxToken.Tcp4Token);
816 } else {
817 TcpIo->TxToken.Tcp6Token.Packet.TxData = (EFI_TCP6_TRANSMIT_DATA *)Data;
818 Tcp6 = TcpIo->Tcp.Tcp6;
819 if (TcpIo->IsListenDone) {
820 Tcp6 = TcpIo->NewTcp.Tcp6;
821 }
822
823 if (Tcp6 == NULL) {
824 goto ON_EXIT;
825 }
826
827 Status = Tcp6->Transmit (Tcp6, &TcpIo->TxToken.Tcp6Token);
828 }
829
830 if (EFI_ERROR (Status)) {
831 goto ON_EXIT;
832 }
833
834 while (!TcpIo->IsTxDone) {
835 if (TcpIo->TcpVersion == TCP_VERSION_4) {
836 Tcp4->Poll (Tcp4);
837 } else {
838 Tcp6->Poll (Tcp6);
839 }
840 }
841
842 TcpIo->IsTxDone = FALSE;
843 Status = TcpIo->TxToken.Tcp4Token.CompletionToken.Status;
844
845ON_EXIT:
846
847 FreePool (Data);
848
849 return Status;
850}
851
871EFIAPI
873 IN OUT TCP_IO *TcpIo,
874 IN NET_BUF *Packet,
875 IN BOOLEAN AsyncMode,
876 IN EFI_EVENT Timeout OPTIONAL
877 )
878{
879 EFI_TCP4_PROTOCOL *Tcp4;
880 EFI_TCP6_PROTOCOL *Tcp6;
881 EFI_TCP4_RECEIVE_DATA *RxData;
882 EFI_STATUS Status;
883 NET_FRAGMENT *Fragment;
884 UINT32 FragmentCount;
885 UINT32 CurrentFragment;
886
887 if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL) || (Packet == NULL)) {
888 return EFI_INVALID_PARAMETER;
889 }
890
891 RxData = TcpIo->RxToken.Tcp4Token.Packet.RxData;
892 if (RxData == NULL) {
893 return EFI_INVALID_PARAMETER;
894 }
895
896 Tcp4 = NULL;
897 Tcp6 = NULL;
898
899 if (TcpIo->TcpVersion == TCP_VERSION_4) {
900 Tcp4 = TcpIo->Tcp.Tcp4;
901
902 if (TcpIo->IsListenDone) {
903 Tcp4 = TcpIo->NewTcp.Tcp4;
904 }
905
906 if (Tcp4 == NULL) {
907 return EFI_DEVICE_ERROR;
908 }
909 } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
910 Tcp6 = TcpIo->Tcp.Tcp6;
911
912 if (TcpIo->IsListenDone) {
913 Tcp6 = TcpIo->NewTcp.Tcp6;
914 }
915
916 if (Tcp6 == NULL) {
917 return EFI_DEVICE_ERROR;
918 }
919 } else {
920 return EFI_UNSUPPORTED;
921 }
922
923 FragmentCount = Packet->BlockOpNum;
924 Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));
925 if (Fragment == NULL) {
926 Status = EFI_OUT_OF_RESOURCES;
927 goto ON_EXIT;
928 }
929
930 //
931 // Build the fragment table.
932 //
933 NetbufBuildExt (Packet, Fragment, &FragmentCount);
934
935 RxData->FragmentCount = 1;
936 CurrentFragment = 0;
937 Status = EFI_SUCCESS;
938
939 while (CurrentFragment < FragmentCount) {
940 RxData->DataLength = Fragment[CurrentFragment].Len;
941 RxData->FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len;
942 RxData->FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk;
943
944 if (TcpIo->TcpVersion == TCP_VERSION_4) {
945 Status = Tcp4->Receive (Tcp4, &TcpIo->RxToken.Tcp4Token);
946 } else {
947 Status = Tcp6->Receive (Tcp6, &TcpIo->RxToken.Tcp6Token);
948 }
949
950 if (EFI_ERROR (Status)) {
951 goto ON_EXIT;
952 }
953
954 while (!TcpIo->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
955 //
956 // Poll until some data is received or an error occurs.
957 //
958 if (TcpIo->TcpVersion == TCP_VERSION_4) {
959 Tcp4->Poll (Tcp4);
960 } else {
961 Tcp6->Poll (Tcp6);
962 }
963 }
964
965 if (!TcpIo->IsRxDone) {
966 //
967 // Timeout occurs, cancel the receive request.
968 //
969 if (TcpIo->TcpVersion == TCP_VERSION_4) {
970 Tcp4->Cancel (Tcp4, &TcpIo->RxToken.Tcp4Token.CompletionToken);
971 } else {
972 Tcp6->Cancel (Tcp6, &TcpIo->RxToken.Tcp6Token.CompletionToken);
973 }
974
975 Status = EFI_TIMEOUT;
976 goto ON_EXIT;
977 } else {
978 TcpIo->IsRxDone = FALSE;
979 }
980
981 Status = TcpIo->RxToken.Tcp4Token.CompletionToken.Status;
982
983 if (EFI_ERROR (Status)) {
984 goto ON_EXIT;
985 }
986
987 Fragment[CurrentFragment].Len -= RxData->FragmentTable[0].FragmentLength;
988 if (Fragment[CurrentFragment].Len == 0) {
989 CurrentFragment++;
990 } else {
991 Fragment[CurrentFragment].Bulk += RxData->FragmentTable[0].FragmentLength;
992 }
993 }
994
995ON_EXIT:
996
997 if (Fragment != NULL) {
998 FreePool (Fragment);
999 }
1000
1001 return Status;
1002}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS EFIAPI TcpIoCreateSocket(IN EFI_HANDLE Image, IN EFI_HANDLE Controller, IN UINT8 TcpVersion, IN TCP_IO_CONFIG_DATA *ConfigData, OUT TCP_IO *TcpIo)
Definition: DxeTcpIoLib.c:125
EFI_STATUS EFIAPI TcpIoAccept(IN OUT TCP_IO *TcpIo, IN EFI_EVENT Timeout OPTIONAL)
Definition: DxeTcpIoLib.c:609
EFI_STATUS EFIAPI TcpIoReceive(IN OUT TCP_IO *TcpIo, IN NET_BUF *Packet, IN BOOLEAN AsyncMode, IN EFI_EVENT Timeout OPTIONAL)
Definition: DxeTcpIoLib.c:872
EFI_STATUS EFIAPI TcpIoConnect(IN OUT TCP_IO *TcpIo, IN EFI_EVENT Timeout OPTIONAL)
Definition: DxeTcpIoLib.c:534
EFI_STATUS TcpIoGetMapping(IN EFI_TCP6_PROTOCOL *Tcp6, IN EFI_TCP6_CONFIG_DATA *Tcp6ConfigData)
Definition: DxeTcpIoLib.c:53
EFI_STATUS EFIAPI TcpIoTransmit(IN TCP_IO *TcpIo, IN NET_BUF *Packet)
Definition: DxeTcpIoLib.c:752
VOID EFIAPI TcpIoDestroySocket(IN TCP_IO *TcpIo)
Definition: DxeTcpIoLib.c:397
VOID EFIAPI TcpIoReset(IN OUT TCP_IO *TcpIo)
Definition: DxeTcpIoLib.c:694
VOID EFIAPI TcpIoCommonNotify(IN EFI_EVENT Event, IN VOID *Context)
Definition: DxeTcpIoLib.c:28
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
EFI_STATUS EFIAPI NetbufBuildExt(IN NET_BUF *Nbuf, IN OUT NET_FRAGMENT *ExtFragment, IN OUT UINT32 *ExtNum)
Definition: NetBuffer.c:866
EFI_STATUS EFIAPI NetLibCreateServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN OUT EFI_HANDLE *ChildHandle)
Definition: DxeNetLib.c:1967
EFI_STATUS EFIAPI NetLibDestroyServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN EFI_HANDLE ChildHandle)
Definition: DxeNetLib.c:2020
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
#define TCP_GET_MAPPING_TIMEOUT
Definition: TcpIoLib.h:24
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ TimerRelative
Definition: UefiSpec.h:539
UINT16 RemotePort
Definition: Tcp6.h:114
BOOLEAN ActiveFlag
Definition: Tcp6.h:119
EFI_IPv6_ADDRESS RemoteAddress
Definition: Tcp6.h:105
UINT16 StationPort
Definition: Tcp6.h:93
EFI_TCP6_ACCESS_POINT AccessPoint
Definition: Tcp6.h:232
UINT8 TrafficClass
Definition: Tcp6.h:224
EFI_TCP6_OPTION * ControlOption
Definition: Tcp6.h:237
Definition: Base.h:213