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>
22 Free a UDP_TX_TOKEN. The TX event is closed.
24 @param[in] TxToken The UDP_TX_TOKEN to release.
29 IN UDP_TX_TOKEN
*TxToken
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
);
44 Free a UDP_RX_TOKEN. The RX event is closed.
46 @param[in] RxToken The UDP_RX_TOKEN to release.
51 IN UDP_RX_TOKEN
*RxToken
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
);
66 The callback function when the packet is sent by UDP.
68 It will remove the packet from the local list then call
69 the packet owner's callback function set by UdpIoSendDatagram.
71 @param[in] Context The UDP TX Token.
80 UDP_TX_TOKEN
*TxToken
;
82 TxToken
= (UDP_TX_TOKEN
*)Context
;
83 ASSERT (TxToken
->Signature
== UDP_IO_TX_SIGNATURE
);
85 (TxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
86 (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
));
175 (RxToken
->Signature
== UDP_IO_RX_SIGNATURE
) &&
176 (RxToken
== RxToken
->UdpIo
->RecvRequest
)
180 (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
181 (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
)
185 // Clear the receive request first in case that the caller
186 // wants to restart the receive in the callback.
188 RxToken
->UdpIo
->RecvRequest
= NULL
;
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
;
195 Token
= &RxToken
->Token
.Udp6
;
196 RxData
= ((EFI_UDP6_COMPLETION_TOKEN
*)Token
)->Packet
.RxData
;
197 Status
= ((EFI_UDP6_COMPLETION_TOKEN
*)Token
)->Status
;
200 if (EFI_ERROR (Status
) || (RxData
== NULL
)) {
201 if (Status
!= EFI_ABORTED
) {
203 // Invoke the CallBack only if the reception is not actively aborted.
205 RxToken
->CallBack (NULL
, NULL
, Status
, RxToken
->Context
);
208 UdpIoFreeRxToken (RxToken
);
213 // Build a NET_BUF from the UDP receive data, then deliver it up.
215 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
216 if (((EFI_UDP4_RECEIVE_DATA
*)RxData
)->DataLength
== 0) {
218 // Discard zero length data payload packet.
223 Netbuf
= NetbufFromExt (
224 (NET_FRAGMENT
*)((EFI_UDP4_RECEIVE_DATA
*)RxData
)->FragmentTable
,
225 ((EFI_UDP4_RECEIVE_DATA
*)RxData
)->FragmentCount
,
227 (UINT32
)RxToken
->HeadLen
,
232 if (Netbuf
== NULL
) {
233 gBS
->SignalEvent (((EFI_UDP4_RECEIVE_DATA
*)RxData
)->RecycleSignal
);
234 RxToken
->CallBack (NULL
, NULL
, EFI_OUT_OF_RESOURCES
, RxToken
->Context
);
236 UdpIoFreeRxToken (RxToken
);
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
;
246 &((EFI_UDP4_SESSION_DATA
*)Session
)->DestinationAddress
,
247 sizeof (EFI_IPv4_ADDRESS
)
251 &EndPoint
.RemoteAddr
,
252 &((EFI_UDP4_SESSION_DATA
*)Session
)->SourceAddress
,
253 sizeof (EFI_IPv4_ADDRESS
)
256 EndPoint
.LocalAddr
.Addr
[0] = NTOHL (EndPoint
.LocalAddr
.Addr
[0]);
257 EndPoint
.RemoteAddr
.Addr
[0] = NTOHL (EndPoint
.RemoteAddr
.Addr
[0]);
259 if (((EFI_UDP6_RECEIVE_DATA
*)RxData
)->DataLength
== 0) {
261 // Discard zero length data payload packet.
266 Netbuf
= NetbufFromExt (
267 (NET_FRAGMENT
*)((EFI_UDP6_RECEIVE_DATA
*)RxData
)->FragmentTable
,
268 ((EFI_UDP6_RECEIVE_DATA
*)RxData
)->FragmentCount
,
270 (UINT32
)RxToken
->HeadLen
,
275 if (Netbuf
== NULL
) {
276 gBS
->SignalEvent (((EFI_UDP6_RECEIVE_DATA
*)RxData
)->RecycleSignal
);
277 RxToken
->CallBack (NULL
, NULL
, EFI_OUT_OF_RESOURCES
, RxToken
->Context
);
279 UdpIoFreeRxToken (RxToken
);
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
;
289 &((EFI_UDP6_SESSION_DATA
*)Session
)->DestinationAddress
,
290 sizeof (EFI_IPv6_ADDRESS
)
294 &EndPoint
.RemoteAddr
,
295 &((EFI_UDP6_SESSION_DATA
*)Session
)->SourceAddress
,
296 sizeof (EFI_IPv6_ADDRESS
)
299 Ip6Swap128 (&EndPoint
.LocalAddr
.v6
);
300 Ip6Swap128 (&EndPoint
.RemoteAddr
.v6
);
303 RxToken
->CallBack (Netbuf
, &EndPoint
, EFI_SUCCESS
, RxToken
->Context
);
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
);
311 gBS
->SignalEvent (((EFI_UDP6_RECEIVE_DATA
*)RxData
)->RecycleSignal
);
312 RxToken
->UdpIo
->Protocol
.Udp6
->Receive (RxToken
->UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
317 Request UdpIoOnDgramRcvdDpc() as a DPC at TPL_CALLBACK.
319 @param[in] Event The UDP receive request event.
320 @param[in] Context The UDP RX token.
331 // Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK
333 QueueDpc (TPL_CALLBACK
, UdpIoOnDgramRcvdDpc
, Context
);
337 Create a UDP_RX_TOKEN to wrap the request.
339 @param[in] UdpIo The UdpIo to receive packets from.
340 @param[in] CallBack The function to call when receive finished.
341 @param[in] Context The opaque parameter to the CallBack.
342 @param[in] HeadLen The head length to reserve for the packet.
344 @return The Wrapped request or NULL if failed to allocate resources or some errors happened.
350 IN UDP_IO_CALLBACK CallBack
,
359 (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
360 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
)
363 Token
= AllocatePool (sizeof (UDP_RX_TOKEN
));
369 Token
->Signature
= UDP_IO_RX_SIGNATURE
;
370 Token
->UdpIo
= UdpIo
;
371 Token
->CallBack
= CallBack
;
372 Token
->Context
= Context
;
373 Token
->HeadLen
= HeadLen
;
375 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
376 Token
->Token
.Udp4
.Status
= EFI_NOT_READY
;
377 Token
->Token
.Udp4
.Packet
.RxData
= NULL
;
379 Status
= gBS
->CreateEvent (
384 &Token
->Token
.Udp4
.Event
387 Token
->Token
.Udp6
.Status
= EFI_NOT_READY
;
388 Token
->Token
.Udp6
.Packet
.RxData
= NULL
;
390 Status
= gBS
->CreateEvent (
395 &Token
->Token
.Udp6
.Event
399 if (EFI_ERROR (Status
)) {
408 Wrap a transmit request into a new created UDP_TX_TOKEN.
410 If Packet is NULL, then ASSERT().
411 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().
413 @param[in] UdpIo The UdpIo to send packet to.
414 @param[in] Packet The user's packet.
415 @param[in] EndPoint The local and remote access point.
416 @param[in] Gateway The overridden next hop.
417 @param[in] CallBack The function to call when transmission completed.
418 @param[in] Context The opaque parameter to the call back.
420 @return The wrapped transmission request or NULL if failed to allocate resources
428 IN UDP_END_POINT
*EndPoint OPTIONAL
,
429 IN EFI_IP_ADDRESS
*Gateway OPTIONAL
,
430 IN UDP_IO_CALLBACK CallBack
,
434 UDP_TX_TOKEN
*TxToken
;
442 ASSERT (Packet
!= NULL
);
444 (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
445 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
)
448 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
449 Size
= sizeof (UDP_TX_TOKEN
) + sizeof (EFI_UDP4_FRAGMENT_DATA
) * (Packet
->BlockOpNum
- 1);
451 Size
= sizeof (UDP_TX_TOKEN
) + sizeof (EFI_UDP6_FRAGMENT_DATA
) * (Packet
->BlockOpNum
- 1);
454 TxToken
= AllocatePool (Size
);
456 if (TxToken
== NULL
) {
460 TxToken
->Signature
= UDP_IO_TX_SIGNATURE
;
461 InitializeListHead (&TxToken
->Link
);
463 TxToken
->UdpIo
= UdpIo
;
464 TxToken
->CallBack
= CallBack
;
465 TxToken
->Packet
= Packet
;
466 TxToken
->Context
= Context
;
468 Token
= &(TxToken
->Token
);
469 Count
= Packet
->BlockOpNum
;
471 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
472 ((EFI_UDP4_COMPLETION_TOKEN
*)Token
)->Status
= EFI_NOT_READY
;
474 Status
= gBS
->CreateEvent (
479 &((EFI_UDP4_COMPLETION_TOKEN
*)Token
)->Event
482 if (EFI_ERROR (Status
)) {
487 Data
= &(TxToken
->Data
.Udp4
);
488 ((EFI_UDP4_COMPLETION_TOKEN
*)Token
)->Packet
.TxData
= Data
;
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
;
496 (NET_FRAGMENT
*)((EFI_UDP4_TRANSMIT_DATA
*)Data
)->FragmentTable
,
500 ((EFI_UDP4_TRANSMIT_DATA
*)Data
)->FragmentCount
= Count
;
502 if (EndPoint
!= NULL
) {
503 Ip
= HTONL (EndPoint
->LocalAddr
.Addr
[0]);
505 &TxToken
->Session
.Udp4
.SourceAddress
,
507 sizeof (EFI_IPv4_ADDRESS
)
510 Ip
= HTONL (EndPoint
->RemoteAddr
.Addr
[0]);
512 &TxToken
->Session
.Udp4
.DestinationAddress
,
514 sizeof (EFI_IPv4_ADDRESS
)
517 TxToken
->Session
.Udp4
.SourcePort
= EndPoint
->LocalPort
;
518 TxToken
->Session
.Udp4
.DestinationPort
= EndPoint
->RemotePort
;
519 ((EFI_UDP4_TRANSMIT_DATA
*)Data
)->UdpSessionData
= &(TxToken
->Session
.Udp4
);
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
;
528 ((EFI_UDP6_COMPLETION_TOKEN
*)Token
)->Status
= EFI_NOT_READY
;
530 Status
= gBS
->CreateEvent (
535 &((EFI_UDP6_COMPLETION_TOKEN
*)Token
)->Event
538 if (EFI_ERROR (Status
)) {
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
;
550 (NET_FRAGMENT
*)((EFI_UDP6_TRANSMIT_DATA
*)Data
)->FragmentTable
,
554 ((EFI_UDP6_TRANSMIT_DATA
*)Data
)->FragmentCount
= Count
;
556 if (EndPoint
!= NULL
) {
558 &TxToken
->Session
.Udp6
.SourceAddress
,
559 &EndPoint
->LocalAddr
.v6
,
560 sizeof (EFI_IPv6_ADDRESS
)
564 &TxToken
->Session
.Udp6
.DestinationAddress
,
565 &EndPoint
->RemoteAddr
.v6
,
566 sizeof (EFI_IPv6_ADDRESS
)
569 TxToken
->Session
.Udp6
.SourcePort
= EndPoint
->LocalPort
;
570 TxToken
->Session
.Udp6
.DestinationPort
= EndPoint
->RemotePort
;
571 ((EFI_UDP6_TRANSMIT_DATA
*)Data
)->UdpSessionData
= &(TxToken
->Session
.Udp6
);
579 Creates a UDP_IO to access the UDP service. It creates and configures
582 If Configure is NULL, then ASSERT().
583 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().
585 It locates the UDP service binding prototype on the Controller parameter
586 uses the UDP service binding prototype to create a UDP child (also known as
587 a UDP instance) configures the UDP child by calling Configure function prototype.
588 Any failures in creating or configuring the UDP child return NULL for failure.
590 @param[in] Controller The controller that has the UDP service binding.
592 @param[in] ImageHandle The image handle for the driver.
593 @param[in] Configure The function to configure the created UDP child.
594 @param[in] UdpVersion The UDP protocol version, UDP4 or UDP6.
595 @param[in] Context The opaque parameter for the Configure function.
597 @return Newly-created UDP_IO or NULL if failed.
603 IN EFI_HANDLE Controller
,
604 IN EFI_HANDLE ImageHandle
,
605 IN UDP_IO_CONFIG Configure
,
613 ASSERT (Configure
!= NULL
);
614 ASSERT ((UdpVersion
== UDP_IO_UDP4_VERSION
) || (UdpVersion
== UDP_IO_UDP6_VERSION
));
616 UdpIo
= AllocatePool (sizeof (UDP_IO
));
622 UdpIo
->UdpVersion
= UdpVersion
;
623 UdpIo
->Signature
= UDP_IO_SIGNATURE
;
624 InitializeListHead (&UdpIo
->Link
);
627 UdpIo
->Controller
= Controller
;
628 UdpIo
->Image
= ImageHandle
;
630 InitializeListHead (&UdpIo
->SentDatagram
);
631 UdpIo
->RecvRequest
= NULL
;
632 UdpIo
->UdpHandle
= NULL
;
634 if (UdpVersion
== UDP_IO_UDP4_VERSION
) {
636 // Create a UDP child then open and configure it
638 Status
= NetLibCreateServiceChild (
641 &gEfiUdp4ServiceBindingProtocolGuid
,
645 if (EFI_ERROR (Status
)) {
649 Status
= gBS
->OpenProtocol (
651 &gEfiUdp4ProtocolGuid
,
652 (VOID
**)&UdpIo
->Protocol
.Udp4
,
655 EFI_OPEN_PROTOCOL_BY_DRIVER
658 if (EFI_ERROR (Status
)) {
662 if (EFI_ERROR (Configure (UdpIo
, Context
))) {
666 Status
= UdpIo
->Protocol
.Udp4
->GetModeData (
667 UdpIo
->Protocol
.Udp4
,
674 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
;
777 (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
778 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
)
781 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &UdpIo
->SentDatagram
) {
782 TxToken
= NET_LIST_USER_STRUCT (Entry
, UDP_TX_TOKEN
, Link
);
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
);
788 UdpIo
->Protocol
.Udp6
->Cancel (UdpIo
->Protocol
.Udp6
, &TxToken
->Token
.Udp6
);
795 Free the UDP_IO and all its related resources.
797 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().
799 The function will cancel all sent datagram and receive request.
801 @param[in] UdpIo The UDP_IO to free.
803 @retval EFI_SUCCESS The UDP_IO is freed.
804 @retval Others Failed to free UDP_IO.
814 UDP_RX_TOKEN
*RxToken
;
817 (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
818 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
)
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
829 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
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
)) {
840 // Close then destroy the Udp4 child
842 Status
= gBS
->CloseProtocol (
844 &gEfiUdp4ProtocolGuid
,
848 if (EFI_ERROR (Status
)) {
852 Status
= NetLibDestroyServiceChild (
855 &gEfiUdp4ServiceBindingProtocolGuid
,
858 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
);
902 Clean up the UDP_IO without freeing it. The function is called when
903 user wants to re-use the UDP_IO later.
905 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().
907 It will release all the transmitted datagrams and receive request. It will
908 also configure NULL for the UDP instance.
910 @param[in] UdpIo The UDP_IO to clean up.
919 UDP_RX_TOKEN
*RxToken
;
922 (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
923 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
)
927 // Cancel all the sent datagram and receive requests.
929 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
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
);
936 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
;
984 (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
985 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
)
988 TxToken
= UdpIoCreateTxToken (UdpIo
, Packet
, EndPoint
, Gateway
, CallBack
, Context
);
990 if (TxToken
== NULL
) {
991 return EFI_OUT_OF_RESOURCES
;
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.
998 InsertHeadList (&UdpIo
->SentDatagram
, &TxToken
->Link
);
1000 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
1001 Status
= UdpIo
->Protocol
.Udp4
->Transmit (UdpIo
->Protocol
.Udp4
, &TxToken
->Token
.Udp4
);
1003 Status
= UdpIo
->Protocol
.Udp6
->Transmit (UdpIo
->Protocol
.Udp6
, &TxToken
->Token
.Udp6
);
1006 if (EFI_ERROR (Status
)) {
1007 RemoveEntryList (&TxToken
->Link
);
1008 UdpIoFreeTxToken (TxToken
);
1016 The select function to cancel a single sent datagram.
1018 @param[in] Token The UDP_TX_TOKEN to test against
1019 @param[in] Context The NET_BUF of the sent datagram
1021 @retval TRUE The packet is to be cancelled.
1022 @retval FALSE The packet is not to be cancelled.
1026 UdpIoCancelSingleDgram (
1027 IN UDP_TX_TOKEN
*Token
,
1033 Packet
= (NET_BUF
*)Context
;
1035 if (Token
->Packet
== Packet
) {
1043 Cancel a single sent datagram.
1045 @param[in] UdpIo The UDP_IO to cancel the packet from
1046 @param[in] Packet The packet to cancel
1051 UdpIoCancelSentDatagram (
1056 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, UdpIoCancelSingleDgram
, Packet
);
1060 Issue a receive request to the UDP_IO.
1062 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().
1064 This function is called when upper-layer needs packet from UDP for processing.
1065 Only one receive request is acceptable at a time so a common usage model is
1066 to invoke this function inside its Callback function when the former packet
1069 @param[in] UdpIo The UDP_IO to receive the packet from.
1070 @param[in] CallBack The call back function to execute when the packet
1072 @param[in] Context The opaque context passed to Callback.
1073 @param[in] HeadLen The length of the upper-layer's protocol header.
1075 @retval EFI_ALREADY_STARTED There is already a pending receive request. Only
1076 one receive request is supported at a time.
1077 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
1078 @retval EFI_SUCCESS The receive request is issued successfully.
1079 @retval EFI_UNSUPPORTED The UDP version in UDP_IO is not supported.
1086 IN UDP_IO_CALLBACK CallBack
,
1091 UDP_RX_TOKEN
*RxToken
;
1095 (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
1096 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
)
1099 if (UdpIo
->RecvRequest
!= NULL
) {
1100 return EFI_ALREADY_STARTED
;
1103 RxToken
= UdpIoCreateRxToken (UdpIo
, CallBack
, Context
, HeadLen
);
1105 if (RxToken
== NULL
) {
1106 return EFI_OUT_OF_RESOURCES
;
1109 UdpIo
->RecvRequest
= RxToken
;
1110 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
1111 Status
= UdpIo
->Protocol
.Udp4
->Receive (UdpIo
->Protocol
.Udp4
, &RxToken
->Token
.Udp4
);
1113 Status
= UdpIo
->Protocol
.Udp6
->Receive (UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
1116 if (EFI_ERROR (Status
)) {
1117 UdpIo
->RecvRequest
= NULL
;
1118 UdpIoFreeRxToken (RxToken
);