TianoCore EDK2 master
Loading...
Searching...
No Matches
DxeUdpIoLib.c
Go to the documentation of this file.
1
8#include <Uefi.h>
9
10#include <Protocol/Udp4.h>
11#include <Protocol/Udp6.h>
12
13#include <Library/UdpIoLib.h>
14#include <Library/BaseLib.h>
15#include <Library/DebugLib.h>
19#include <Library/DpcLib.h>
20
27VOID
29 IN UDP_TX_TOKEN *TxToken
30 )
31{
32 if (TxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
33 gBS->CloseEvent (TxToken->Token.Udp4.Event);
34 } else if (TxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION) {
35 gBS->CloseEvent (TxToken->Token.Udp6.Event);
36 } else {
37 ASSERT (FALSE);
38 }
39
40 FreePool (TxToken);
41}
42
49VOID
51 IN UDP_RX_TOKEN *RxToken
52 )
53{
54 if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
55 gBS->CloseEvent (RxToken->Token.Udp4.Event);
56 } else if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION) {
57 gBS->CloseEvent (RxToken->Token.Udp6.Event);
58 } else {
59 ASSERT (FALSE);
60 }
61
62 FreePool (RxToken);
63}
64
74VOID
75EFIAPI
77 IN VOID *Context
78 )
79{
80 UDP_TX_TOKEN *TxToken;
81
82 TxToken = (UDP_TX_TOKEN *)Context;
83 ASSERT (TxToken->Signature == UDP_IO_TX_SIGNATURE);
84 ASSERT (
85 (TxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
86 (TxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
87 );
88
89 RemoveEntryList (&TxToken->Link);
90
91 if (TxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
92 TxToken->CallBack (TxToken->Packet, NULL, TxToken->Token.Udp4.Status, TxToken->Context);
93 } else {
94 TxToken->CallBack (TxToken->Packet, NULL, TxToken->Token.Udp6.Status, TxToken->Context);
95 }
96
97 UdpIoFreeTxToken (TxToken);
98}
99
107VOID
108EFIAPI
110 IN EFI_EVENT Event,
111 IN VOID *Context
112 )
113{
114 //
115 // Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK
116 //
117 QueueDpc (TPL_CALLBACK, UdpIoOnDgramSentDpc, Context);
118}
119
126VOID
127EFIAPI
129 IN VOID *Context
130 )
131{
132 UDP_RX_TOKEN *RxToken;
133
134 RxToken = (UDP_RX_TOKEN *)Context;
135
136 if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
137 gBS->SignalEvent (RxToken->Token.Udp4.Packet.RxData->RecycleSignal);
138 } else if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION) {
139 gBS->SignalEvent (RxToken->Token.Udp6.Packet.RxData->RecycleSignal);
140 } else {
141 ASSERT (FALSE);
142 }
143
144 UdpIoFreeRxToken (RxToken);
145}
146
156VOID
157EFIAPI
159 IN VOID *Context
160 )
161{
162 EFI_STATUS Status;
163 VOID *Token;
164 VOID *RxData;
165 VOID *Session;
166 UDP_RX_TOKEN *RxToken;
167 UDP_END_POINT EndPoint;
168 NET_BUF *Netbuf;
169
170 RxToken = (UDP_RX_TOKEN *)Context;
171
172 ZeroMem (&EndPoint, sizeof (UDP_END_POINT));
173
174 ASSERT (
175 (RxToken->Signature == UDP_IO_RX_SIGNATURE) &&
176 (RxToken == RxToken->UdpIo->RecvRequest)
177 );
178
179 ASSERT (
180 (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
181 (RxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
182 );
183
184 //
185 // Clear the receive request first in case that the caller
186 // wants to restart the receive in the callback.
187 //
188 RxToken->UdpIo->RecvRequest = NULL;
189
190 if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
191 Token = &RxToken->Token.Udp4;
192 RxData = ((EFI_UDP4_COMPLETION_TOKEN *)Token)->Packet.RxData;
193 Status = ((EFI_UDP4_COMPLETION_TOKEN *)Token)->Status;
194 } else {
195 Token = &RxToken->Token.Udp6;
196 RxData = ((EFI_UDP6_COMPLETION_TOKEN *)Token)->Packet.RxData;
197 Status = ((EFI_UDP6_COMPLETION_TOKEN *)Token)->Status;
198 }
199
200 if (EFI_ERROR (Status) || (RxData == NULL)) {
201 if (Status != EFI_ABORTED) {
202 //
203 // Invoke the CallBack only if the reception is not actively aborted.
204 //
205 RxToken->CallBack (NULL, NULL, Status, RxToken->Context);
206 }
207
208 UdpIoFreeRxToken (RxToken);
209 return;
210 }
211
212 //
213 // Build a NET_BUF from the UDP receive data, then deliver it up.
214 //
215 if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
216 if (((EFI_UDP4_RECEIVE_DATA *)RxData)->DataLength == 0) {
217 //
218 // Discard zero length data payload packet.
219 //
220 goto Resume;
221 }
222
223 Netbuf = NetbufFromExt (
224 (NET_FRAGMENT *)((EFI_UDP4_RECEIVE_DATA *)RxData)->FragmentTable,
225 ((EFI_UDP4_RECEIVE_DATA *)RxData)->FragmentCount,
226 0,
227 (UINT32)RxToken->HeadLen,
229 RxToken
230 );
231
232 if (Netbuf == NULL) {
233 gBS->SignalEvent (((EFI_UDP4_RECEIVE_DATA *)RxData)->RecycleSignal);
234 RxToken->CallBack (NULL, NULL, EFI_OUT_OF_RESOURCES, RxToken->Context);
235
236 UdpIoFreeRxToken (RxToken);
237 return;
238 }
239
240 Session = &((EFI_UDP4_RECEIVE_DATA *)RxData)->UdpSession;
241 EndPoint.LocalPort = ((EFI_UDP4_SESSION_DATA *)Session)->DestinationPort;
242 EndPoint.RemotePort = ((EFI_UDP4_SESSION_DATA *)Session)->SourcePort;
243
244 CopyMem (
245 &EndPoint.LocalAddr,
246 &((EFI_UDP4_SESSION_DATA *)Session)->DestinationAddress,
247 sizeof (EFI_IPv4_ADDRESS)
248 );
249
250 CopyMem (
251 &EndPoint.RemoteAddr,
252 &((EFI_UDP4_SESSION_DATA *)Session)->SourceAddress,
253 sizeof (EFI_IPv4_ADDRESS)
254 );
255
256 EndPoint.LocalAddr.Addr[0] = NTOHL (EndPoint.LocalAddr.Addr[0]);
257 EndPoint.RemoteAddr.Addr[0] = NTOHL (EndPoint.RemoteAddr.Addr[0]);
258 } else {
259 if (((EFI_UDP6_RECEIVE_DATA *)RxData)->DataLength == 0) {
260 //
261 // Discard zero length data payload packet.
262 //
263 goto Resume;
264 }
265
266 Netbuf = NetbufFromExt (
267 (NET_FRAGMENT *)((EFI_UDP6_RECEIVE_DATA *)RxData)->FragmentTable,
268 ((EFI_UDP6_RECEIVE_DATA *)RxData)->FragmentCount,
269 0,
270 (UINT32)RxToken->HeadLen,
272 RxToken
273 );
274
275 if (Netbuf == NULL) {
276 gBS->SignalEvent (((EFI_UDP6_RECEIVE_DATA *)RxData)->RecycleSignal);
277 RxToken->CallBack (NULL, NULL, EFI_OUT_OF_RESOURCES, RxToken->Context);
278
279 UdpIoFreeRxToken (RxToken);
280 return;
281 }
282
283 Session = &((EFI_UDP6_RECEIVE_DATA *)RxData)->UdpSession;
284 EndPoint.LocalPort = ((EFI_UDP6_SESSION_DATA *)Session)->DestinationPort;
285 EndPoint.RemotePort = ((EFI_UDP6_SESSION_DATA *)Session)->SourcePort;
286
287 CopyMem (
288 &EndPoint.LocalAddr,
289 &((EFI_UDP6_SESSION_DATA *)Session)->DestinationAddress,
290 sizeof (EFI_IPv6_ADDRESS)
291 );
292
293 CopyMem (
294 &EndPoint.RemoteAddr,
295 &((EFI_UDP6_SESSION_DATA *)Session)->SourceAddress,
296 sizeof (EFI_IPv6_ADDRESS)
297 );
298
299 Ip6Swap128 (&EndPoint.LocalAddr.v6);
300 Ip6Swap128 (&EndPoint.RemoteAddr.v6);
301 }
302
303 RxToken->CallBack (Netbuf, &EndPoint, EFI_SUCCESS, RxToken->Context);
304 return;
305
306Resume:
307 if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
308 gBS->SignalEvent (((EFI_UDP4_RECEIVE_DATA *)RxData)->RecycleSignal);
309 RxToken->UdpIo->Protocol.Udp4->Receive (RxToken->UdpIo->Protocol.Udp4, &RxToken->Token.Udp4);
310 } else {
311 gBS->SignalEvent (((EFI_UDP6_RECEIVE_DATA *)RxData)->RecycleSignal);
312 RxToken->UdpIo->Protocol.Udp6->Receive (RxToken->UdpIo->Protocol.Udp6, &RxToken->Token.Udp6);
313 }
314}
315
323VOID
324EFIAPI
326 IN EFI_EVENT Event,
327 IN VOID *Context
328 )
329{
330 //
331 // Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK
332 //
333 QueueDpc (TPL_CALLBACK, UdpIoOnDgramRcvdDpc, Context);
334}
335
349 IN UDP_IO *UdpIo,
350 IN UDP_IO_CALLBACK CallBack,
351 IN VOID *Context,
352 IN UINT32 HeadLen
353 )
354{
355 UDP_RX_TOKEN *Token;
356 EFI_STATUS Status;
357
358 ASSERT (
359 (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
360 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
361 );
362
363 Token = AllocatePool (sizeof (UDP_RX_TOKEN));
364
365 if (Token == NULL) {
366 return NULL;
367 }
368
369 Token->Signature = UDP_IO_RX_SIGNATURE;
370 Token->UdpIo = UdpIo;
371 Token->CallBack = CallBack;
372 Token->Context = Context;
373 Token->HeadLen = HeadLen;
374
375 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
376 Token->Token.Udp4.Status = EFI_NOT_READY;
377 Token->Token.Udp4.Packet.RxData = NULL;
378
379 Status = gBS->CreateEvent (
380 EVT_NOTIFY_SIGNAL,
381 TPL_NOTIFY,
383 Token,
384 &Token->Token.Udp4.Event
385 );
386 } else {
387 Token->Token.Udp6.Status = EFI_NOT_READY;
388 Token->Token.Udp6.Packet.RxData = NULL;
389
390 Status = gBS->CreateEvent (
391 EVT_NOTIFY_SIGNAL,
392 TPL_NOTIFY,
394 Token,
395 &Token->Token.Udp6.Event
396 );
397 }
398
399 if (EFI_ERROR (Status)) {
400 FreePool (Token);
401 return NULL;
402 }
403
404 return Token;
405}
406
426 IN UDP_IO *UdpIo,
427 IN NET_BUF *Packet,
428 IN UDP_END_POINT *EndPoint OPTIONAL,
429 IN EFI_IP_ADDRESS *Gateway OPTIONAL,
430 IN UDP_IO_CALLBACK CallBack,
431 IN VOID *Context
432 )
433{
434 UDP_TX_TOKEN *TxToken;
435 VOID *Token;
436 VOID *Data;
437 EFI_STATUS Status;
438 UINT32 Count;
439 UINTN Size;
440 IP4_ADDR Ip;
441
442 ASSERT (Packet != NULL);
443 ASSERT (
444 (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
445 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
446 );
447
448 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
449 Size = sizeof (UDP_TX_TOKEN) + sizeof (EFI_UDP4_FRAGMENT_DATA) * (Packet->BlockOpNum - 1);
450 } else {
451 Size = sizeof (UDP_TX_TOKEN) + sizeof (EFI_UDP6_FRAGMENT_DATA) * (Packet->BlockOpNum - 1);
452 }
453
454 TxToken = AllocatePool (Size);
455
456 if (TxToken == NULL) {
457 return NULL;
458 }
459
460 TxToken->Signature = UDP_IO_TX_SIGNATURE;
461 InitializeListHead (&TxToken->Link);
462
463 TxToken->UdpIo = UdpIo;
464 TxToken->CallBack = CallBack;
465 TxToken->Packet = Packet;
466 TxToken->Context = Context;
467
468 Token = &(TxToken->Token);
469 Count = Packet->BlockOpNum;
470
471 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
472 ((EFI_UDP4_COMPLETION_TOKEN *)Token)->Status = EFI_NOT_READY;
473
474 Status = gBS->CreateEvent (
475 EVT_NOTIFY_SIGNAL,
476 TPL_NOTIFY,
478 TxToken,
479 &((EFI_UDP4_COMPLETION_TOKEN *)Token)->Event
480 );
481
482 if (EFI_ERROR (Status)) {
483 FreePool (TxToken);
484 return NULL;
485 }
486
487 Data = &(TxToken->Data.Udp4);
488 ((EFI_UDP4_COMPLETION_TOKEN *)Token)->Packet.TxData = Data;
489
490 ((EFI_UDP4_TRANSMIT_DATA *)Data)->UdpSessionData = NULL;
491 ((EFI_UDP4_TRANSMIT_DATA *)Data)->GatewayAddress = NULL;
492 ((EFI_UDP4_TRANSMIT_DATA *)Data)->DataLength = Packet->TotalSize;
493
495 Packet,
496 (NET_FRAGMENT *)((EFI_UDP4_TRANSMIT_DATA *)Data)->FragmentTable,
497 &Count
498 );
499
500 ((EFI_UDP4_TRANSMIT_DATA *)Data)->FragmentCount = Count;
501
502 if (EndPoint != NULL) {
503 Ip = HTONL (EndPoint->LocalAddr.Addr[0]);
504 CopyMem (
505 &TxToken->Session.Udp4.SourceAddress,
506 &Ip,
507 sizeof (EFI_IPv4_ADDRESS)
508 );
509
510 Ip = HTONL (EndPoint->RemoteAddr.Addr[0]);
511 CopyMem (
512 &TxToken->Session.Udp4.DestinationAddress,
513 &Ip,
514 sizeof (EFI_IPv4_ADDRESS)
515 );
516
517 TxToken->Session.Udp4.SourcePort = EndPoint->LocalPort;
518 TxToken->Session.Udp4.DestinationPort = EndPoint->RemotePort;
519 ((EFI_UDP4_TRANSMIT_DATA *)Data)->UdpSessionData = &(TxToken->Session.Udp4);
520 }
521
522 if ((Gateway != NULL) && (Gateway->Addr[0] != 0)) {
523 Ip = HTONL (Gateway->Addr[0]);
524 CopyMem (&TxToken->Gateway, &Ip, sizeof (EFI_IPv4_ADDRESS));
525 ((EFI_UDP4_TRANSMIT_DATA *)Data)->GatewayAddress = &TxToken->Gateway;
526 }
527 } else {
528 ((EFI_UDP6_COMPLETION_TOKEN *)Token)->Status = EFI_NOT_READY;
529
530 Status = gBS->CreateEvent (
531 EVT_NOTIFY_SIGNAL,
532 TPL_NOTIFY,
534 TxToken,
535 &((EFI_UDP6_COMPLETION_TOKEN *)Token)->Event
536 );
537
538 if (EFI_ERROR (Status)) {
539 FreePool (TxToken);
540 return NULL;
541 }
542
543 Data = &(TxToken->Data.Udp6);
544 ((EFI_UDP6_COMPLETION_TOKEN *)Token)->Packet.TxData = Data;
545 ((EFI_UDP6_TRANSMIT_DATA *)Data)->UdpSessionData = NULL;
546 ((EFI_UDP6_TRANSMIT_DATA *)Data)->DataLength = Packet->TotalSize;
547
549 Packet,
550 (NET_FRAGMENT *)((EFI_UDP6_TRANSMIT_DATA *)Data)->FragmentTable,
551 &Count
552 );
553
554 ((EFI_UDP6_TRANSMIT_DATA *)Data)->FragmentCount = Count;
555
556 if (EndPoint != NULL) {
557 CopyMem (
558 &TxToken->Session.Udp6.SourceAddress,
559 &EndPoint->LocalAddr.v6,
560 sizeof (EFI_IPv6_ADDRESS)
561 );
562
563 CopyMem (
564 &TxToken->Session.Udp6.DestinationAddress,
565 &EndPoint->RemoteAddr.v6,
566 sizeof (EFI_IPv6_ADDRESS)
567 );
568
569 TxToken->Session.Udp6.SourcePort = EndPoint->LocalPort;
570 TxToken->Session.Udp6.DestinationPort = EndPoint->RemotePort;
571 ((EFI_UDP6_TRANSMIT_DATA *)Data)->UdpSessionData = &(TxToken->Session.Udp6);
572 }
573 }
574
575 return TxToken;
576}
577
600UDP_IO *
601EFIAPI
603 IN EFI_HANDLE Controller,
604 IN EFI_HANDLE ImageHandle,
605 IN UDP_IO_CONFIG Configure,
606 IN UINT8 UdpVersion,
607 IN VOID *Context
608 )
609{
610 UDP_IO *UdpIo;
611 EFI_STATUS Status;
612
613 ASSERT (Configure != NULL);
614 ASSERT ((UdpVersion == UDP_IO_UDP4_VERSION) || (UdpVersion == UDP_IO_UDP6_VERSION));
615
616 UdpIo = AllocatePool (sizeof (UDP_IO));
617
618 if (UdpIo == NULL) {
619 return NULL;
620 }
621
622 UdpIo->UdpVersion = UdpVersion;
623 UdpIo->Signature = UDP_IO_SIGNATURE;
624 InitializeListHead (&UdpIo->Link);
625 UdpIo->RefCnt = 1;
626
627 UdpIo->Controller = Controller;
628 UdpIo->Image = ImageHandle;
629
631 UdpIo->RecvRequest = NULL;
632 UdpIo->UdpHandle = NULL;
633
634 if (UdpVersion == UDP_IO_UDP4_VERSION) {
635 //
636 // Create a UDP child then open and configure it
637 //
638 Status = NetLibCreateServiceChild (
639 Controller,
640 ImageHandle,
641 &gEfiUdp4ServiceBindingProtocolGuid,
642 &UdpIo->UdpHandle
643 );
644
645 if (EFI_ERROR (Status)) {
646 goto FREE_MEM;
647 }
648
649 Status = gBS->OpenProtocol (
650 UdpIo->UdpHandle,
651 &gEfiUdp4ProtocolGuid,
652 (VOID **)&UdpIo->Protocol.Udp4,
653 ImageHandle,
654 Controller,
655 EFI_OPEN_PROTOCOL_BY_DRIVER
656 );
657
658 if (EFI_ERROR (Status)) {
659 goto FREE_CHILD;
660 }
661
662 if (EFI_ERROR (Configure (UdpIo, Context))) {
663 goto CLOSE_PROTOCOL;
664 }
665
666 Status = UdpIo->Protocol.Udp4->GetModeData (
667 UdpIo->Protocol.Udp4,
668 NULL,
669 NULL,
670 NULL,
671 &UdpIo->SnpMode
672 );
673
674 if (EFI_ERROR (Status)) {
675 goto CLOSE_PROTOCOL;
676 }
677 } else {
678 Status = NetLibCreateServiceChild (
679 Controller,
680 ImageHandle,
681 &gEfiUdp6ServiceBindingProtocolGuid,
682 &UdpIo->UdpHandle
683 );
684
685 if (EFI_ERROR (Status)) {
686 goto FREE_MEM;
687 }
688
689 Status = gBS->OpenProtocol (
690 UdpIo->UdpHandle,
691 &gEfiUdp6ProtocolGuid,
692 (VOID **)&UdpIo->Protocol.Udp6,
693 ImageHandle,
694 Controller,
695 EFI_OPEN_PROTOCOL_BY_DRIVER
696 );
697
698 if (EFI_ERROR (Status)) {
699 goto FREE_CHILD;
700 }
701
702 if (EFI_ERROR (Configure (UdpIo, Context))) {
703 goto CLOSE_PROTOCOL;
704 }
705
706 Status = UdpIo->Protocol.Udp6->GetModeData (
707 UdpIo->Protocol.Udp6,
708 NULL,
709 NULL,
710 NULL,
711 &UdpIo->SnpMode
712 );
713
714 if (EFI_ERROR (Status)) {
715 goto CLOSE_PROTOCOL;
716 }
717 }
718
719 return UdpIo;
720
721CLOSE_PROTOCOL:
722 if (UdpVersion == UDP_IO_UDP4_VERSION) {
723 gBS->CloseProtocol (UdpIo->UdpHandle, &gEfiUdp4ProtocolGuid, ImageHandle, Controller);
724 } else {
725 gBS->CloseProtocol (UdpIo->UdpHandle, &gEfiUdp6ProtocolGuid, ImageHandle, Controller);
726 }
727
728FREE_CHILD:
729 if (UdpVersion == UDP_IO_UDP4_VERSION) {
731 Controller,
732 ImageHandle,
733 &gEfiUdp4ServiceBindingProtocolGuid,
734 UdpIo->UdpHandle
735 );
736 } else {
738 Controller,
739 ImageHandle,
740 &gEfiUdp6ServiceBindingProtocolGuid,
741 UdpIo->UdpHandle
742 );
743 }
744
745FREE_MEM:
746 FreePool (UdpIo);
747 return NULL;
748}
749
763VOID
764EFIAPI
766 IN UDP_IO *UdpIo,
767 IN EFI_STATUS IoStatus,
768 IN UDP_IO_TO_CANCEL ToCancel OPTIONAL,
769 IN VOID *Context OPTIONAL
770 )
771{
772 LIST_ENTRY *Entry;
773 LIST_ENTRY *Next;
774 UDP_TX_TOKEN *TxToken;
775
776 ASSERT (
777 (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
778 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
779 );
780
781 NET_LIST_FOR_EACH_SAFE (Entry, Next, &UdpIo->SentDatagram) {
782 TxToken = NET_LIST_USER_STRUCT (Entry, UDP_TX_TOKEN, Link);
783
784 if ((ToCancel == NULL) || (ToCancel (TxToken, Context))) {
785 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
786 UdpIo->Protocol.Udp4->Cancel (UdpIo->Protocol.Udp4, &TxToken->Token.Udp4);
787 } else {
788 UdpIo->Protocol.Udp6->Cancel (UdpIo->Protocol.Udp6, &TxToken->Token.Udp6);
789 }
790 }
791 }
792}
793
808EFIAPI
810 IN UDP_IO *UdpIo
811 )
812{
813 EFI_STATUS Status;
814 UDP_RX_TOKEN *RxToken;
815
816 ASSERT (
817 (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
818 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
819 );
820
821 //
822 // Cancel all the sent datagram and receive requests. The
823 // callbacks of transmit requests are executed to allow the
824 // caller to release the resource. The callback of receive
825 // request are NOT executed. This is because it is most
826 // likely that the current user of the UDP IO port is closing
827 // itself.
828 //
829 UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);
830
831 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
832 if ((RxToken = UdpIo->RecvRequest) != NULL) {
833 Status = UdpIo->Protocol.Udp4->Cancel (UdpIo->Protocol.Udp4, &RxToken->Token.Udp4);
834 if (EFI_ERROR (Status)) {
835 return Status;
836 }
837 }
838
839 //
840 // Close then destroy the Udp4 child
841 //
842 Status = gBS->CloseProtocol (
843 UdpIo->UdpHandle,
844 &gEfiUdp4ProtocolGuid,
845 UdpIo->Image,
846 UdpIo->Controller
847 );
848 if (EFI_ERROR (Status)) {
849 return Status;
850 }
851
853 UdpIo->Controller,
854 UdpIo->Image,
855 &gEfiUdp4ServiceBindingProtocolGuid,
856 UdpIo->UdpHandle
857 );
858 if (EFI_ERROR (Status)) {
859 return Status;
860 }
861 } else {
862 if ((RxToken = UdpIo->RecvRequest) != NULL) {
863 Status = UdpIo->Protocol.Udp6->Cancel (UdpIo->Protocol.Udp6, &RxToken->Token.Udp6);
864 if (EFI_ERROR (Status)) {
865 return Status;
866 }
867 }
868
869 //
870 // Close then destroy the Udp6 child
871 //
872 Status = gBS->CloseProtocol (
873 UdpIo->UdpHandle,
874 &gEfiUdp6ProtocolGuid,
875 UdpIo->Image,
876 UdpIo->Controller
877 );
878 if (EFI_ERROR (Status)) {
879 return Status;
880 }
881
883 UdpIo->Controller,
884 UdpIo->Image,
885 &gEfiUdp6ServiceBindingProtocolGuid,
886 UdpIo->UdpHandle
887 );
888 if (EFI_ERROR (Status)) {
889 return Status;
890 }
891 }
892
893 if (!IsListEmpty (&UdpIo->Link)) {
894 RemoveEntryList (&UdpIo->Link);
895 }
896
897 FreePool (UdpIo);
898 return EFI_SUCCESS;
899}
900
913VOID
914EFIAPI
916 IN UDP_IO *UdpIo
917 )
918{
919 UDP_RX_TOKEN *RxToken;
920
921 ASSERT (
922 (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
923 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
924 );
925
926 //
927 // Cancel all the sent datagram and receive requests.
928 //
929 UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);
930
931 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
932 if ((RxToken = UdpIo->RecvRequest) != NULL) {
933 UdpIo->Protocol.Udp4->Cancel (UdpIo->Protocol.Udp4, &RxToken->Token.Udp4);
934 }
935
936 UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, NULL);
937 } else {
938 if ((RxToken = UdpIo->RecvRequest) != NULL) {
939 UdpIo->Protocol.Udp6->Cancel (UdpIo->Protocol.Udp6, &RxToken->Token.Udp6);
940 }
941
942 UdpIo->Protocol.Udp6->Configure (UdpIo->Protocol.Udp6, NULL);
943 }
944}
945
970EFIAPI
972 IN UDP_IO *UdpIo,
973 IN NET_BUF *Packet,
974 IN UDP_END_POINT *EndPoint OPTIONAL,
975 IN EFI_IP_ADDRESS *Gateway OPTIONAL,
976 IN UDP_IO_CALLBACK CallBack,
977 IN VOID *Context
978 )
979{
980 UDP_TX_TOKEN *TxToken;
981 EFI_STATUS Status;
982
983 ASSERT (
984 (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
985 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
986 );
987
988 TxToken = UdpIoCreateTxToken (UdpIo, Packet, EndPoint, Gateway, CallBack, Context);
989
990 if (TxToken == NULL) {
991 return EFI_OUT_OF_RESOURCES;
992 }
993
994 //
995 // Insert the tx token into SendDatagram list before transmitting it. Remove
996 // it from the list if the returned status is not EFI_SUCCESS.
997 //
998 InsertHeadList (&UdpIo->SentDatagram, &TxToken->Link);
999
1000 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
1001 Status = UdpIo->Protocol.Udp4->Transmit (UdpIo->Protocol.Udp4, &TxToken->Token.Udp4);
1002 } else {
1003 Status = UdpIo->Protocol.Udp6->Transmit (UdpIo->Protocol.Udp6, &TxToken->Token.Udp6);
1004 }
1005
1006 if (EFI_ERROR (Status)) {
1007 RemoveEntryList (&TxToken->Link);
1008 UdpIoFreeTxToken (TxToken);
1009 return Status;
1010 }
1011
1012 return EFI_SUCCESS;
1013}
1014
1024BOOLEAN
1025EFIAPI
1027 IN UDP_TX_TOKEN *Token,
1028 IN VOID *Context
1029 )
1030{
1031 NET_BUF *Packet;
1032
1033 Packet = (NET_BUF *)Context;
1034
1035 if (Token->Packet == Packet) {
1036 return TRUE;
1037 }
1038
1039 return FALSE;
1040}
1041
1049VOID
1050EFIAPI
1052 IN UDP_IO *UdpIo,
1053 IN NET_BUF *Packet
1054 )
1055{
1056 UdpIoCancelDgrams (UdpIo, EFI_ABORTED, UdpIoCancelSingleDgram, Packet);
1057}
1058
1083EFIAPI
1085 IN UDP_IO *UdpIo,
1086 IN UDP_IO_CALLBACK CallBack,
1087 IN VOID *Context,
1088 IN UINT32 HeadLen
1089 )
1090{
1091 UDP_RX_TOKEN *RxToken;
1092 EFI_STATUS Status;
1093
1094 ASSERT (
1095 (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
1096 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
1097 );
1098
1099 if (UdpIo->RecvRequest != NULL) {
1100 return EFI_ALREADY_STARTED;
1101 }
1102
1103 RxToken = UdpIoCreateRxToken (UdpIo, CallBack, Context, HeadLen);
1104
1105 if (RxToken == NULL) {
1106 return EFI_OUT_OF_RESOURCES;
1107 }
1108
1109 UdpIo->RecvRequest = RxToken;
1110 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
1111 Status = UdpIo->Protocol.Udp4->Receive (UdpIo->Protocol.Udp4, &RxToken->Token.Udp4);
1112 } else {
1113 Status = UdpIo->Protocol.Udp6->Receive (UdpIo->Protocol.Udp6, &RxToken->Token.Udp6);
1114 }
1115
1116 if (EFI_ERROR (Status)) {
1117 UdpIo->RecvRequest = NULL;
1118 UdpIoFreeRxToken (RxToken);
1119 }
1120
1121 return Status;
1122}
UINT64 UINTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
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 QueueDpc(IN EFI_TPL DpcTpl, IN EFI_DPC_PROCEDURE DpcProcedure, IN VOID *DpcContext OPTIONAL)
Definition: DpcLib.c:62
VOID EFIAPI UdpIoRecycleDgram(IN VOID *Context)
Definition: DxeUdpIoLib.c:128
UDP_RX_TOKEN * UdpIoCreateRxToken(IN UDP_IO *UdpIo, IN UDP_IO_CALLBACK CallBack, IN VOID *Context, IN UINT32 HeadLen)
Definition: DxeUdpIoLib.c:348
VOID UdpIoFreeTxToken(IN UDP_TX_TOKEN *TxToken)
Definition: DxeUdpIoLib.c:28
VOID UdpIoFreeRxToken(IN UDP_RX_TOKEN *RxToken)
Definition: DxeUdpIoLib.c:50
VOID EFIAPI UdpIoOnDgramRcvdDpc(IN VOID *Context)
Definition: DxeUdpIoLib.c:158
VOID EFIAPI UdpIoCancelSentDatagram(IN UDP_IO *UdpIo, IN NET_BUF *Packet)
Definition: DxeUdpIoLib.c:1051
VOID EFIAPI UdpIoOnDgramRcvd(IN EFI_EVENT Event, IN VOID *Context)
Definition: DxeUdpIoLib.c:325
VOID EFIAPI UdpIoCleanIo(IN UDP_IO *UdpIo)
Definition: DxeUdpIoLib.c:915
VOID EFIAPI UdpIoCancelDgrams(IN UDP_IO *UdpIo, IN EFI_STATUS IoStatus, IN UDP_IO_TO_CANCEL ToCancel OPTIONAL, IN VOID *Context OPTIONAL)
Definition: DxeUdpIoLib.c:765
BOOLEAN EFIAPI UdpIoCancelSingleDgram(IN UDP_TX_TOKEN *Token, IN VOID *Context)
Definition: DxeUdpIoLib.c:1026
EFI_STATUS EFIAPI UdpIoRecvDatagram(IN UDP_IO *UdpIo, IN UDP_IO_CALLBACK CallBack, IN VOID *Context, IN UINT32 HeadLen)
Definition: DxeUdpIoLib.c:1084
EFI_STATUS EFIAPI UdpIoSendDatagram(IN UDP_IO *UdpIo, IN NET_BUF *Packet, IN UDP_END_POINT *EndPoint OPTIONAL, IN EFI_IP_ADDRESS *Gateway OPTIONAL, IN UDP_IO_CALLBACK CallBack, IN VOID *Context)
Definition: DxeUdpIoLib.c:971
VOID EFIAPI UdpIoOnDgramSentDpc(IN VOID *Context)
Definition: DxeUdpIoLib.c:76
VOID EFIAPI UdpIoOnDgramSent(IN EFI_EVENT Event, IN VOID *Context)
Definition: DxeUdpIoLib.c:109
UDP_TX_TOKEN * UdpIoCreateTxToken(IN UDP_IO *UdpIo, IN NET_BUF *Packet, IN UDP_END_POINT *EndPoint OPTIONAL, IN EFI_IP_ADDRESS *Gateway OPTIONAL, IN UDP_IO_CALLBACK CallBack, IN VOID *Context)
Definition: DxeUdpIoLib.c:425
EFI_STATUS EFIAPI UdpIoFreeIo(IN UDP_IO *UdpIo)
Definition: DxeUdpIoLib.c:809
UDP_IO *EFIAPI UdpIoCreateIo(IN EFI_HANDLE Controller, IN EFI_HANDLE ImageHandle, IN UDP_IO_CONFIG Configure, IN UINT8 UdpVersion, IN VOID *Context)
Definition: DxeUdpIoLib.c:602
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
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_IPv6_ADDRESS *EFIAPI Ip6Swap128(EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:892
EFI_STATUS EFIAPI NetLibDestroyServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN EFI_HANDLE ChildHandle)
Definition: DxeNetLib.c:2020
NET_BUF *EFIAPI NetbufFromExt(IN NET_FRAGMENT *ExtFragment, IN UINT32 ExtNum, IN UINT32 HeadSpace, IN UINT32 HeadLen, IN NET_VECTOR_EXT_FREE ExtFree, IN VOID *Arg OPTIONAL)
Definition: NetBuffer.c:693
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
#define UDP_IO_RX_SIGNATURE
Definition: UdpIoLib.h:24
EFI_STATUS(EFIAPI * UDP_IO_CONFIG)(IN UDP_IO *UdpIo, IN VOID *Context)
Definition: UdpIoLib.h:168
BOOLEAN(EFIAPI * UDP_IO_TO_CANCEL)(IN UDP_TX_TOKEN *Token, IN VOID *Context)
Definition: UdpIoLib.h:185
VOID(EFIAPI * UDP_IO_CALLBACK)(IN NET_BUF *Packet, IN UDP_END_POINT *EndPoint, IN EFI_STATUS IoStatus, IN VOID *Context)
Definition: UdpIoLib.h:57
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
LIST_ENTRY SentDatagram
A list of UDP_TX_TOKEN.
Definition: UdpIoLib.h:140
EFI_UDP6_RECEIVE_DATA * RxData
Definition: Udp6.h:288
EFI_STATUS Status
Definition: Udp6.h:283
EFI_EVENT RecycleSignal
Definition: Udp6.h:228
EFI_IPv6_ADDRESS DestinationAddress
Definition: Udp6.h:110
UINT16 SourcePort
Definition: Udp6.h:105
EFI_IPv6_ADDRESS SourceAddress
Definition: Udp6.h:100
UINT16 DestinationPort
Definition: Udp6.h:115