2 Help functions to access UDP service, it is used by both the DHCP and MTFTP.
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Protocol/Udp4.h>
11 #include <Protocol/Udp6.h>
13 #include <Library/UdpIoLib.h>
14 #include <Library/BaseLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DpcLib.h>
23 Free a UDP_TX_TOKEN. The TX event is closed.
25 @param[in] TxToken The UDP_TX_TOKEN to release.
30 IN UDP_TX_TOKEN
*TxToken
34 if (TxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
35 gBS
->CloseEvent (TxToken
->Token
.Udp4
.Event
);
36 } else if (TxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
) {
37 gBS
->CloseEvent (TxToken
->Token
.Udp6
.Event
);
46 Free a UDP_RX_TOKEN. The RX event is closed.
48 @param[in] RxToken The UDP_RX_TOKEN to release.
53 IN UDP_RX_TOKEN
*RxToken
56 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
57 gBS
->CloseEvent (RxToken
->Token
.Udp4
.Event
);
58 } else if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
) {
59 gBS
->CloseEvent (RxToken
->Token
.Udp6
.Event
);
68 The callback function when the packet is sent by UDP.
70 It will remove the packet from the local list then call
71 the packet owner's callback function set by UdpIoSendDatagram.
73 @param[in] Context The UDP TX Token.
82 UDP_TX_TOKEN
*TxToken
;
84 TxToken
= (UDP_TX_TOKEN
*) Context
;
85 ASSERT (TxToken
->Signature
== UDP_IO_TX_SIGNATURE
);
86 ASSERT ((TxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
87 (TxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
89 RemoveEntryList (&TxToken
->Link
);
91 if (TxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
92 TxToken
->CallBack (TxToken
->Packet
, NULL
, TxToken
->Token
.Udp4
.Status
, TxToken
->Context
);
94 TxToken
->CallBack (TxToken
->Packet
, NULL
, TxToken
->Token
.Udp6
.Status
, TxToken
->Context
);
97 UdpIoFreeTxToken (TxToken
);
101 Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK.
103 @param[in] Event The event signaled.
104 @param[in] Context The UDP TX Token.
115 // Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK
117 QueueDpc (TPL_CALLBACK
, UdpIoOnDgramSentDpc
, Context
);
121 Recycle the received UDP data.
123 @param[in] Context The UDP_RX_TOKEN.
132 UDP_RX_TOKEN
*RxToken
;
134 RxToken
= (UDP_RX_TOKEN
*) Context
;
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
);
144 UdpIoFreeRxToken (RxToken
);
148 The event handle for UDP receive request.
150 It will build a NET_BUF from the received UDP data, then deliver it
153 @param[in] Context The UDP RX token.
158 UdpIoOnDgramRcvdDpc (
166 UDP_RX_TOKEN
*RxToken
;
167 UDP_END_POINT EndPoint
;
170 RxToken
= (UDP_RX_TOKEN
*) Context
;
172 ZeroMem (&EndPoint
, sizeof(UDP_END_POINT
));
174 ASSERT ((RxToken
->Signature
== UDP_IO_RX_SIGNATURE
) &&
175 (RxToken
== RxToken
->UdpIo
->RecvRequest
));
177 ASSERT ((RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
178 (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
181 // Clear the receive request first in case that the caller
182 // wants to restart the receive in the callback.
184 RxToken
->UdpIo
->RecvRequest
= NULL
;
186 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
187 Token
= &RxToken
->Token
.Udp4
;
188 RxData
= ((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Packet
.RxData
;
189 Status
= ((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Status
;
191 Token
= &RxToken
->Token
.Udp6
;
192 RxData
= ((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Packet
.RxData
;
193 Status
= ((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Status
;
196 if (EFI_ERROR (Status
) || RxData
== NULL
) {
197 if (Status
!= EFI_ABORTED
) {
199 // Invoke the CallBack only if the reception is not actively aborted.
201 RxToken
->CallBack (NULL
, NULL
, Status
, RxToken
->Context
);
204 UdpIoFreeRxToken (RxToken
);
209 // Build a NET_BUF from the UDP receive data, then deliver it up.
211 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
212 if (((EFI_UDP4_RECEIVE_DATA
*) RxData
)->DataLength
== 0) {
214 // Discard zero length data payload packet.
219 Netbuf
= NetbufFromExt (
220 (NET_FRAGMENT
*)((EFI_UDP4_RECEIVE_DATA
*) RxData
)->FragmentTable
,
221 ((EFI_UDP4_RECEIVE_DATA
*) RxData
)->FragmentCount
,
223 (UINT32
) RxToken
->HeadLen
,
228 if (Netbuf
== NULL
) {
229 gBS
->SignalEvent (((EFI_UDP4_RECEIVE_DATA
*) RxData
)->RecycleSignal
);
230 RxToken
->CallBack (NULL
, NULL
, EFI_OUT_OF_RESOURCES
, RxToken
->Context
);
232 UdpIoFreeRxToken (RxToken
);
236 Session
= &((EFI_UDP4_RECEIVE_DATA
*) RxData
)->UdpSession
;
237 EndPoint
.LocalPort
= ((EFI_UDP4_SESSION_DATA
*) Session
)->DestinationPort
;
238 EndPoint
.RemotePort
= ((EFI_UDP4_SESSION_DATA
*) Session
)->SourcePort
;
242 &((EFI_UDP4_SESSION_DATA
*) Session
)->DestinationAddress
,
243 sizeof (EFI_IPv4_ADDRESS
)
247 &EndPoint
.RemoteAddr
,
248 &((EFI_UDP4_SESSION_DATA
*) Session
)->SourceAddress
,
249 sizeof (EFI_IPv4_ADDRESS
)
252 EndPoint
.LocalAddr
.Addr
[0] = NTOHL (EndPoint
.LocalAddr
.Addr
[0]);
253 EndPoint
.RemoteAddr
.Addr
[0] = NTOHL (EndPoint
.RemoteAddr
.Addr
[0]);
255 if (((EFI_UDP6_RECEIVE_DATA
*) RxData
)->DataLength
== 0) {
257 // Discard zero length data payload packet.
262 Netbuf
= NetbufFromExt (
263 (NET_FRAGMENT
*)((EFI_UDP6_RECEIVE_DATA
*) RxData
)->FragmentTable
,
264 ((EFI_UDP6_RECEIVE_DATA
*) RxData
)->FragmentCount
,
266 (UINT32
) RxToken
->HeadLen
,
271 if (Netbuf
== NULL
) {
272 gBS
->SignalEvent (((EFI_UDP6_RECEIVE_DATA
*) RxData
)->RecycleSignal
);
273 RxToken
->CallBack (NULL
, NULL
, EFI_OUT_OF_RESOURCES
, RxToken
->Context
);
275 UdpIoFreeRxToken (RxToken
);
279 Session
= &((EFI_UDP6_RECEIVE_DATA
*) RxData
)->UdpSession
;
280 EndPoint
.LocalPort
= ((EFI_UDP6_SESSION_DATA
*) Session
)->DestinationPort
;
281 EndPoint
.RemotePort
= ((EFI_UDP6_SESSION_DATA
*) Session
)->SourcePort
;
285 &((EFI_UDP6_SESSION_DATA
*) Session
)->DestinationAddress
,
286 sizeof (EFI_IPv6_ADDRESS
)
290 &EndPoint
.RemoteAddr
,
291 &((EFI_UDP6_SESSION_DATA
*) Session
)->SourceAddress
,
292 sizeof (EFI_IPv6_ADDRESS
)
295 Ip6Swap128 (&EndPoint
.LocalAddr
.v6
);
296 Ip6Swap128 (&EndPoint
.RemoteAddr
.v6
);
299 RxToken
->CallBack (Netbuf
, &EndPoint
, EFI_SUCCESS
, RxToken
->Context
);
303 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
304 gBS
->SignalEvent (((EFI_UDP4_RECEIVE_DATA
*) RxData
)->RecycleSignal
);
305 RxToken
->UdpIo
->Protocol
.Udp4
->Receive (RxToken
->UdpIo
->Protocol
.Udp4
, &RxToken
->Token
.Udp4
);
307 gBS
->SignalEvent (((EFI_UDP6_RECEIVE_DATA
*) RxData
)->RecycleSignal
);
308 RxToken
->UdpIo
->Protocol
.Udp6
->Receive (RxToken
->UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
313 Request UdpIoOnDgramRcvdDpc() as a DPC at TPL_CALLBACK.
315 @param[in] Event The UDP receive request event.
316 @param[in] Context The UDP RX token.
327 // Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK
329 QueueDpc (TPL_CALLBACK
, UdpIoOnDgramRcvdDpc
, Context
);
333 Create a UDP_RX_TOKEN to wrap the request.
335 @param[in] UdpIo The UdpIo to receive packets from.
336 @param[in] CallBack The function to call when receive finished.
337 @param[in] Context The opaque parameter to the CallBack.
338 @param[in] HeadLen The head length to reserve for the packet.
340 @return The Wrapped request or NULL if failed to allocate resources or some errors happened.
346 IN UDP_IO_CALLBACK CallBack
,
354 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
355 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
357 Token
= AllocatePool (sizeof (UDP_RX_TOKEN
));
363 Token
->Signature
= UDP_IO_RX_SIGNATURE
;
364 Token
->UdpIo
= UdpIo
;
365 Token
->CallBack
= CallBack
;
366 Token
->Context
= Context
;
367 Token
->HeadLen
= HeadLen
;
369 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
371 Token
->Token
.Udp4
.Status
= EFI_NOT_READY
;
372 Token
->Token
.Udp4
.Packet
.RxData
= NULL
;
374 Status
= gBS
->CreateEvent (
379 &Token
->Token
.Udp4
.Event
383 Token
->Token
.Udp6
.Status
= EFI_NOT_READY
;
384 Token
->Token
.Udp6
.Packet
.RxData
= NULL
;
386 Status
= gBS
->CreateEvent (
391 &Token
->Token
.Udp6
.Event
396 if (EFI_ERROR (Status
)) {
405 Wrap a transmit request into a new created UDP_TX_TOKEN.
407 If Packet is NULL, then ASSERT().
408 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().
410 @param[in] UdpIo The UdpIo to send packet to.
411 @param[in] Packet The user's packet.
412 @param[in] EndPoint The local and remote access point.
413 @param[in] Gateway The overridden next hop.
414 @param[in] CallBack The function to call when transmission completed.
415 @param[in] Context The opaque parameter to the call back.
417 @return The wrapped transmission request or NULL if failed to allocate resources
425 IN UDP_END_POINT
*EndPoint OPTIONAL
,
426 IN EFI_IP_ADDRESS
*Gateway OPTIONAL
,
427 IN UDP_IO_CALLBACK CallBack
,
431 UDP_TX_TOKEN
*TxToken
;
439 ASSERT (Packet
!= NULL
);
440 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
441 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
443 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
444 Size
= sizeof (UDP_TX_TOKEN
) + sizeof (EFI_UDP4_FRAGMENT_DATA
) * (Packet
->BlockOpNum
- 1);
446 Size
= sizeof (UDP_TX_TOKEN
) + sizeof (EFI_UDP6_FRAGMENT_DATA
) * (Packet
->BlockOpNum
- 1);
449 TxToken
= AllocatePool (Size
);
451 if (TxToken
== NULL
) {
455 TxToken
->Signature
= UDP_IO_TX_SIGNATURE
;
456 InitializeListHead (&TxToken
->Link
);
458 TxToken
->UdpIo
= UdpIo
;
459 TxToken
->CallBack
= CallBack
;
460 TxToken
->Packet
= Packet
;
461 TxToken
->Context
= Context
;
463 Token
= &(TxToken
->Token
);
464 Count
= Packet
->BlockOpNum
;
466 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
468 ((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Status
= EFI_NOT_READY
;
470 Status
= gBS
->CreateEvent (
475 &((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Event
478 if (EFI_ERROR (Status
)) {
483 Data
= &(TxToken
->Data
.Udp4
);
484 ((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Packet
.TxData
= Data
;
486 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->UdpSessionData
= NULL
;
487 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->GatewayAddress
= NULL
;
488 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->DataLength
= Packet
->TotalSize
;
492 (NET_FRAGMENT
*)((EFI_UDP4_TRANSMIT_DATA
*) Data
)->FragmentTable
,
496 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->FragmentCount
= Count
;
498 if (EndPoint
!= NULL
) {
499 Ip
= HTONL (EndPoint
->LocalAddr
.Addr
[0]);
501 &TxToken
->Session
.Udp4
.SourceAddress
,
503 sizeof (EFI_IPv4_ADDRESS
)
506 Ip
= HTONL (EndPoint
->RemoteAddr
.Addr
[0]);
508 &TxToken
->Session
.Udp4
.DestinationAddress
,
510 sizeof (EFI_IPv4_ADDRESS
)
513 TxToken
->Session
.Udp4
.SourcePort
= EndPoint
->LocalPort
;
514 TxToken
->Session
.Udp4
.DestinationPort
= EndPoint
->RemotePort
;
515 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->UdpSessionData
= &(TxToken
->Session
.Udp4
);
518 if (Gateway
!= NULL
&& (Gateway
->Addr
[0] != 0)) {
519 Ip
= HTONL (Gateway
->Addr
[0]);
520 CopyMem (&TxToken
->Gateway
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
521 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->GatewayAddress
= &TxToken
->Gateway
;
526 ((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Status
= EFI_NOT_READY
;
528 Status
= gBS
->CreateEvent (
533 &((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Event
536 if (EFI_ERROR (Status
)) {
541 Data
= &(TxToken
->Data
.Udp6
);
542 ((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Packet
.TxData
= Data
;
543 ((EFI_UDP6_TRANSMIT_DATA
*) Data
)->UdpSessionData
= NULL
;
544 ((EFI_UDP6_TRANSMIT_DATA
*) Data
)->DataLength
= Packet
->TotalSize
;
548 (NET_FRAGMENT
*)((EFI_UDP6_TRANSMIT_DATA
*) Data
)->FragmentTable
,
552 ((EFI_UDP6_TRANSMIT_DATA
*) Data
)->FragmentCount
= Count
;
554 if (EndPoint
!= NULL
) {
556 &TxToken
->Session
.Udp6
.SourceAddress
,
557 &EndPoint
->LocalAddr
.v6
,
558 sizeof(EFI_IPv6_ADDRESS
)
562 &TxToken
->Session
.Udp6
.DestinationAddress
,
563 &EndPoint
->RemoteAddr
.v6
,
564 sizeof(EFI_IPv6_ADDRESS
)
567 TxToken
->Session
.Udp6
.SourcePort
= EndPoint
->LocalPort
;
568 TxToken
->Session
.Udp6
.DestinationPort
= EndPoint
->RemotePort
;
569 ((EFI_UDP6_TRANSMIT_DATA
*) Data
)->UdpSessionData
= &(TxToken
->Session
.Udp6
);
577 Creates a UDP_IO to access the UDP service. It creates and configures
580 If Configure is NULL, then ASSERT().
581 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().
583 It locates the UDP service binding prototype on the Controller parameter
584 uses the UDP service binding prototype to create a UDP child (also known as
585 a UDP instance) configures the UDP child by calling Configure function prototype.
586 Any failures in creating or configuring the UDP child return NULL for failure.
588 @param[in] Controller The controller that has the UDP service binding.
590 @param[in] ImageHandle The image handle for the driver.
591 @param[in] Configure The function to configure the created UDP child.
592 @param[in] UdpVersion The UDP protocol version, UDP4 or UDP6.
593 @param[in] Context The opaque parameter for the Configure function.
595 @return Newly-created UDP_IO or NULL if failed.
601 IN EFI_HANDLE Controller
,
602 IN EFI_HANDLE ImageHandle
,
603 IN UDP_IO_CONFIG Configure
,
611 ASSERT (Configure
!= NULL
);
612 ASSERT ((UdpVersion
== UDP_IO_UDP4_VERSION
) || (UdpVersion
== UDP_IO_UDP6_VERSION
));
614 UdpIo
= AllocatePool (sizeof (UDP_IO
));
620 UdpIo
->UdpVersion
= UdpVersion
;
621 UdpIo
->Signature
= UDP_IO_SIGNATURE
;
622 InitializeListHead (&UdpIo
->Link
);
625 UdpIo
->Controller
= Controller
;
626 UdpIo
->Image
= ImageHandle
;
628 InitializeListHead (&UdpIo
->SentDatagram
);
629 UdpIo
->RecvRequest
= NULL
;
630 UdpIo
->UdpHandle
= NULL
;
632 if (UdpVersion
== UDP_IO_UDP4_VERSION
) {
634 // Create a UDP child then open and configure it
636 Status
= NetLibCreateServiceChild (
639 &gEfiUdp4ServiceBindingProtocolGuid
,
643 if (EFI_ERROR (Status
)) {
647 Status
= gBS
->OpenProtocol (
649 &gEfiUdp4ProtocolGuid
,
650 (VOID
**) &UdpIo
->Protocol
.Udp4
,
653 EFI_OPEN_PROTOCOL_BY_DRIVER
656 if (EFI_ERROR (Status
)) {
660 if (EFI_ERROR (Configure (UdpIo
, Context
))) {
664 Status
= UdpIo
->Protocol
.Udp4
->GetModeData (
665 UdpIo
->Protocol
.Udp4
,
672 if (EFI_ERROR (Status
)) {
678 Status
= NetLibCreateServiceChild (
681 &gEfiUdp6ServiceBindingProtocolGuid
,
685 if (EFI_ERROR (Status
)) {
689 Status
= gBS
->OpenProtocol (
691 &gEfiUdp6ProtocolGuid
,
692 (VOID
**) &UdpIo
->Protocol
.Udp6
,
695 EFI_OPEN_PROTOCOL_BY_DRIVER
698 if (EFI_ERROR (Status
)) {
702 if (EFI_ERROR (Configure (UdpIo
, Context
))) {
706 Status
= UdpIo
->Protocol
.Udp6
->GetModeData (
707 UdpIo
->Protocol
.Udp6
,
714 if (EFI_ERROR (Status
)) {
722 if (UdpVersion
== UDP_IO_UDP4_VERSION
) {
723 gBS
->CloseProtocol (UdpIo
->UdpHandle
, &gEfiUdp4ProtocolGuid
, ImageHandle
, Controller
);
725 gBS
->CloseProtocol (UdpIo
->UdpHandle
, &gEfiUdp6ProtocolGuid
, ImageHandle
, Controller
);
729 if (UdpVersion
== UDP_IO_UDP4_VERSION
) {
730 NetLibDestroyServiceChild (
733 &gEfiUdp4ServiceBindingProtocolGuid
,
737 NetLibDestroyServiceChild (
740 &gEfiUdp6ServiceBindingProtocolGuid
,
751 Cancel all the sent datagram that pass the selection criteria of ToCancel.
753 If ToCancel is NULL, all the datagrams are cancelled.
754 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().
756 @param[in] UdpIo The UDP_IO to cancel packet.
757 @param[in] IoStatus The IoStatus to return to the packet owners.
758 @param[in] ToCancel The select function to test whether to cancel this
760 @param[in] Context The opaque parameter to the ToCancel.
767 IN EFI_STATUS IoStatus
,
768 IN UDP_IO_TO_CANCEL ToCancel
, OPTIONAL
769 IN VOID
*Context OPTIONAL
774 UDP_TX_TOKEN
*TxToken
;
776 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
777 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
779 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &UdpIo
->SentDatagram
) {
780 TxToken
= NET_LIST_USER_STRUCT (Entry
, UDP_TX_TOKEN
, Link
);
782 if ((ToCancel
== NULL
) || (ToCancel (TxToken
, Context
))) {
784 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
785 UdpIo
->Protocol
.Udp4
->Cancel (UdpIo
->Protocol
.Udp4
, &TxToken
->Token
.Udp4
);
787 UdpIo
->Protocol
.Udp6
->Cancel (UdpIo
->Protocol
.Udp6
, &TxToken
->Token
.Udp6
);
794 Free the UDP_IO and all its related resources.
796 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().
798 The function will cancel all sent datagram and receive request.
800 @param[in] UdpIo The UDP_IO to free.
802 @retval EFI_SUCCESS The UDP_IO is freed.
803 @retval Others Failed to free UDP_IO.
813 UDP_RX_TOKEN
*RxToken
;
815 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
816 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
819 // Cancel all the sent datagram and receive requests. The
820 // callbacks of transmit requests are executed to allow the
821 // caller to release the resource. The callback of receive
822 // request are NOT executed. This is because it is most
823 // likely that the current user of the UDP IO port is closing
826 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
828 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
830 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
831 Status
= UdpIo
->Protocol
.Udp4
->Cancel (UdpIo
->Protocol
.Udp4
, &RxToken
->Token
.Udp4
);
832 if (EFI_ERROR (Status
)) {
838 // Close then destroy the Udp4 child
840 Status
= gBS
->CloseProtocol (
842 &gEfiUdp4ProtocolGuid
,
846 if (EFI_ERROR (Status
)) {
850 Status
= NetLibDestroyServiceChild (
853 &gEfiUdp4ServiceBindingProtocolGuid
,
856 if (EFI_ERROR (Status
)) {
862 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
863 Status
= UdpIo
->Protocol
.Udp6
->Cancel (UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
864 if (EFI_ERROR (Status
)) {
870 // Close then destroy the Udp6 child
872 Status
= gBS
->CloseProtocol (
874 &gEfiUdp6ProtocolGuid
,
878 if (EFI_ERROR (Status
)) {
882 Status
= NetLibDestroyServiceChild (
885 &gEfiUdp6ServiceBindingProtocolGuid
,
888 if (EFI_ERROR (Status
)) {
893 if (!IsListEmpty(&UdpIo
->Link
)) {
894 RemoveEntryList (&UdpIo
->Link
);
903 Clean up the UDP_IO without freeing it. The function is called when
904 user wants to re-use the UDP_IO later.
906 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().
908 It will release all the transmitted datagrams and receive request. It will
909 also configure NULL for the UDP instance.
911 @param[in] UdpIo The UDP_IO to clean up.
920 UDP_RX_TOKEN
*RxToken
;
922 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
923 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
926 // Cancel all the sent datagram and receive requests.
928 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
930 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
931 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
932 UdpIo
->Protocol
.Udp4
->Cancel (UdpIo
->Protocol
.Udp4
, &RxToken
->Token
.Udp4
);
935 UdpIo
->Protocol
.Udp4
->Configure (UdpIo
->Protocol
.Udp4
, NULL
);
938 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
939 UdpIo
->Protocol
.Udp6
->Cancel (UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
942 UdpIo
->Protocol
.Udp6
->Configure (UdpIo
->Protocol
.Udp6
, NULL
);
947 Send a packet through the UDP_IO.
949 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().
951 The packet will be wrapped in UDP_TX_TOKEN. Function Callback will be called
952 when the packet is sent. The optional parameter EndPoint overrides the default
953 address pair if specified.
955 @param[in] UdpIo The UDP_IO to send the packet through.
956 @param[in] Packet The packet to send.
957 @param[in] EndPoint The local and remote access point. Override the
958 default address pair set during configuration.
959 @param[in] Gateway The gateway to use.
960 @param[in] CallBack The function being called when packet is
961 transmitted or failed.
962 @param[in] Context The opaque parameter passed to CallBack.
964 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the packet.
965 @retval EFI_SUCCESS The packet is successfully delivered to UDP for
974 IN UDP_END_POINT
*EndPoint OPTIONAL
,
975 IN EFI_IP_ADDRESS
*Gateway OPTIONAL
,
976 IN UDP_IO_CALLBACK CallBack
,
980 UDP_TX_TOKEN
*TxToken
;
983 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
984 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
986 TxToken
= UdpIoCreateTxToken (UdpIo
, Packet
, EndPoint
, Gateway
, CallBack
, Context
);
988 if (TxToken
== NULL
) {
989 return EFI_OUT_OF_RESOURCES
;
993 // Insert the tx token into SendDatagram list before transmitting it. Remove
994 // it from the list if the returned status is not EFI_SUCCESS.
996 InsertHeadList (&UdpIo
->SentDatagram
, &TxToken
->Link
);
998 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
999 Status
= UdpIo
->Protocol
.Udp4
->Transmit (UdpIo
->Protocol
.Udp4
, &TxToken
->Token
.Udp4
);
1001 Status
= UdpIo
->Protocol
.Udp6
->Transmit (UdpIo
->Protocol
.Udp6
, &TxToken
->Token
.Udp6
);
1004 if (EFI_ERROR (Status
)) {
1005 RemoveEntryList (&TxToken
->Link
);
1006 UdpIoFreeTxToken (TxToken
);
1015 The select function to cancel a single sent datagram.
1017 @param[in] Token The UDP_TX_TOKEN to test against
1018 @param[in] Context The NET_BUF of the sent datagram
1020 @retval TRUE The packet is to be cancelled.
1021 @retval FALSE The packet is not to be cancelled.
1025 UdpIoCancelSingleDgram (
1026 IN UDP_TX_TOKEN
*Token
,
1032 Packet
= (NET_BUF
*) Context
;
1034 if (Token
->Packet
== Packet
) {
1042 Cancel a single sent datagram.
1044 @param[in] UdpIo The UDP_IO to cancel the packet from
1045 @param[in] Packet The packet to cancel
1050 UdpIoCancelSentDatagram (
1055 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, UdpIoCancelSingleDgram
, Packet
);
1059 Issue a receive request to the UDP_IO.
1061 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().
1063 This function is called when upper-layer needs packet from UDP for processing.
1064 Only one receive request is acceptable at a time so a common usage model is
1065 to invoke this function inside its Callback function when the former packet
1068 @param[in] UdpIo The UDP_IO to receive the packet from.
1069 @param[in] CallBack The call back function to execute when the packet
1071 @param[in] Context The opaque context passed to Callback.
1072 @param[in] HeadLen The length of the upper-layer's protocol header.
1074 @retval EFI_ALREADY_STARTED There is already a pending receive request. Only
1075 one receive request is supported at a time.
1076 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
1077 @retval EFI_SUCCESS The receive request is issued successfully.
1078 @retval EFI_UNSUPPORTED The UDP version in UDP_IO is not supported.
1085 IN UDP_IO_CALLBACK CallBack
,
1090 UDP_RX_TOKEN
*RxToken
;
1093 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
1094 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
1096 if (UdpIo
->RecvRequest
!= NULL
) {
1097 return EFI_ALREADY_STARTED
;
1100 RxToken
= UdpIoCreateRxToken (UdpIo
, CallBack
, Context
, HeadLen
);
1102 if (RxToken
== NULL
) {
1103 return EFI_OUT_OF_RESOURCES
;
1106 UdpIo
->RecvRequest
= RxToken
;
1107 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
1108 Status
= UdpIo
->Protocol
.Udp4
->Receive (UdpIo
->Protocol
.Udp4
, &RxToken
->Token
.Udp4
);
1110 Status
= UdpIo
->Protocol
.Udp6
->Receive (UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
1113 if (EFI_ERROR (Status
)) {
1114 UdpIo
->RecvRequest
= NULL
;
1115 UdpIoFreeRxToken (RxToken
);