2 Help functions to access UDP service, it is used by both the DHCP and MTFTP.
4 Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at<BR>
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Protocol/Udp4.h>
17 #include <Protocol/Udp6.h>
19 #include <Library/UdpIoLib.h>
20 #include <Library/BaseLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/MemoryAllocationLib.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/DpcLib.h>
29 Free a UDP_TX_TOKEN. The TX event is closed.
31 @param[in] TxToken The UDP_TX_TOKEN to release.
36 IN UDP_TX_TOKEN
*TxToken
40 if (TxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
41 gBS
->CloseEvent (TxToken
->Token
.Udp4
.Event
);
42 } else if (TxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
) {
43 gBS
->CloseEvent (TxToken
->Token
.Udp6
.Event
);
52 Free a UDP_RX_TOKEN. The RX event is closed.
54 @param[in] RxToken The UDP_RX_TOKEN to release.
59 IN UDP_RX_TOKEN
*RxToken
62 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
63 gBS
->CloseEvent (RxToken
->Token
.Udp4
.Event
);
64 } else if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
) {
65 gBS
->CloseEvent (RxToken
->Token
.Udp6
.Event
);
74 The callback function when the packet is sent by UDP.
76 It will remove the packet from the local list then call
77 the packet owner's callback function set by UdpIoSendDatagram.
79 @param[in] Context The UDP TX Token.
88 UDP_TX_TOKEN
*TxToken
;
90 TxToken
= (UDP_TX_TOKEN
*) Context
;
91 ASSERT (TxToken
->Signature
== UDP_IO_TX_SIGNATURE
);
92 ASSERT ((TxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
93 (TxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
95 RemoveEntryList (&TxToken
->Link
);
97 if (TxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
98 TxToken
->CallBack (TxToken
->Packet
, NULL
, TxToken
->Token
.Udp4
.Status
, TxToken
->Context
);
100 TxToken
->CallBack (TxToken
->Packet
, NULL
, TxToken
->Token
.Udp6
.Status
, TxToken
->Context
);
103 UdpIoFreeTxToken (TxToken
);
107 Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK.
109 @param[in] Event The event signaled.
110 @param[in] Context The UDP TX Token.
121 // Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK
123 QueueDpc (TPL_CALLBACK
, UdpIoOnDgramSentDpc
, Context
);
127 Recycle the received UDP data.
129 @param[in] Context The UDP_RX_TOKEN.
138 UDP_RX_TOKEN
*RxToken
;
140 RxToken
= (UDP_RX_TOKEN
*) Context
;
142 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
143 gBS
->SignalEvent (RxToken
->Token
.Udp4
.Packet
.RxData
->RecycleSignal
);
144 } else if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
) {
145 gBS
->SignalEvent (RxToken
->Token
.Udp6
.Packet
.RxData
->RecycleSignal
);
150 UdpIoFreeRxToken (RxToken
);
154 The event handle for UDP receive request.
156 It will build a NET_BUF from the recieved UDP data, then deliver it
159 @param[in] Context The UDP RX token.
164 UdpIoOnDgramRcvdDpc (
172 UDP_RX_TOKEN
*RxToken
;
173 UDP_END_POINT EndPoint
;
176 RxToken
= (UDP_RX_TOKEN
*) Context
;
178 ZeroMem (&EndPoint
, sizeof(UDP_END_POINT
));
180 ASSERT ((RxToken
->Signature
== UDP_IO_RX_SIGNATURE
) &&
181 (RxToken
== RxToken
->UdpIo
->RecvRequest
));
183 ASSERT ((RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
184 (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
187 // Clear the receive request first in case that the caller
188 // wants to restart the receive in the callback.
190 RxToken
->UdpIo
->RecvRequest
= NULL
;
192 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
193 Token
= &RxToken
->Token
.Udp4
;
194 RxData
= ((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Packet
.RxData
;
195 Status
= ((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Status
;
197 Token
= &RxToken
->Token
.Udp6
;
198 RxData
= ((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Packet
.RxData
;
199 Status
= ((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Status
;
202 if (EFI_ERROR (Status
) || RxData
== NULL
) {
203 if (Status
!= EFI_ABORTED
) {
205 // Invoke the CallBack only if the reception is not actively aborted.
207 RxToken
->CallBack (NULL
, NULL
, Status
, RxToken
->Context
);
210 UdpIoFreeRxToken (RxToken
);
215 // Build a NET_BUF from the UDP receive data, then deliver it up.
217 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
218 if (((EFI_UDP4_RECEIVE_DATA
*) RxData
)->DataLength
== 0) {
220 // Discard zero length data payload packet.
225 Netbuf
= NetbufFromExt (
226 (NET_FRAGMENT
*)((EFI_UDP4_RECEIVE_DATA
*) RxData
)->FragmentTable
,
227 ((EFI_UDP4_RECEIVE_DATA
*) RxData
)->FragmentCount
,
229 (UINT32
) RxToken
->HeadLen
,
234 if (Netbuf
== NULL
) {
235 gBS
->SignalEvent (((EFI_UDP4_RECEIVE_DATA
*) RxData
)->RecycleSignal
);
236 RxToken
->CallBack (NULL
, NULL
, EFI_OUT_OF_RESOURCES
, RxToken
->Context
);
238 UdpIoFreeRxToken (RxToken
);
242 Session
= &((EFI_UDP4_RECEIVE_DATA
*) RxData
)->UdpSession
;
243 EndPoint
.LocalPort
= ((EFI_UDP4_SESSION_DATA
*) Session
)->DestinationPort
;
244 EndPoint
.RemotePort
= ((EFI_UDP4_SESSION_DATA
*) Session
)->SourcePort
;
248 &((EFI_UDP4_SESSION_DATA
*) Session
)->DestinationAddress
,
249 sizeof (EFI_IPv4_ADDRESS
)
253 &EndPoint
.RemoteAddr
,
254 &((EFI_UDP4_SESSION_DATA
*) Session
)->SourceAddress
,
255 sizeof (EFI_IPv4_ADDRESS
)
258 EndPoint
.LocalAddr
.Addr
[0] = NTOHL (EndPoint
.LocalAddr
.Addr
[0]);
259 EndPoint
.RemoteAddr
.Addr
[0] = NTOHL (EndPoint
.RemoteAddr
.Addr
[0]);
261 if (((EFI_UDP6_RECEIVE_DATA
*) RxData
)->DataLength
== 0) {
263 // Discard zero length data payload packet.
268 Netbuf
= NetbufFromExt (
269 (NET_FRAGMENT
*)((EFI_UDP6_RECEIVE_DATA
*) RxData
)->FragmentTable
,
270 ((EFI_UDP6_RECEIVE_DATA
*) RxData
)->FragmentCount
,
272 (UINT32
) RxToken
->HeadLen
,
277 if (Netbuf
== NULL
) {
278 gBS
->SignalEvent (((EFI_UDP6_RECEIVE_DATA
*) RxData
)->RecycleSignal
);
279 RxToken
->CallBack (NULL
, NULL
, EFI_OUT_OF_RESOURCES
, RxToken
->Context
);
281 UdpIoFreeRxToken (RxToken
);
285 Session
= &((EFI_UDP6_RECEIVE_DATA
*) RxData
)->UdpSession
;
286 EndPoint
.LocalPort
= ((EFI_UDP6_SESSION_DATA
*) Session
)->DestinationPort
;
287 EndPoint
.RemotePort
= ((EFI_UDP6_SESSION_DATA
*) Session
)->SourcePort
;
291 &((EFI_UDP6_SESSION_DATA
*) Session
)->DestinationAddress
,
292 sizeof (EFI_IPv6_ADDRESS
)
296 &EndPoint
.RemoteAddr
,
297 &((EFI_UDP6_SESSION_DATA
*) Session
)->SourceAddress
,
298 sizeof (EFI_IPv6_ADDRESS
)
301 Ip6Swap128 (&EndPoint
.LocalAddr
.v6
);
302 Ip6Swap128 (&EndPoint
.RemoteAddr
.v6
);
305 RxToken
->CallBack (Netbuf
, &EndPoint
, EFI_SUCCESS
, RxToken
->Context
);
309 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
310 gBS
->SignalEvent (((EFI_UDP4_RECEIVE_DATA
*) RxData
)->RecycleSignal
);
311 RxToken
->UdpIo
->Protocol
.Udp4
->Receive (RxToken
->UdpIo
->Protocol
.Udp4
, &RxToken
->Token
.Udp4
);
313 gBS
->SignalEvent (((EFI_UDP6_RECEIVE_DATA
*) RxData
)->RecycleSignal
);
314 RxToken
->UdpIo
->Protocol
.Udp6
->Receive (RxToken
->UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
319 Request UdpIoOnDgramRcvdDpc() as a DPC at TPL_CALLBACK.
321 @param[in] Event The UDP receive request event.
322 @param[in] Context The UDP RX token.
333 // Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK
335 QueueDpc (TPL_CALLBACK
, UdpIoOnDgramRcvdDpc
, Context
);
339 Create a UDP_RX_TOKEN to wrap the request.
341 @param[in] UdpIo The UdpIo to receive packets from.
342 @param[in] CallBack The function to call when receive finished.
343 @param[in] Context The opaque parameter to the CallBack.
344 @param[in] HeadLen The head length to reserver for the packet.
346 @return The Wrapped request or NULL if failed to allocate resources or some errors happened.
352 IN UDP_IO_CALLBACK CallBack
,
360 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
361 (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
) {
377 Token
->Token
.Udp4
.Status
= EFI_NOT_READY
;
378 Token
->Token
.Udp4
.Packet
.RxData
= NULL
;
380 Status
= gBS
->CreateEvent (
385 &Token
->Token
.Udp4
.Event
389 Token
->Token
.Udp6
.Status
= EFI_NOT_READY
;
390 Token
->Token
.Udp6
.Packet
.RxData
= NULL
;
392 Status
= gBS
->CreateEvent (
397 &Token
->Token
.Udp6
.Event
402 if (EFI_ERROR (Status
)) {
411 Wrap a transmit request into a new created UDP_TX_TOKEN.
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 overrided 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
);
443 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
444 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
446 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
447 Size
= sizeof (UDP_TX_TOKEN
) + sizeof (EFI_UDP4_FRAGMENT_DATA
) * (Packet
->BlockOpNum
- 1);
449 Size
= sizeof (UDP_TX_TOKEN
) + sizeof (EFI_UDP6_FRAGMENT_DATA
) * (Packet
->BlockOpNum
- 1);
452 TxToken
= AllocatePool (Size
);
454 if (TxToken
== NULL
) {
458 TxToken
->Signature
= UDP_IO_TX_SIGNATURE
;
459 InitializeListHead (&TxToken
->Link
);
461 TxToken
->UdpIo
= UdpIo
;
462 TxToken
->CallBack
= CallBack
;
463 TxToken
->Packet
= Packet
;
464 TxToken
->Context
= Context
;
466 Token
= &(TxToken
->Token
);
467 Count
= Packet
->BlockOpNum
;
469 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
471 ((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Status
= EFI_NOT_READY
;
473 Status
= gBS
->CreateEvent (
478 &((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Event
481 if (EFI_ERROR (Status
)) {
486 Data
= &(TxToken
->Data
.Udp4
);
487 ((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Packet
.TxData
= Data
;
489 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->UdpSessionData
= NULL
;
490 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->GatewayAddress
= NULL
;
491 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->DataLength
= Packet
->TotalSize
;
495 (NET_FRAGMENT
*)((EFI_UDP4_TRANSMIT_DATA
*) Data
)->FragmentTable
,
499 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->FragmentCount
= Count
;
501 if (EndPoint
!= NULL
) {
502 Ip
= HTONL (EndPoint
->LocalAddr
.Addr
[0]);
504 &TxToken
->Session
.Udp4
.SourceAddress
,
506 sizeof (EFI_IPv4_ADDRESS
)
509 Ip
= HTONL (EndPoint
->RemoteAddr
.Addr
[0]);
511 &TxToken
->Session
.Udp4
.DestinationAddress
,
513 sizeof (EFI_IPv4_ADDRESS
)
516 TxToken
->Session
.Udp4
.SourcePort
= EndPoint
->LocalPort
;
517 TxToken
->Session
.Udp4
.DestinationPort
= EndPoint
->RemotePort
;
518 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->UdpSessionData
= &(TxToken
->Session
.Udp4
);
521 if (Gateway
!= NULL
&& (Gateway
->Addr
[0] != 0)) {
522 Ip
= HTONL (Gateway
->Addr
[0]);
523 CopyMem (&TxToken
->Gateway
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
524 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->GatewayAddress
= &TxToken
->Gateway
;
529 ((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Status
= EFI_NOT_READY
;
531 Status
= gBS
->CreateEvent (
536 &((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Event
539 if (EFI_ERROR (Status
)) {
544 Data
= &(TxToken
->Data
.Udp6
);
545 ((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Packet
.TxData
= Data
;
546 ((EFI_UDP6_TRANSMIT_DATA
*) Data
)->UdpSessionData
= NULL
;
547 ((EFI_UDP6_TRANSMIT_DATA
*) Data
)->DataLength
= Packet
->TotalSize
;
551 (NET_FRAGMENT
*)((EFI_UDP6_TRANSMIT_DATA
*) Data
)->FragmentTable
,
555 ((EFI_UDP6_TRANSMIT_DATA
*) Data
)->FragmentCount
= Count
;
557 if (EndPoint
!= NULL
) {
559 &TxToken
->Session
.Udp6
.SourceAddress
,
560 &EndPoint
->LocalAddr
.v6
,
561 sizeof(EFI_IPv6_ADDRESS
)
565 &TxToken
->Session
.Udp6
.DestinationAddress
,
566 &EndPoint
->RemoteAddr
.v6
,
567 sizeof(EFI_IPv6_ADDRESS
)
570 TxToken
->Session
.Udp6
.SourcePort
= EndPoint
->LocalPort
;
571 TxToken
->Session
.Udp6
.DestinationPort
= EndPoint
->RemotePort
;
572 ((EFI_UDP6_TRANSMIT_DATA
*) Data
)->UdpSessionData
= &(TxToken
->Session
.Udp6
);
580 Creates a UDP_IO to access the UDP service. It creates and configures
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 funtion.
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.
752 If ToCancel is NULL, all the datagrams are cancelled.
754 @param[in] UdpIo The UDP_IO to cancel packet.
755 @param[in] IoStatus The IoStatus to return to the packet owners.
756 @param[in] ToCancel The select funtion to test whether to cancel this
758 @param[in] Context The opaque parameter to the ToCancel.
765 IN EFI_STATUS IoStatus
,
766 IN UDP_IO_TO_CANCEL ToCancel
, OPTIONAL
772 UDP_TX_TOKEN
*TxToken
;
774 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
775 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
777 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &UdpIo
->SentDatagram
) {
778 TxToken
= NET_LIST_USER_STRUCT (Entry
, UDP_TX_TOKEN
, Link
);
780 if ((ToCancel
== NULL
) || (ToCancel (TxToken
, Context
))) {
782 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
783 UdpIo
->Protocol
.Udp4
->Cancel (UdpIo
->Protocol
.Udp4
, &TxToken
->Token
.Udp4
);
785 UdpIo
->Protocol
.Udp6
->Cancel (UdpIo
->Protocol
.Udp6
, &TxToken
->Token
.Udp6
);
792 Free the UDP_IO and all its related resources.
794 The function will cancel all sent datagram and receive request.
796 @param[in] UdpIo The UDP_IO to free.
798 @retval EFI_SUCCESS The UDP_IO is freed.
807 UDP_RX_TOKEN
*RxToken
;
809 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
810 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
813 // Cancel all the sent datagram and receive requests. The
814 // callbacks of transmit requests are executed to allow the
815 // caller to release the resource. The callback of receive
816 // request are NOT executed. This is because it is most
817 // likely that the current user of the UDP IO port is closing
820 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
822 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
824 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
825 UdpIo
->Protocol
.Udp4
->Cancel (UdpIo
->Protocol
.Udp4
, &RxToken
->Token
.Udp4
);
829 // Close then destroy the Udp4 child
833 &gEfiUdp4ProtocolGuid
,
838 NetLibDestroyServiceChild (
841 &gEfiUdp4ServiceBindingProtocolGuid
,
847 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
848 UdpIo
->Protocol
.Udp6
->Cancel (UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
852 // Close then destroy the Udp6 child
856 &gEfiUdp6ProtocolGuid
,
861 NetLibDestroyServiceChild (
864 &gEfiUdp6ServiceBindingProtocolGuid
,
869 if (!IsListEmpty(&UdpIo
->Link
)) {
870 RemoveEntryList (&UdpIo
->Link
);
879 Clean up the UDP_IO without freeing it. The function is called when
880 user wants to re-use the UDP_IO later.
882 It will release all the transmitted datagrams and receive request. It will
883 also configure NULL for the UDP instance.
885 @param[in] UdpIo The UDP_IO to clean up.
894 UDP_RX_TOKEN
*RxToken
;
896 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
897 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
900 // Cancel all the sent datagram and receive requests.
902 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
904 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
905 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
906 UdpIo
->Protocol
.Udp4
->Cancel (UdpIo
->Protocol
.Udp4
, &RxToken
->Token
.Udp4
);
909 UdpIo
->Protocol
.Udp4
->Configure (UdpIo
->Protocol
.Udp4
, NULL
);
912 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
913 UdpIo
->Protocol
.Udp6
->Cancel (UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
916 UdpIo
->Protocol
.Udp6
->Configure (UdpIo
->Protocol
.Udp6
, NULL
);
921 Send a packet through the UDP_IO.
923 The packet will be wrapped in UDP_TX_TOKEN. Function Callback will be called
924 when the packet is sent. The optional parameter EndPoint overrides the default
925 address pair if specified.
927 @param[in] UdpIo The UDP_IO to send the packet through.
928 @param[in] Packet The packet to send.
929 @param[in] EndPoint The local and remote access point. Override the
930 default address pair set during configuration.
931 @param[in] Gateway The gateway to use.
932 @param[in] CallBack The function being called when packet is
933 transmitted or failed.
934 @param[in] Context The opaque parameter passed to CallBack.
936 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the packet.
937 @retval EFI_SUCCESS The packet is successfully delivered to UDP for
946 IN UDP_END_POINT
*EndPoint OPTIONAL
,
947 IN EFI_IP_ADDRESS
*Gateway OPTIONAL
,
948 IN UDP_IO_CALLBACK CallBack
,
952 UDP_TX_TOKEN
*TxToken
;
955 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
956 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
958 TxToken
= UdpIoCreateTxToken (UdpIo
, Packet
, EndPoint
, Gateway
, CallBack
, Context
);
960 if (TxToken
== NULL
) {
961 return EFI_OUT_OF_RESOURCES
;
965 // Insert the tx token into SendDatagram list before transmitting it. Remove
966 // it from the list if the returned status is not EFI_SUCCESS.
968 InsertHeadList (&UdpIo
->SentDatagram
, &TxToken
->Link
);
970 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
971 Status
= UdpIo
->Protocol
.Udp4
->Transmit (UdpIo
->Protocol
.Udp4
, &TxToken
->Token
.Udp4
);
973 Status
= UdpIo
->Protocol
.Udp6
->Transmit (UdpIo
->Protocol
.Udp6
, &TxToken
->Token
.Udp6
);
976 if (EFI_ERROR (Status
)) {
977 RemoveEntryList (&TxToken
->Link
);
978 UdpIoFreeTxToken (TxToken
);
987 The select function to cancel a single sent datagram.
989 @param[in] Token The UDP_TX_TOKEN to test against
990 @param[in] Context The NET_BUF of the sent datagram
992 @retval TRUE The packet is to be cancelled.
993 @retval FALSE The packet is not to be cancelled.
997 UdpIoCancelSingleDgram (
998 IN UDP_TX_TOKEN
*Token
,
1004 Packet
= (NET_BUF
*) Context
;
1006 if (Token
->Packet
== Packet
) {
1014 Cancel a single sent datagram.
1016 @param[in] UdpIo The UDP_IO to cancel the packet from
1017 @param[in] Packet The packet to cancel
1022 UdpIoCancelSentDatagram (
1027 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, UdpIoCancelSingleDgram
, Packet
);
1031 Issue a receive request to the UDP_IO.
1033 This function is called when upper-layer needs packet from UDP for processing.
1034 Only one receive request is acceptable at a time so a common usage model is
1035 to invoke this function inside its Callback function when the former packet
1038 @param[in] UdpIo The UDP_IO to receive the packet from.
1039 @param[in] CallBack The call back function to execute when the packet
1041 @param[in] Context The opaque context passed to Callback.
1042 @param[in] HeadLen The length of the upper-layer's protocol header.
1044 @retval EFI_ALREADY_STARTED There is already a pending receive request. Only
1045 one receive request is supported at a time.
1046 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
1047 @retval EFI_SUCCESS The receive request is issued successfully.
1048 @retval EFI_UNSUPPORTED The UDP version in UDP_IO is not supported.
1055 IN UDP_IO_CALLBACK CallBack
,
1060 UDP_RX_TOKEN
*RxToken
;
1063 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
1064 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
1066 if (UdpIo
->RecvRequest
!= NULL
) {
1067 return EFI_ALREADY_STARTED
;
1070 RxToken
= UdpIoCreateRxToken (UdpIo
, CallBack
, Context
, HeadLen
);
1072 if (RxToken
== NULL
) {
1073 return EFI_OUT_OF_RESOURCES
;
1076 UdpIo
->RecvRequest
= RxToken
;
1077 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
1078 Status
= UdpIo
->Protocol
.Udp4
->Receive (UdpIo
->Protocol
.Udp4
, &RxToken
->Token
.Udp4
);
1080 Status
= UdpIo
->Protocol
.Udp6
->Receive (UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
1083 if (EFI_ERROR (Status
)) {
1084 UdpIo
->RecvRequest
= NULL
;
1085 UdpIoFreeRxToken (RxToken
);